Rails + Cucumber/Capybara: How to set/retrieve cookies in tests?
Solution 1
So eventually I figured it out after trying a lot of different things.
Given(/^I didn't log out the last time I was on the site$/) do
user = FactoryGirl.create(:user)
visit new_user_session_path
fill_in('user[email]', with: user.email)
fill_in('user[password]', with: 'test123')
click_button('Sign in')
Capybara.current_session.driver.request.cookies.[]('auth_token').should_not be_nil
auth_token_value = Capybara.current_session.driver.request.cookies.[]('auth_token')
Capybara.reset_sessions!
page.driver.browser.set_cookie("auth_token=#{auth_token_value}")
end
When(/^I go to the homepage$/) do
visit root_path
end
Then(/^I should automatically be logged in$/) do
page.should have_content("Logout")
end
UPDATE:
Here's what I use in case I'm using Selenium for some of the tests:
if Capybara.current_session.driver.class == Capybara::Selenium::Driver
auth_token = page.driver.browser.manage.cookie_named('auth_token')[:value]
page.driver.browser.manage.delete_all_cookies
page.driver.browser.manage.add_cookie(:name => "auth_token", :value => auth_token)
else
puts "cookies = #{Capybara.current_session.driver.request.cookies}"
Capybara.current_session.driver.request.cookies.[]('auth_token').should_not be_nil
auth_token_value = Capybara.current_session.driver.request.cookies.[]('auth_token')
Capybara.reset_sessions!
page.driver.browser.set_cookie("auth_token=#{auth_token_value}")
end
Solution 2
Use https://github.com/nruth/show_me_the_cookies which wraps the driver methods. It has methods for getting cookies, deleting cookies, and a method for creating cookies called create_cookie
.
Related videos on Youtube
bigpotato
Updated on October 02, 2022Comments
-
bigpotato over 1 year
I'm implementing a lazy login feature. My cucumber feature should describe it:
Feature: User log in Scenario: Lazy login Given I didn't log out the last time I was on the site When I go to the homepage Then I should automatically be logged in
And these are my step definitions:
Given(/^I didn't log out the last time I was on the site$/) do user = FactoryGirl.create(:user) visit new_user_session_path fill_in('user[email]', with: user.email) fill_in('user[password]', with: 'test123') click_button('Sign in') Capybara.reset_sessions! end When(/^I go to the homepage$/) do visit root_path end Then(/^I should automatically be logged in$/) do #<-- Fails here page.should have_content("Logout") end
This is what happens when a user logs in: the
cookies.signed[:auth_token]
gets set. This will be used by a before filter in my ApplicationController so that users who open a fresh browser will be logged in automatically:class SessionsController < Devise::SessionsController def create super if user_signed_in? puts 'yesssssss' session[:user_id] = current_user.id current_user.remember_me! if current_user.remember_token.blank? cookies.signed[:auth_token] = { :value => current_user.remember_token, :domain => "mysite.com", :secure => !(Rails.env.test? || Rails.env.development?) } puts "current_user.remember_token = #{current_user.remember_token}" puts 'cookies:' puts cookies.signed[:auth_token] end end
end
This is the before filter in my ApplicationController:
def sign_in_through_cookie logger.info "logging in by cookie" puts "logging in by cookie" puts cookies.signed[:auth_token] #<-- PROBLEM: this returns nil. return true if !current_user.nil? if !cookies[:auth_token].nil? && cookies[:auth_token] != '' user = User.find_by_remember_token(cookies.signed[:auth_token]) return false if user.blank? sign_in(user) puts 'success' return true else return false end end
So the issue is that in the last step of my cucumber feature,
cookies.signed[:auth_token]
returns nil. I'm guessing this is just a capybara thing. So do I actually have to set a cookie in the test as opposed to using the one in my controller? -
Nakilon over 9 yearsundefined method `set_cookie' for #<Selenium::WebDriver::Driver
-
Arepo over 7 yearsInstead of
Capybara.current_session.driver.request.cookies.[]('auth_token')
, why not use Ruby's standard sugar for hashes - ieCapybara.current_session.driver.request.cookies['auth_token']
-
sameers about 7 yearsFor the Poltergeist driver, the method (as documented on the Poltergeist GitHub page) is
page.driver.set_cookie()
, and its 3 arguments are the cookie's name, its value, and an options hash for setting, among other things, the cookie's expiry value. -
Gorm Casper over 5 years@JonKern glad to hear it! I see that
create_cookie
has been documented in the README, so I'm updating my answer. -
anandvc almost 4 yearsIf you get the error
undefined method set_cookie for #<Selenium::WebDriver::Chrome::Driver:
then you can set cookies like so:page.driver.browser.manage.add_cookie(name: "cookie_name", value: "cookie_value")
-
Maxime Boué about 3 yearsThe solution is not on the page from the link you gave anymore