使用RSpec的`all`匹配器与Capybara的`have_css`匹配器时出错

tri*_*anm 8 rspec ruby-on-rails capybara rspec-rails

我刚刚开始使用RSpec(和Capybara)的功能规格.我正在测试我的ActiveAdmin仪表板,我想检查所有面板是否有一个订单表,如下面的代码段所示:

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我是否认为RSpec的内置all匹配器应该与其他匹配器一起工作?

注:我使用describeit替代feature,并scenario在这种情况下,因为我测试输出,而不是用户交互方案(请参阅我的其他问题).

Jus*_* Ko 12

不幸的是,RSpec all和Capybara 之间存在冲突,all参见Capybara Issue 1396.在all您呼叫实际上是水豚的all.

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

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

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

expect(panels).to RSpec::Matchers::BuiltIn::All.new(have_css('table.orders tbody'))
Run Code Online (Sandbox Code Playgroud)

解决方案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
Run Code Online (Sandbox Code Playgroud)

随着更改,all以下行中的行为将类似于RSpec的all方法.

expect(panels).to all(have_css('table.orders tbody'))
Run Code Online (Sandbox Code Playgroud)

请注意,如果您想使用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)
Run Code Online (Sandbox Code Playgroud)