Как утверждать количество элементов с помощью 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.


person merryprankster    schedule 18.07.2011    source источник
comment
Просто чтобы люди знали, page.should have_css(ol li, :count =› 2) был реализован в капибаре. Я думаю, что его очень удобно использовать с областями действия: внутри (ol.users-list) do page.should have_css ('li', :count => 3) end   -  person rafaelkin    schedule 18.04.2013
comment
@rafaelkin, просто чтобы уточнить: теперь водосвинка сообщает, например. несоответствие количества элементов более подробно? Я какое-то время не следил за капибарой, но тогда, когда я задал вопрос, проблема заключалась в формате сообщения об ошибке, а не в том, что page.should have_css("ol li", :count => 2) уже не было бы реализовано.   -  person merryprankster    schedule 22.04.2013
comment
ребята, у меня такое ощущение, что принятый в настоящее время ответ (= мой собственный) больше не лучший, но у меня нет времени (больше не работает с Ruby), чтобы оценить, какое из предложенных решений является лучшим. Я изменю принятый ответ на ответ Ричарда только потому, что он включает вывод утверждения, касающегося исходной проблемы.   -  person merryprankster    schedule 28.10.2013


Ответы (6)


Мне это нравится намного больше.

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

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

person pandaPowder    schedule 10.06.2013
comment
Также работает с have_css: expect(page).to have_css('input', count: 12) - person Abe Voelker; 07.12.2014

Ну так как вроде поддержки из коробки нет, я написал вот такой кастомный матчер:

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.

person merryprankster    schedule 25.07.2011
comment
Похоже, исправить это в Capybara непросто: github.com/jnicklas/capybara/issues/331< /а> - person merryprankster; 25.07.2011

Я думаю, что следующее проще, дает довольно четкий вывод и устраняет необходимость в специальном сопоставителе.

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

Затем это распечатывает ошибку:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)
person Richard    schedule 10.07.2013
comment
Это не ждет, пока ожидание сбудется, например. когда все еще есть ожидающие запросы ajax. - person Clemens Helm; 18.08.2014

Редактировать: Как указал @ThomasWalpole, использование all отключает ожидание/повторную попытку Capybara, поэтому приведенный выше ответ @pandaPower намного лучше.

Как насчет этого?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end
person Constant Meiring    schedule 10.03.2015
comment
Это полностью устраняет ожидание/повторную попытку Capybaras и никогда не должно быть рекомендуемым решением. - person Thomas Walpole; 02.06.2017
comment
@ThomasWalpole Я не уверен, о чем ты говоришь. Как поиск элемента внутри другого элемента каким-либо образом влияет на ожидание/повторную попытку в Capybara? - person Constant Meiring; 07.06.2017
comment
@ConstantMeiring Это не within, это вызов .count по результатам all, который отключает ожидание/повторную попытку. Вызывая count по результатам all (для которых допустимым возвратом является пустой массив), вы конвертируете в целое число и сравниваете его. Если это сравнение терпит неудачу, ожидания терпят неудачу. Если вместо этого вы передадите параметр count одному из сопоставителей Capybara, capybara будет ждать/повторно пытаться найти указанный селектор, пока не совпадет параметр count (или Capybara.default_max_wait_time не истечет). - person Thomas Walpole; 07.06.2017

Текущая (9/2/2013) передовая практика, рекомендованная Capybara, следующая (источник):

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

person acconrad    schedule 02.09.2013

Ответ @pandaPower очень хорош, но синтаксис для меня немного отличался:

expect(page).to have_selector('.views-row', :count => 30)
person Nick    schedule 04.09.2014
comment
Использование хеш-ракет не считается другим синтаксисом. - person premjg; 25.11.2014
comment
Я не рубиновый разработчик и не понимал, что эти два синтаксиса эквивалентны. TBH Я не уверен, что это заслуживает понижения. Это действующая альтернатива. Для тех, кто не знаком с Ruby, это может показаться неочевидным. Это было не для меня. - person Nick; 03.09.2015