在 Rails 查看规范中使用 Capybara 的“within”范围助手

Using Capybara's `within` scoping helper in Rails View Specs

像许多人一样,我不仅使用 Capybara 来测试功能规格,还使用 ​​Rails 查看规格中呈现的 HTML。

我将渲染的 HTML 包装到 Capybara 节点中 -

require "spec_helper"

RSpec.describe "foo/show.html.erb", type: :view do
  it "should display foo" do
    render

    within(".some-class") do
      expect(page).to have_content("woohoo")
    end
  end

  def page
    @page ||= Capybara::Node::Simple.new(rendered)
  end
end

但是,我最近注意到几个测试(格式与上述类似)在它们实际上应该失败(误报)时通过了。

我追踪到 within do ... end 块的行为 - 它从不执行我的视图规范中的那些块。我通过尝试在 within 块内使用 binding.pry 暂停执行来确认,但它从未触发。由于它从不执行,所有规范都顺利通过

看起来 within 是一个 Capybara Session method,并且由于没有 "session",因此不打算使用视图规范是有道理的。

  1. 我很好奇为什么对 within 的调用只是默默地失败了?它调用了什么 within 方法,如果找不到它为什么不抛出错误?

  2. 有没有办法让它在这里与视图规范一起工作?使用复杂的渲染 HTML 将您的测试限定在特定的 HTML 节点上非常方便,这是 within 的全部要点,所以我很想能够使用它

谢谢!

默认情况下只有 Capybara::RSpecMatchers 应包含在视图规格中 - https://github.com/jnicklas/capybara/blob/master/lib/capybara/rspec.rb#L10 - 而不是 Capybara::DSL,因此 Capybaras within 不应该可用(尝试使用 byebug并进入内部调用以查看提供它的库)。您可以通过使用 matchers/finders 可以在节点上调用并将范围限定到所使用的节点这一事实来确定您的测试范围 - 比如

page = Capybara.string(rendered)
scoped_node = page.find(".some-class")
expect(scoped_node).to have_content("woohoo")
expect(scoped_node.find('.contained-class')).to have_content("abcdefg")

更新:快速浏览后,您实际调用的 within 可能是 RSpec be_within 匹配器,由于某种原因被别名为 within - https://github.com/rspec/rspec-expectations/blob/3-5-maintenance/lib/rspec/matchers.rb#L416 - 不确定为什么,因为我想不出在期望中它会如何读得很好 - 基本上你的所有语句都在创建一个永远不会被调用的匹配器,只是忽略传递给它的块.