Update: see end of post for how the specs now work now that I have my specs in spec/requests instead of spec/controllers. Still wondering how to get a valid signed in user f
There are two issues at play:
1. rspec/controller vs rspec/requests
I was attempting to do an integration test under spec/controller. As per https://github.com/jnicklas/capybara#readme, you need to put Capybara specs in spec/requests or spec/integration. As per https://stackoverflow.com/a/5803121/9344:
A request spec is a thin wrapper around ActionDispatch::IntegrationTest, which doesn't work like controller specs (which wrap ActionController::TestCase). Even though there is a session method available, I don't think it is supported (i.e. it's probably there because a module that gets included for other utilities also includes that method).
Originally this could be solved with Devise via a helper method something like:
# file: spec/requests_helper.rb
def login(user)
post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
end
But the official/latest solution, which I had implemented already (but see point two below for why it didn't solve my issue), can be found at https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara
2. Devise::HelperTests are for controller/view tests, not integration tests.
If I want to do some tests on a controller, I can use the Devise::TestHelpers (referenced via spec_helper.rb) but even then I don't get functionality for Capybara integration tests as the Devise::TestHelpers are specifically written for controller/view tests, not integration tests. See rspec & devise test helpers.
In summary, what I wanted to do in a controller test can't be done because it was really an integration test and the session etc. isn't available for use in spec/controllers. However, there are some Devise test helpers that can be used to help do controller/view tests.
UPDATE
I revisited this much later, and have now got the Warden helpers functioning on my integration tests. Hurrah! This has taken off 8-10 seconds on my 448 tests. The trick was a new entry on https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara. Specifically:
Capybara-Webkit
If you have trouble using Warden's login_as method with the capybara-webkit driver, try setting run_callbacks to false in the login_as options struct
user = Factory.create(:user)
login_as(user, :scope => :user,
:run_callbacks => false)
In summary, instead of having to do an actual form fill and post for each time I needed an authenticated user for an integration test, now I just need login_as(user, :scope => :user, :run_callbacks => false)
(of course refactored out into a helper method).