I'm using Rails 3.1.0.rc4 and I'm working on doing integration tests with capybara's new Steak-like DSL and Rspec (using Devise authentication)
The issue I'm having is that when I run an integration test, the rack-test driver from capybara seems to just completely lose the user's logged in session, in fact, the session seems to just clear out altogether.
After days of debugging, I'm at a complete loss as to why. Going line by line through the middleware stack, I believe I've ruled the problem down to something going on in the ActiveRecord::SessionStore
that is causing this. I've read here that Rails will clear out a session if it can't validate the CSRF token, which leaves me to believe that I've got something configured wrong, and for some reason this one test is not authenticating the CSRF token correctly.
This is what is in my session_store.rb in the /initializers directory:
MyApp::Application.config.session_store :active_record_store
Does anyone who knows about CSRF protection in rails have any leads on why this may be happening?
Also, here are some things to note:
- the thing I'm trying to test actually works within the browser itself, only this one test is dropping the session
- the session seems to get dropped after the submission of a form to which the action url is to another server. I'm using the VCR gem for capturing the requests/responses to this external server in the test, and while I believe I've ruled the external request as the problem, this may have something directly to do with the CSRF token not authenticating, thus clearing out the session.
- other tests involving logging in / using sessions are not dropping sessions
Can anyone give me any leads as to what is going on here exactly, and why the one test just seems to arbitrarily drop its session and fail on me? I've done lots of debugging and have tried everything I can possible think of.
I was able to fix this error by setting this value to true in config/initializers/test.rb
Beforehand, the CSRF
<meta>
tags were not printing out to the<head>
. After changing this value they finally appear.The manual way of doing it is very simple:
You can then break this out into a function in your 'spec_helper.rb':
and use it in any of your tests (probably request specs):
I'm new to capybara too and I was having a similar problem.
I was trying to login a user doing something like this:
And that was working ok until I tried to do something with capybara, such as visiting a page and just testing if the user was logged in. This simple test was not passing:
At first I thought capybara was clearing the sessions but I was wrong. The thing that took me some time to realize is that the driver capybara is using handles its own sessions, so, from the point of view of capybara my user was never logged in. To do so you have to do it like this
Not sure if this is your case, but hope that helps.
This might be a long shot but I believe we end up in a bad state after
click_button 'Sign in'
and callingvisit elsewhere
immediately after.My theory is that when we click the button the request hasn't completed yet, and we kill it by visiting another path.
From the Capybara documentation:
If this is the case the solution is simple: give Capybara something to look for and let it wait until the request is complete. This can be as simple as adding:
expect(page).to have_text('Signed in as bob@example.com')