Fixing Capybara 2.0 and Labels

Brian Cardarella

CEO & Founder

Brian Cardarella

I love Capybara, it makes integration testing a breeze. However, one of the decisions made for Capybara 2.0 confuses an annoys me. In Capybara 1.x you could do the following:

fill_in 'Password', :with => '123456'
fill_in 'Password confirmation', :with => '123456'

And everything worked. In Capybara 2.0 this does not work. Capybara will notice two labels that contain ‘Password’ and complain about an ambiguous locator. The suggested work around is to attach meta data to the input element and use that for the selector. There are two reasons why I don’t like this. First, I am doing Ember development now and I have no control of the ID, it is generated by the framework. Second, I believe that the integration test should be recreating the steps (as much as possible) as if a user were actually using the app. Something like:

fill_in '[data-name="password"]', :with => '123456'
fill_in '[data-name="password_confirmation"]', :with => '123456'

Doesn’t sit right with me. Users are looking at the text, not the selectors. I get that apps have the ability to show different languages but that doesn’t conern me, I don’t need to test if the Rails i18n works or not. I just care about asserting the happy and sad paths in my app.

So, to fix this problem simply add the following code into your test_helper.rb

module XPath::HTML

  def locate_field(xpath, locator)
    locate_field = xpath[attr(:id).equals(locator) | attr(:name).equals(locator) | attr(:placeholder).equals(locator) | attr(:id).equals(anywhere(:label)[string.n.equals(locator)].attr(:for))]
    locate_field += descendant(:label)[string.n.contains(locator)].descendant(xpath)

And you should be all set!


Stay in the Know

Get the latest news and insights on Elixir, Phoenix, machine learning, product strategy, and more—delivered straight to your inbox.

Narwin holding a press release sheet while opening the DockYard brand kit box