如何在Capybara中设置会话值?

33
我正在为Shopify开发一个应用程序,希望进行集成测试。我需要能够存储一些值在会话变量中,以便进行身份验证。我应该如何做呢?我使用Capybara和Capybara-webkit。

1
在集成测试中,您应该从登录表单中记录用户。 - apneadiving
1
那行不通。关键问题在于我正在使用外部认证系统:Shopify。因此,Shopify被配置为返回到特定URL的成功登录。你看出问题了吗?那个URL不能是本地主机。这就是为什么即使在集成测试中,我也需要模拟登录过程的原因。 - Nerian
我如何在Shopify应用程序中使用相同的东西来进行Cucumber测试? - Navin Bista
5个回答

33
接受的答案建议使用rack_session_access。它通过插入中间件控制器来编辑和更新会话状态,然后让capybara访问该页面并提交包含会话数据的表单来实现。非常巧妙!但如果您直接或通过Devise使用Warden,则不必这样做。
Warden具有一个钩子on_next_request,可访问warden机制,可用于直接设置会话密钥。我将其打包到rspec中:
创建spec/support/inject_session.rb:
module InjectSession
  include Warden::Test::Helpers

  def inject_session(hash)
    Warden.on_next_request do |proxy|
      hash.each do |key, value|
        proxy.raw_session[key] = value
      end
    end
  end
end

spec/spec_helper.rb中,将模块包含在功能规格中:
RSpec.configure do |config|
    config.include InjectSession, :type => :feature
end

然后在规范中的示例用法可能是:

   inject_session :magic => 'pixie dust', :color => 'pink' 
   visit shopping_cart_path
   page.should be_all_sparkly_and_pink # or whatever

@YossiShasho 它为什么不工作?对我来说它似乎很好用,目前使用的是devise 3.2.4和warden 1.2.3。 - ronen
我真的不记得出了什么问题,但我没有花太多精力去解决它。只是按照上面建议的 rack_session_access gem 继续进行,这很好用。 - Yossi Shasho
我非常喜欢这个解决方案。不幸的是它没有起作用,所以我也转而使用rack_session_access(Ruby 2.2,Rails 4.2)。 - awenkhh
这对我在Rails 4.2,Devise 3.4.1等方面也适用。 - Thibaut Barrère
兄弟,你让我的一天更美好了!我在这里使用Devise 4.5.0和Rails 5.2.1。谢谢你!<3 - Washington Botelho
我想提一下,我们需要要求 Rails(至少在Rails>6中)自动加载这个新文件夹。我们可以通过在 rails_helper.rb 中添加以下行来实现: Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require(f) } - Gustavo G.

27

@fguillen,我如何在Shopify应用程序中使用相同的Cucumber? - Navin Bista

4

你可以使用像 VCR 或 webmock 这样的工具来模拟外部 HTTP 资源的调用。


4

正如apneadiving的评论所建议的那样,您应该使用capybara“直接”填写表单。对于身份验证登录表单的填充,使用Cucumber进行测试可能如下所示(来自Capybara github页面):

When /I sign in/ do
  within("#session") do
    fill_in 'Login', :with => 'user@example.com'
    fill_in 'Password', :with => 'password'
  end
  click_link 'Sign in'
  ...
end

如果您想尝试不同的操作或者在正常的登录过程中遇到问题,这篇SO问答可能会有所帮助。

那行不通。关键问题在于我正在使用外部认证系统:Shopify。因此,Shopify被配置为返回到特定URL的成功登录。你看出问题了吗?那个URL不能是本地主机。这就是为什么即使在集成测试中,我也需要模拟登录过程的原因。 - Nerian
1
@Nerian 请尝试使用 https://github.com/myronmarston/vcr 来记录外部请求到您的本地环境,然后您就可以使用这种方法。 - Christopher Manning

3

我恐怕要带来不好的消息,根据Capybara的文档:

测试无法访问会话和请求,对响应的访问受到限制。

因此您将无法按照您的预期进行测试。


只是想到:在您的控制器中插入一些条件语句以进行测试是可以接受的。

 session[:foo] = User.first.id if Rails.env.test?

更好的选择是仅在集成测试中对您的控制器进行猴子补丁。

3
这是可能的,但感觉像是代码异味 - 将测试代码注入到生产应用程序中?如果可以的话,最好重新编写您的测试。 - Taryn East

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接