¿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.