Pergunta

Does anyone know how to make rspec follow a redirect (in a controller spec)? (e.g test/unit has follow_redirect!)

I have tried "follow_redirect!" and "follow_redirect" but only get

undefined method `follow_redirect!' for #<Spec::Rails::Example::ControllerExampleGroup::Subclass_1:0xb6df5294>

For example:
When I create an account the page is redirected to accounts page and my new account should be at the top of the list.

it "should create an account" do
  post :create, :name => "My New Account"
  FOLLOW_REDIRECT!
  response.code.should == "200"
  accounts = assigns[:accounts]
  accounts[0].name.should == "My New Account"
end

But FOLLOW_REDIRECT! needs to be changed to something that actually works.

Foi útil?

Solução

If you want to test the redirect you are moving outside of the rspec-rails domain.

You can use Webrat or some other integration-test framework to test this.

The easiest way to solve this without resorting to integration testing is probably to mock out the method that is causing the redirect.

Outras dicas

I think this is the default behavior for rspec-rails controller tests, in the sense that you can set an expectation on the response status and/or path, and test for success.

For example:

it "should create an account" do
  post :create
  response.code.should == "302"
  response.should redirect_to(accounts_path)
end

You can access the redirect location with

response.headers['Location']

you could then request that directly.

Try to use integration/request tests. They are using web-like acces through routing to controllers. For example: I have for Rails 2 app in file /spec/integration/fps_spec.rb

 require 'spec_helper'

 describe "FinPoradci" do 

   it "POST /fps.html with params" do
     fp_params={:accord_id => "FP99998", :under_acc => "OM001", :first_name => "Pavel", :last_name => "Novy"}
     fp_test=FinPoradce.new(fp_params)
     #after create follow redirection to show
     post_via_redirect "/fps", {:fp => fp_params}
     response.response_code.should == 200 # => :found ,  not 302 :created
     new_fp=assigns(:fp)
     new_fp.should_not be_empty
     new_fp.errors.should be_empty
     flash[:error].should be_empty
     flash[:notice].should_not be_empty
     response.should render_template(:show)
   end
 end

and it works. Until you want to send headers (for basic http authorization).

 env={'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user,password)}
 post_via_redirect "/fps", {:fp => fp_params}, env

is fine for create, but after redirection it returns 401 and needs new authorization. SO I have to split it in 2 tests: creation and show on result of creation.

The spec is out of scope, if you want to follow a redirect use request spec, the equivalent of integration test in Test::Unit.

In request specs follow_redirect! works as well as in Test::Unit.

Or if you want to redirect inmediately use _via_redirect as suffix for the verb, example:

post_via_redirect :create, user: @user

For RSpec / Capybara + Rails

response_headers['Location']

But it works only if there is no delay before redirect. If it is there, then it's harder to follow the logic.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top