If you are using engines to break up your large Rails app, you might end up with a strange case where you cannot login for your capybara tests within individual engines. It sounds weird at first, but the engine your trying to test might not have a dependency on the engine that provides authentication. It should depend on the fact that there is a user_id in the session, but how it got there is none of its concern.
Here’s a real example of engines and I currently working on:
- User engine – contains model/table for users
- UserManagement engine – contains controllers and views for sign in/up
- LocationManagement engine – contains controllers and views for managing locations
Both the UserManagement and LocationManagement engines depend on the User engine. Furthermore the LocationManagement engine requires a logged in user in to access its controllers (it does this by looking for
session[:user_id] in a before filter and sets
@current_user off of it). The LocationManagement engine does not depend on the UserManagement engine, or vice-a-versa.
In my acceptance tests for the LocationManagement engine I need to test the creation of Locations. To do this, I first need a logged in user. Without making the LocationManagement engine depend on the UserManagement engine, there’s no way for me to login the user by visiting the Sign In page and filling in a form. So instead of filling in a Sign In form, I will set a session variable for user_id.
In order to set a session variable in a capybara test, you need to use a gem called rack_session_access: https://github.com/railsware/rack_session_access. This gem creates a http endpoint that allows you to set session variables. It should go without saying: DO NOT allow this gem to run in production!
In your engine’s gemfile, add the dependency on rack_session_access:
group :development, :test do ... gem "rack_session_access" ... end
The gem is actually rack middleware, so the next step is to tell your dummy app to add it to its middleware stack. In
spec/dummy/config/test.rb add the following line:
Dummy::Application.configure do ... config.middleware.use RackSessionAccess::Middleware .. end
…in your spec_helper.rb add:
…and finally in your test “login” your user by…
page.set_rack_session(:user_id => @user.id)
Voila! You have the equivalent of a logged in user! Thank you Andriy Yanko for posting on Accessing application session in capybara.