Как перейти по первой ссылке в списке элементов после обновления до Capybara 2.0?


125

Как в таком случае нажать первую ссылку:

<div class="item">
  <a href="/agree/">Agree</a>
</div>
<div class="item">
  <a href="/agree/">Agree</a>
</div>
within ".item" do
  first(:link, "Agree").click
end

и я получаю эту ошибку:

Capybara::Ambiguous:
  Ambiguous match, found 2 elements matching css ".item"

И без этого withinя получаю эту ошибку:

Failure/Error: first(:link, "Agree").click
NoMethodError:
  undefined method `click' for nil:NilClass

Ответы:


176

Вы можете просто использовать:

first('.item').click_link('Agree')

или

first('.item > a').click

(если ваш селектор по умолчанию: css)


Код в вашем вопросе не работает как:

within ".item" do
  first(:link, "Agree").click
end

эквивалентно:

find('.item').first(:link, "Agree").click

Capybara находит несколько .item, поэтому возникает исключение. Я считаю такое поведение Capybara 2 очень хорошим.


4
Я бы не рекомендовал использовать #first, он не дожидается появления элемента: rubydoc.info/github/jnicklas/capybara/… . Если контент был создан во время выполнения с помощью JS, сначала будет возвращено значение nil, если он выполняет ожидание до создания ссылки.
опубликовано 05

122

Попробуйте следующее:

within ".item" do
  click_link("Agree", :match => :first)
end

Источники:


1
удивительный. И это работает на простом page.find ('# {css}',: match =>: first). Щелкните Cheers, чтобы получить действительно полезный ответ
Dono


4

Xpath может обращаться к элементу. Я пока не очень хорошо разбираюсь в этом, но что-то вроде//div[@class='active'][1]/a

Это может работать, а может и не работать, но дело в том, что xpath может адресовать массив совпадений и извлекать конкретный. Вы должны соответствовать этому.

Рабочий пример из одного из моих проектов:

внутри page.find ("div.panel", text: / Proposals /) выполните
  внутри page.find ('tr', text: / Foo /) делать
    page.should have_xpath ('td [3]', текст: @today)
  конец
конец

2

Поскольку first () не всегда ждет, возможно, это полезно:

expect(page).to have_css("selector")                               
first("selector").click

2

большинство этих решений не будут использовать блестящие функции ожидания Capybara

лучше сделать так, как предлагает эта ссылка:
https://oughttbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara#find-the-first-matching-element

Плохой:

first(".active").click
Если на странице еще нет элемента .active, сначала будет возвращено nil, и щелчок не удастся.

Хорошо:

Если вы хотите убедиться, что есть только один
find(".active").click

Если вам нужен только первый элемент,
find(".active", match: :first).click
Capybara будет ждать появления элемента, прежде чем пытаться щелкнуть.

Обратите внимание, что match: :firstон более хрупкий, потому что он незаметно щелкнет другой элемент, если вы введете новые элементы, которые соответствуют.


Я считаю, что это наиболее точный ответ.
katericata

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.