【问题标题】:Rails + Cucumber/Capybara: How to set/retrieve cookies in tests?Rails + Cucumber/Capybara:如何在测试中设置/检索 cookie?
【发布时间】: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,而不是在我的控制器中使用那个吗?

【问题讨论】:

    标签: ruby-on-rails cookies capybara


    【解决方案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 #&lt;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
    

    【讨论】:

    • 解决方案不在您提供的链接的页面上
    猜你喜欢
    • 2018-06-06
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2012-12-09
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    相关资源
    最近更新 更多