Rails + Cucumber/Capybara:如何在测试中设置/检索 cookie?
Posted
技术标签:
【中文标题】Rails + Cucumber/Capybara:如何在测试中设置/检索 cookie?【英文标题】:Rails + Cucumber/Capybara: How to set/retrieve cookies in tests? 【发布时间】:2013-10-19 23:53:24 【问题描述】:我正在实现一个惰性登录功能。我的黄瓜功能应该描述一下:
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
这些是我的步骤定义:
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
这就是用户登录时发生的情况:cookies.signed[:auth_token]
被设置。这将由我的 ApplicationController 中的前置过滤器使用,以便打开新浏览器的用户将自动登录:
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
结束
这是我的 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
所以问题是在我的黄瓜功能的最后一步,cookies.signed[:auth_token]
返回 nil。我猜这只是水豚的事情。那么我真的必须在测试中设置一个 cookie,而不是在我的控制器中使用那个吗?
【问题讨论】:
【参考方案1】:所以我在尝试了很多不同的事情后最终弄明白了。
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
更新:
以下是我使用 Selenium 进行某些测试时使用的内容:
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
【讨论】:
#<:webdriver::driver> 而不是Capybara.current_session.driver.request.cookies.[]('auth_token')
,为什么不使用Ruby 的标准糖来处理哈希——即Capybara.current_session.driver.request.cookies['auth_token']
对于 Poltergeist 驱动程序,方法(如 the Poltergeist GitHub page 中所述)是 page.driver.set_cookie()
,它的 3 个参数是 cookie 的名称、它的值和用于设置的选项哈希等, cookie 的过期值。
如果您收到错误undefined method set_cookie for #<Selenium::WebDriver::Chrome::Driver:
,那么您可以像这样设置cookie:page.driver.browser.manage.add_cookie(name: "cookie_name", value: "cookie_value")
【参考方案2】:
使用封装了驱动方法的https://github.com/nruth/show_me_the_cookies。它具有获取 cookie、删除 cookie 和创建 cookie 的方法,称为 create_cookie
。
【讨论】:
@JonKern 很高兴听到它!我看到create_cookie
已记录在自述文件中,所以我正在更新我的答案。【参考方案3】:
我只需要测试 cookie 值
灵感来自https://collectiveidea.com/blog/archives/2012/01/05/capybara-cucumber-and-how-the-cookie-crumbles
并移植到 Rails 5.x
创建features/support/cookies.rb
有内容
module Capybara
class Session
def cookies
@cookies ||= ActionDispatch::Request.new(Rails.application.env_config.deep_dup).cookie_jar
end
end
end
Before do
allow_any_instance_of(ActionDispatch::Request).to receive(:cookie_jar).and_return(page.cookies)
allow_any_instance_of(ActionDispatch::Request).to receive(:cookies).and_return(page.cookies)
end
接下来是测试步骤
Then('is set cookie string with value string') do |cookie, value|
expect(page.cookies.signed[cookie]).to eq value
end
【讨论】:
解决方案不在您提供的链接的页面上以上是关于Rails + Cucumber/Capybara:如何在测试中设置/检索 cookie?的主要内容,如果未能解决你的问题,请参考以下文章
Rails 3.0.9 + Devise + Cucumber + Capybara 臭名昭著的“没有路线匹配 /users/sign_out”
在 Cucumber + Capybara + PhantomJS 在 Rails 中调试 jQuery Ajax
Cucumber + Capybara + Selenium:选择文本
Cucumber 和 Capybara,单击非链接或按钮元素
Cucumber, capybara and selenium - 无需按钮即可提交表单
Cucumber / Capybara 错误:参数 [0] 未定义(Selenium::WebDriver::Error::JavascriptError)