How to click first link in list of items after upgrading to Capybara 2.0?
Solution 1
You can just use:
first('.item').click_link('Agree')
or
first('.item > a').click
(if your default selector is :css)
Code in your question doesn't work as:
within ".item" do
first(:link, "Agree").click
end
is equivalent to:
find('.item').first(:link, "Agree").click
Capybara finds several .item
's so it raises an exception. I consider this behavior of Capybara 2 very good.
Solution 2
Try the following:
within ".item" do
click_link("Agree", :match => :first)
end
Sources:
- http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions#click_link-instance_method
- https://github.com/jnicklas/capybara#strategy
Solution 3
This phrasing also works:
within first(".item") do
click_link "Agree"
end
Solution 4
most of those solutions will not use Capybara's brilliant waiting features
better do as this link suggests:
https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara#find-the-first-matching-element
Bad:
first(".active").click
If there isn’t an .active element on the page yet, first will return nil and the click will fail.
Good:
If you want to make sure there's exactly one
find(".active").click
If you just want the first element
find(".active", match: :first).click
Capybara will wait for the element to appear before trying to click.
Note that match: :first
is more brittle, because it will silently click on a different element if you introduce new elements which match.
Solution 5
Xpath can address the element. I'm not very good with it yet, but something like //div[@class='active'][1]/a
That may or may not work, but the point is that xpath can address an array of matches and pull out a particular one. You should be able to match with this.
A working example example from one of my projects:
within page.find("div.panel", text: /Proposals/) do within page.find('tr', text: /Foo/) do page.should have_xpath('td[3]', text: @today) end end
tomekfranek
Updated on June 18, 2020Comments
-
tomekfranek almost 4 years
How to click first link in that case:
<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
and I get this error:
Capybara::Ambiguous: Ambiguous match, found 2 elements matching css ".item"
And without the
within
I get this error:Failure/Error: first(:link, "Agree").click NoMethodError: undefined method `click' for nil:NilClass
-
Dono over 10 yearsamazing. And it works on simple page.find('#{css}', :match => :first).click Cheers for the really helpful answer
-
Mauricio Moraes over 9 yearsWorked for me, thanks. Capybara 2.4.1 and poltergeist.
-
dgtized over 7 yearsI would recommend against using #first, it doesn't wait for an element to exist: rubydoc.info/github/jnicklas/capybara/…. If the content was created at runtime with JS first will return nil if it runs the expectation before the link is created.
-
keoghpe almost 7 yearsThis example isn't relevant to capybara
-
emptywalls almost 7 yearsIsn't that jQuery?
-
katericata about 4 yearsI believe this is the most accurate answer.
-
notapatch over 2 years