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
tomekfranek
fonte

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.

Andrei Botalov
fonte
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
Elle Mundy
fonte
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
DGM
fonte
2

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

expect(page).to have_css("selector")                               
first("selector").click
Nroose
fonte
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.

Salomanuel
fonte
Eu acredito que esta é a resposta mais precisa.
katericata
-2

Simples você pode usar:

$('.item').find('a').first().click();
Vlogs de TI
fonte
2
Este exemplo não é relevante para capivara
keoghpe
2
Não é esse jQuery?
Emptywalls