65

How do you test redirect_to :back in rspec?

I get

ActionController::RedirectBackError:
No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].

How do I go about setting the HTTP_REFERER in my test?

ndnenkov
  • 35,425
  • 9
  • 72
  • 104
Cyrus
  • 3,687
  • 5
  • 35
  • 67
  • It might be useful to see the test source itself. This might be symptomatic of another issue... – jaydel May 18 '11 at 13:44
  • I was able to alleviate this error by calling 'visit root_path' first. But I think I can only do that in an integration test. Is that right? – Cyrus May 19 '11 at 18:09

6 Answers6

119

Using RSpec, you can set the referer in a before block. When I tried to set the referer directly in the test, it didn't seem to work no matter where I put it, but the before block does the trick.

describe BackController < ApplicationController do
  before(:each) do
    request.env["HTTP_REFERER"] = "where_i_came_from"
  end

  describe "GET /goback" do
    it "redirects back to the referring page" do
      get 'goback'
      response.should redirect_to "where_i_came_from"
    end
  end
end
jrh
  • 4,101
  • 2
  • 22
  • 27
  • 4
    I found it was a good idea to use: `request.env["HTTP_REFERER"] = "where_i_came_from" unless request.nil? or request.env.nil?` – jcollum Jan 13 '12 at 20:08
  • yeah. for me it is always nil and it is just not working. Looks like a huge bug to me. – Robert Reiz Aug 08 '13 at 11:35
  • 1
    It may have been updated to fix this issue since this answer was created, but I'm able to successfully set `request.env["HTTP_REFERER"]` in my test without using a `before` block. – Nick Apr 13 '16 at 15:48
4

From the rails guide when requesting the request with the new request style:

describe BackController < ApplicationController do
  describe "GET /goback" do
    it "redirects back to the referring page" do
      get :show, 
        params: { id: 12 },
        headers: { "HTTP_REFERER" => "http://example.com/home" }
      expect(response).to redirect_to("http://example.com/home")
    end
  end
end
ivanxuu
  • 842
  • 9
  • 10
4

If someone stumbles upon this and they're using request specs, you'll need to explicitly set the headers on the request you're making. The format of the test request depends on which version of RSpec you're using and if you can use keyword arguments instead of positional arguments.

let(:headers){ { "HTTP_REFERER" => "/widgets" } }

it "redirects back to widgets" do 
  post "/widgets", params: {}, headers: headers # keyword (better)
  post "/widgets", {}, headers                  # positional

  expect(response).to redirect_to(widgets_path)
end

https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec

sp89
  • 408
  • 4
  • 9
3

IMHO the accepted answer is a bit hacky. A better alternative would be to set the HTTP_REFERER to an actual url in your application and then expect to be redirected back:

describe BackController, type: :controller do
  before(:each) do
    request.env['HTTP_REFERER'] = root_url
  end

  it 'redirects back' do
    get :whatever
    response.should redirect_to :back
  end
end
  • Redirecting to a random string constant feels as if it works by accident
  • You take advantage of rspec's built in functionality to express exactly what you wanted
  • You don't introduce and repeat magic string values

For newer versions of rspec, you can use expectations instead:

expect(response).to redirect_to :back
ndnenkov
  • 35,425
  • 9
  • 72
  • 104
1

In regard to testing :back links in integration tests, I first visit a deadend page, that I think is not likely to be ever used as a link, and then the page I am testing. So my code looks like this

   before(:each) do
       visit deadend_path
       visit testpage_path
    end
    it "testpage Page should have a Back button going :back" do
      response.should have_selector("a",:href => deadend_path,
                                        :content => "Back")
    end

However this does have the flaw that if the link is really to the deadend_path, then the test will incorrectly pass.

Obromios
  • 15,408
  • 15
  • 72
  • 127
-2
request.env['HTTP_REFERER'] = '/your_referring_url'
Undo
  • 25,519
  • 37
  • 106
  • 129
Rahil Sondhi
  • 656
  • 6
  • 7