¿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

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.


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

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

2

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

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

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.


Creo que esta es la respuesta más precisa.
katericata

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.