Capybara Ambiguity Resolution

My solution is

first(:link, link).click

instead of

click_link(link)

Such behavior of Capybara is intentional and I believe it shouldn't be fixed as suggested in most of other answers.

Versions of Capybara before 2.0 returned the first element instead of raising exception but later maintainers of Capybara decided that it's a bad idea and it's better to raise it. It was decided that in many situations returning first element leads to returning not the element that the developer wanted to be returned.

The most upvoted answer here recommend to use first or all instead of find but:

  1. all and first don't wait till element with such locator will appear on the page though find does wait
  2. all(...).first and first won't protect you from situation that in future another element with such locator may appear on the page and as the result you may find incorrect element

So it's adviced to choose another, less ambiguous locator: for example select element by id, class or other css/xpath locator so that only one element will match it.


As a note here are some locators that I usually consider useful when resolving ambiguity:

  • find('ul > li:first-child')

    It's more useful than first('ul > li') as it will wait till first li will appear on the page.

  • click_link('Create Account', match: :first)

    It's better than first(:link, 'Create Account').click as it will wait till at least one Create Account link will appear on the page. However I believe it's better to choose unique locator that doesn't appear on the page twice.

  • fill_in('Password', with: 'secret', exact: true)

    exact: true tells Capybara to find only exact matches, i.e. not find "Password Confirmation"