¿Cómo hacer clic en el primer enlace de la lista de elementos después de actualizar a Capybara 2.0?

125

Cómo hacer clic en el primer enlace en ese 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

y me sale este error:

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

Y sin el withinme sale este error:

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

Respuestas:

176

Solo puedes usar:

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

o

first('.item > a').click

(si su selector predeterminado es: css)


El código en su pregunta no funciona como:

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

es equivalente a:

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

Carpincho encuentra varios .item, por lo que plantea una excepción. Considero que este comportamiento de Carpincho 2 es muy bueno.

Andrei Botalov
fuente
44
Recomendaría no usar #first, no espera que exista un elemento: rubydoc.info/github/jnicklas/capybara/… . Si el contenido se creó en tiempo de ejecución con JS primero devolverá nulo si se ejecuta la expectativa antes de que se cree el enlace.
Dgtized
24

Esta frase también funciona:

within first(".item") do
  click_link "Agree"
end
Elle Mundy
fuente
Trabajó para mí, gracias. Carpincho 2.4.1 y poltergeist.
Mauricio Moraes
4

Xpath puede abordar el elemento. Todavía no soy muy bueno con eso, pero algo así como//div[@class='active'][1]/a

Eso puede o no funcionar, pero el punto es que xpath puede abordar una serie de coincidencias y extraer una en particular. Deberías poder coincidir con esto.

Un ejemplo de trabajo de uno de mis proyectos:

dentro de page.find ("div.panel", texto: / Proposals /) do
  dentro de page.find ('tr', texto: / Foo /) do
    page.should have_xpath ('td [3]', texto: @today)
  final
final
DGM
fuente
2

Como first () no siempre espera, quizás esto sea útil:

expect(page).to have_css("selector")                               
first("selector").click
nroose
fuente
2

la mayoría de esas soluciones no utilizarán las brillantes funciones de espera de Capybara

mejor haga lo que sugiere este enlace:
https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara#find-the-first-matching-element

Malo:

first(".active").click
Si todavía no hay un elemento .active en la página, primero devolverá nil y el clic fallará.

Bueno:

Si quieres asegurarte de que hay exactamente uno
find(".active").click

Si solo desea el primer elemento,
find(".active", match: :first).click
Capybara esperará a que aparezca el elemento antes de intentar hacer clic.

Tenga en cuenta que match: :firstes más frágil, porque hará clic silenciosamente en un elemento diferente si introduce nuevos elementos que coincidan.

Salomanuel
fuente
Creo que esta es la respuesta más precisa.
katericata
-2

Simple puedes usar:

$('.item').find('a').first().click();
Vlogs de TI
fuente
2
Este ejemplo no es relevante para el carpincho
keoghpe
2
¿No es eso jQuery?
paredes vacías