【问题标题】:Error when using RSpec's `all` matcher with Capybara's `have_css` matcher将 RSpec 的 `all` 匹配器与 Capybara 的 `have_css` 匹配器一起使用时出错
【发布时间】:2014-09-17 23:44:37
【问题描述】:

我刚刚开始使用 RSpec(和 Capybara)进行功能规范。我正在测试我的 ActiveAdmin 仪表板,我想检查所有面板是否都有一个订单表,如此 sn-p 所示:

feature 'admin dashboard', type: :feature do
  def panels
    page.all('.column .panel')
  end

  describe 'all panels' do
    it 'have an orders table' do
      expect(panels).to all(have_css('table.orders tbody'))
    end
  end
end

我在单元测试中经常使用 all 匹配器,但在包装 Capybara 的 have_css 匹配器时它似乎不起作用,因为我收到以下错误:

Failure/Error: expect(panels).to all(have_css('table.orders tbody'))
TypeError:
  no implicit conversion of Capybara::RackTest::CSSHandlers into String

我的假设是否正确,即 RSpec 的内置 all 匹配器也应该与其他匹配器一起使用?

注意:在这种情况下,我使用 describeit 而不是 featurescenario,因为我正在测试输出而不是用户交互场景(请参阅我的 other question)。

【问题讨论】:

  • 不幸的是,RSpec 的 all 和 Capybara 的 all 之间存在冲突,请参阅 Capybara Issue 1396。你打电话的all实际上是Capybara的all
  • 哦,你是对的@JustinKo。你有什么解决方法可以推荐吗?

标签: ruby-on-rails rspec capybara rspec-rails


【解决方案1】:

不幸的是,RSpec 的 all 和 Capybara 的 all 之间存在冲突,请参阅 Capybara Issue 1396。你打电话的all其实是Capybara的all

解决方案 1 - 直接调用 BuiltIn::All

最快的解决方案是直接调用 RSpec 的 all 方法(或至少调用它执行的代码。

如果您使用RSpec::Matchers::BuiltIn::All.new 而不是all,预期将起作用:

expect(panels).to RSpec::Matchers::BuiltIn::All.new(have_css('table.orders tbody'))

解决方案 2 - 重新定义所有

直接调用 BuiltIn:All 读取效果不好,因此如果经常使用可能会很烦人。另一种方法是将all 方法重新定义为RSpec 的all 方法。为此,请添加模块和配置:

module FixAll
  def all(expected)
    RSpec::Matchers::BuiltIn::All.new(expected)
  end
end

RSpec.configure do |c|
  c.include FixAll
end

随着更改,以下行中的 all 将表现得像 RSpec 的 all 方法。

expect(panels).to all(have_css('table.orders tbody'))

请注意,如果您想使用 Capybara 的 all 方法,您现在总是需要使用会话调用它(即 page):

# This will work because "page.all" is used
expect(page.all('table').length).to eq(2)

# This will throw an exception since "all" is used
expect(all('table').length).to eq(2)

【讨论】:

  • 谢谢,我最终使用了解决方案 2。顺便问一下,这样放置辅助模块的“标准”位置在哪里?我已经去了 spec/support/helpers/fix_all_helper.rb。
  • “支持”文件夹中的某些位置似乎有意义。除此之外,鉴于这种方法的非标准性,可能没有标准。
  • 我在 Cucumber 环境中尝试过此操作(将文件放入 features/support/fix_rspec_all.rb),但出现关于 RSpec.configure 不存在的错误。所以相反,我删除了那个配置块,只是调用了World(FixAll),它将我的方法添加到 Cucumber“世界”中。我实际上调用了我的匹配器each,这样它们就不会发生冲突,我可以同时使用它们。请参阅下面的替代答案
【解决方案2】:

我对接受的答案使用了非常相似的方法,但在 Cucumber 环境中,我收到了关于 RSpec.configure 不存在的错误。另外,我想将匹配器称为 all 之外的其他名称,以便我可以同时使用它们而不会发生冲突。这就是我最终的结果

# features/support/rspec_each.rb

module RSpecEach
  def each(expected)
    RSpec::Matchers::BuiltIn::All.new(expected)
  end
end

World(RSpecEach) # extends the Cucumber World environment

现在我可以执行以下操作:

expect(page.all('#employees_by_dept td.counts')).to each(have_text('1'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 2021-08-26
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 2011-07-23
    相关资源
    最近更新 更多