In a view file I have:
= link_to \'View\', post
= link_to \'View\', comment
In a spec file (I\'m using Capybara):
click_on
There's probably a few ways but I usually scope something like this.
within(".comment") do
click_on("View")
end
There's quite possibly/probably alternatives as well. I usually do my acceptance testing from cucumber, so my steps typically look like
When I follow "View" within the comment element
Where I have a step that translates within the comment element
to a scoped call to the step itself (which I think is built into the latest capybara web_steps)
There are many ways for solving this type of problems.
Do it like this
if(page.find("a")[:href] == "comment")
click_on("View")
or
page.find("a:eq(2)").click
Remember javascript indexing starts with 0 while In Capybara, indexing starts with 1. So use a:eq(2) here for second href.
If you use capybara-ui you could define the widget, or reusable DOM reference, for each widget.
# define your widget. in this case,
# we're defining it in a role
widget :view_post, ['.post', text: 'View']
widget :view_comment, ['.comment', text: 'View']
# then click that widget in the test
role.click :view_post
role.click :view_comment
For capybara 2
solution:
within(".comment") do
click_on("View")
end
would not help if you have a few .comment
. So simple use: page.first(:link, "View").click
The worst thing about "the second" link is that it can become the third or the first or even the twenty fifth someday. So, scoping with a within
block is the best way. Example:
within(".comment") do
click_on("View")
end
But if it is difficult to specify the link with a within
scope (which sometimes it really is), I guess the way to click the second link with a certain text is:
find(:xpath, "(//a[text()='View'])[2]").click
In later versions of capybara (2.0.2
, for example) both click_on 'View' and click_link 'View' will raise an ambiguous match error:
Failure/Error: click_on 'View'
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching link or button "View"
So this won't do even if you want to click the first link (or if any link would be ok, which is my case).
As far as I understand this is made to force people write more specific tests where particular links are clicked.
It definitely could be tricky to debug the code if you accidentally placed two or more links with identical text and try to see what is happening. It's good to rely on something that is unlikely to change and specifying a link with a within
block is a nice way to do this.
You could try to find all entries and deal with an array:
page.all('a')[1].click
Would help to have a class or use within to scope your search ;)