Как перейти по первой ссылке в списке элементов после обновления до 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
tomekfranek
источник

Ответы:

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

Источники:

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

Эта формулировка также работает:

within first(".item") do
  click_link "Agree"
end
Эль Манди
источник
У меня сработало, спасибо. Капибара 2.4.1 и полтергейст.
Маурисио Мораес
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)
  конец
конец
DGM
источник
2

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

expect(page).to have_css("selector")                               
first("selector").click
nroose
источник
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он более хрупкий, потому что он незаметно щелкнет другой элемент, если вы введете новые элементы, которые соответствуют.

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

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

$('.item').find('a').first().click();
IT-видеоблоги
источник
2
Этот пример не относится к капибарам
keoghpe
2
Разве это не jQuery?
emptywalls