ruby-on-railsrspecsorcery

Testing authentication with Sorcery and RSpec


I've spent far too long messing with this before asking for help. I can't seem to get RSpec and Sorcery to play together nicely. I've read through the docs on Integration testing with Sorcery and can post the login action properly, but my tests still doesn't think the user is logged in.

# spec/controllers/user_controller_spec
describe 'user access' do
    let (:user) { create(:user) }

    before :each do
      login_user(user[:email], user[:password])
    end

    it "should log in the user" do
      controller.should be_logged_in
    end

end

And my login_user method

# spec/support/sorcery_login
module Sorcery
  module TestHelpers
    module Rails
      def login_user email, password
        page.driver.post(sessions_path, { email: email , password: password, remember_me: false })
      end
    end
  end
end

The sessions controller handles the pages properly when I use them on the generated pages just fine. I tried outputting the results of the login_user method and it appears to properly post the data. How do I persist this logged in user through the tests? Does a before :each block not work for this? I'm just not sure where it could be running wrong and I'm pretty new to testing/RSpec so I may be missing something obvious. I'd appreciate any help.

Here's the output of the failed tests:

1) UsersController user access should log in the user
    Failure/Error: controller.should be_logged_in
    expected logged_in? to return true, got false

Solution

  • I just went through this yesterday. Here's what I did, if it helps.

    Sorcery provides a test helper login_user that relies on a @controller object being available. This works great in controller specs, but doesn't work in integration tests. So the workaround in integration tests is to write another method (like the one you have above) to simulate actually logging in via an HTTP request (essentially simulating submitting a form).

    So my first thought is that you should try renaming your method to login_user_post or something else that doesn't collide with the built-in test helper.

    Another potential gotcha is that it looks to me like the Sorcery helper assumes that your user's password is 'secret'.

    Here's a link to the built-in helper so you can see what I'm talking about:

    https://github.com/NoamB/sorcery/blob/master/lib/sorcery/test_helpers/rails.rb

    Good luck - I really like this gem except for this part. It is really only fully explained by patching together SO posts. Here's the code I use:

    Integration Helper

    module Sorcery
      module TestHelpers
        module Rails
          def login_user_post(user, password)
            page.driver.post(sessions_url, { username: user, password: password}) 
          end
    
          def logout_user_get
            page.driver.get(logout_url)
          end
        end
      end
    end
    

    Integration Spec (where user needs to be logged in to do stuff)

      before(:each) do
        @user = create(:user)
        login_user_post(@user.username, 'secret')
      end
    

    Controller Spec (where the regular login_user helper works fine)

      before(:each) do
        @user = create(:user)
        login_user
      end
    

    Note that login_user doesn't need any arguments if you have an @user object with the password 'secret'.