I'm trying to write integration tests with rspec, factory_girl & capybara. I also have cucumber installed, but I'm not using it (to my knowledge).
I basically want to prepopulate the db with my user, then go to my home page and try to log in. It should redirect to user_path(@user).
However, sessions don't seem to be persisted in my /rspec/requests/ integration tests.
My spec: /rspec/requests/users_spec.rb
require 'spec_helper'
describe "User flow" do
before(:each) do
@user = Factory(:user)
end
it "should login user" do
visit("/index")
fill_in :email, :with => @user.email
fill_in :password, :with => @user.password
click_button "Login"
assert current_path == user_path(@user)
end
end
Returns:
Failures:
1) User flow should login user
Failure/Error: assert current_path == user_path(@user)
<false> is not true.
# (eval):2:in `send'
# (eval):2:in `assert'
# ./spec/requests/users_spec.rb:16
Instead, it redirects to my please_login_path - which should happen if the login fails for any reason (or if session[:user_id] is not set).
If I try to put session.inspect, it fails as a nil object.
If I try to do this in the controller tests (/rspec/controllers/sessions_spec.rb), I can access the session with no problem, and I can call session[:user_id]
If you are using Devise, you'll need to include Warden::Test::Helpers (right after the require of spec_helper is a good place) as outlined in the warden wiki.
The call to session is returning nil because capybara doesn't provide access to it when running as an integration test.
I have the same problems and although filling out a form might be an option for some, I had to roll my own authentication ruby because I was using a third party auth system (Janrain to be exact).... in my tests I ended up using something like this:
Here is what I have in my spec/support/test_helpers_and_stuff.rb
module AuthTestHelper
class SessionBackdoorController < ::ApplicationController
def create
sign_in User.find(params[:user_id])
head :ok
end
end
begin
_routes = Rails.application.routes
_routes.disable_clear_and_finalize = true
_routes.clear!
Rails.application.routes_reloader.paths.each{ |path| load(path) }
_routes.draw do
# here you can add any route you want
match "/test_login_backdoor", to: "session_backdoor#create"
end
ActiveSupport.on_load(:action_controller) { _routes.finalize! }
ensure
_routes.disable_clear_and_finalize = false
end
def request_signin_as(user)
visit "/test_login_backdoor?user_id=#{user.id}"
end
def signin_as(user)
session[:session_user] = user.id
end
end
Then in my request spec, with capybara and selenium, I did the following:
describe "Giveaway Promotion" do
context "Story: A fan participates in a giveaway", js: :selenium do
context "as a signed in user" do
before :each do
@user = Factory(:user)
request_signin_as @user
end
it "should be able to participate as an already signed in user" do
visit giveaway_path
....
end
end
end
end
BTW, I came up with solutions after trying the proposed solutions to this post and this post and neither of them worked for me. (but they certainly inspired my solution)
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With