Search code examples
ruby-on-rails-3rspec2rspec-rails

'redirect_to root_path' does not appear as a redirect in RSpec integration test


I have a rails app with the following routes

root :to => "pages#home"
scope "/:locale" do
  root :to => "pages#home"
  ...
  match "/sign_in" => "sessions#new"
  resources :sessions, :only => [:new, :create]
end

My ApplicationController contains a default_url_options() that automatically sets the locale option

My SessionsController contains the following

class SessionsController < ApplicationController
  def new
  end

  def create
    redirect_to root_path
  end
end

So there there is not yet any logic, just a redirect. When I run the application in a browser, go to the sign in page, submit the form (which posts to /en/sessions), then it works as expected: I am redirected to /en

The integration test however fails to recognize the redirect

describe "sign-in" do
  before(:each) do
    visit "/en/sign_in"
    @user = Factory.create(:user)
  end

  context "with valid attributes" do
    before(:each) do
      fill_in "email", :with => @user.email
      fill_in "password", :with => @user.password
    end

    it "should redirect to root" do
      click_button "Sign in"
      response.should be_redirect
      response.should redirect_to "/en"
    end
  end
end

The test fails with the message

5) Authentication sign-in with valid attributes should redirect to root
   Failure/Error: response.should be_redirect
     expected redirect? to return true, got false

So even though the application redirects correctly, RSpec does not see the response as a redirect.

If I, just for the fun of it, change the implementation of create to

def create
  redirect_to new_user_path
end

Then I get the error message

6) SessionsController POST 'create' with valid user should redirect to root
   Failure/Error: response.should redirect_to root_path
     Expected response to be a redirect to <http://test.host/en> but was a redirect to <http://test.host/en/users/new>

Which is of course the expected error message as the function is now redirecting to the wrong url. But why is it that new_user_path results in a redirect that RSpec sees as a redirect, but root_path results in a redirect that RSpec does not recognize as a redirect?

Update

Based on comments, I modified the test to verify the status code

  it "should redirect to root" do
    click_button "Sign in"
    response.status.should == 302
    response.should be_redirect
    response.should redirect_to "/en"
  end

It leads to the error

5) Authentication sign-in with valid attributes should redirect to root
   Failure/Error: response.status.should == 302
     expected: 302
          got: 200 (using ==)

Solution

  • I think I solved the problem. Changing the verification code to

    it "should redirect to root" do
      current_url.should == root_url("en")
    end
    

    works.

    I assume that the cause of my problem is because webrat actually follows the redirect, so in my original test, I was testing the response code of the second response after the redirect.