如何使用Capybara声明元素数量并带有正确的错误消息?

时间:2011-07-18 06:02:26

标签: rspec dsl capybara

我知道在Capybara,你可以这样做:

page.should have_css("ol li", :count => 2)

但是,假设该页面仅包含一个匹配元素,则该错误不具有描述性:

  1) initial page load shows greetings
 Failure/Error: page.should have_css("ol li", :count => 2)
 expected css "ol li" to return something

而不是这个相当模糊的错误消息,有没有办法以这样的方式编写断言,即错误输出类似于'匹配'ol li'时,预期:2,找到:1'。显然我可以自己为这样的行为制作一个自定义逻辑 - 我问有没有办法在开箱即用的情况下做到这一点?

对于它的价值,我使用的是Selenium驱动程序和RSpec。

6 个答案:

答案 0 :(得分:166)

我更喜欢这个。

expect(page).to have_selector('input', count: 12)

https://github.com/jnicklas/capybara/blob/415e2db70d3b19b46a4d3d0fe62f50400f9d2b61/spec/rspec/matchers_spec.rb

答案 1 :(得分:22)

好吧,因为似乎没有开箱即用的支持,我写了这个自定义匹配器:

RSpec::Matchers.define :match_exactly do |expected_match_count, selector|
    match do |context|
        matching = context.all(selector)
        @matched = matching.size
        @matched == expected_match_count
    end

    failure_message_for_should do
        "expected '#{selector}' to match exactly #{expected_match_count} elements, but matched #{@matched}"
    end

    failure_message_for_should_not do
        "expected '#{selector}' to NOT match exactly #{expected_match_count} elements, but it did"
    end
end

现在,您可以执行以下操作:

describe "initial page load", :type => :request do
    it "has 12 inputs" do
        visit "/"
        page.should match_exactly(12, "input")
    end
end

并获得如下输出:

  1) initial page load has 12 inputs
     Failure/Error: page.should match_exactly(12, "input")
       expected 'input' to match exactly 12 elements, but matched 13

它现在可以解决问题,我将研究制作Capybara的这一部分。

答案 2 :(得分:14)

我认为以下内容更简单,输出相当清晰,无需自定义匹配器。

page.all("ol li").count.should eql(2)

然后打印出错误:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)

答案 3 :(得分:9)

编辑正如@ThomasWalpole指出的那样,使用all禁用了Capybara的等待/重试,所以@pandaPower的答案要好得多。

这个怎么样?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end

答案 4 :(得分:3)

Capybara推荐的当前(9/2/2013)最佳做法如下(source):

page.assert_selector('p#foo', :count => 4)

答案 5 :(得分:-3)

@pandaPower的答案非常好,但语法对我来说略有不同:

expect(page).to have_selector('.views-row', :count => 30)