Como clicar no primeiro link da lista de itens após a atualização para o Capybara 2.0?


125

Como clicar no primeiro link nesse caso:

<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

e recebo este erro:

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

E sem o withineu recebo este erro:

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

Respostas:


176

Você pode apenas usar:

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

ou

first('.item > a').click

(se o seletor padrão for: css)


O código na sua pergunta não funciona como:

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

é equivalente a:

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

A Capivara encontra vários .item, por isso gera uma exceção. Considero esse comportamento da Capivara 2 muito bom.


4
Eu recomendaria não usar #first, ele não espera que um elemento exista: rubydoc.info/github/jnicklas/capybara/… . Se o conteúdo foi criado em tempo de execução com JS primeiro retornará nulo se executar a expectativa antes que o link seja criado.
usar o seguinte comando


24

Esse fraseado também funciona:

within first(".item") do
  click_link "Agree"
end

Trabalhou para mim, obrigado. Capivara 2.4.1 e poltergeist.
Mauricio Moraes

4

Xpath pode endereçar o elemento. Ainda não sou muito bom com isso, mas algo como//div[@class='active'][1]/a

Isso pode ou não funcionar, mas o ponto é que o xpath pode endereçar uma matriz de correspondências e obter uma determinada. Você deve conseguir combinar com isso.

Um exemplo de exemplo de trabalho de um dos meus projetos:

em page.find ("div.panel", texto: / Propostas /) faça
  em page.find ('tr', texto: / Foo /) faça
    page.should_xpath ('td [3]', texto: @today)
  fim
fim

2

Como first () nem sempre espera, talvez isso seja útil:

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

2

a maioria dessas soluções não usará os brilhantes recursos de espera da Capivara

melhor fazer como este link sugere:
https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara#find-the-first-matching-element

Ruim:

first(".active").click
Se ainda não houver um elemento .active na página, o valor retornará nulo e o clique falhará.

Boa:

Se você quiser ter certeza de que há exatamente um
find(".active").click

Se você quiser apenas o primeiro elemento, a
find(".active", match: :first).click
Capivara esperará o elemento aparecer antes de tentar clicar.

Observe que match: :firsté mais frágil, porque ele clicará silenciosamente em um elemento diferente se você introduzir novos elementos correspondentes.


Eu acredito que esta é a resposta mais precisa.
katericata

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.