Whether you’re writing feature specs using MiniTest, RSpec or Cucumber, you’re probably using Capybara to select elements. But, what happens when you’re trying to query a single selector and yet, there are multiples?
The Problem
Recently this question/example appeared on Reddit.
“How can I use Capybara’s within block on a page with multiple instances of a class?”
The example provided looked something like the following.
A HAML view:
.page-header %h4 Some Header .page-header %h4 Another Header
A Capybara/RSpec test:
within '.page-header' do expect(page).to have_content 'Some Header'end within '.page-header' do expect(page).to have_content 'Another Header'end
When the user tried to run the test, they’d get the following error:
Capybara::Ambiguous: Ambiguous match, found 2 elements matching visible CSS “.page-header”
The problem is, as the user stated, there are multiple elements in that view with the ‘page-header’ class. Capybara doesn’t know which one we want to use.
The Solution
Fortunately, there are multiple ways to combat this problem. Today, though, I just want to show an easy-to-use, built-in method to solve this problem.
#all
The #all method will return a Capybara::Result. The result is, essentially, an array of Node Elements. Result takes advantage of Ruby’s Enumerable Module.
Now, we can grab the specific header by getting its index in the result.
within all('.page-header')[0] do ...end within all('.page-header')[1] do ...end
There are more ways to solve this problem. However, sometimes a simple method like this can be all you need.
Follow me on Twitter.