Fixing Capybara 2.0 and Labels
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
module XPath::HTML protected 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) locate_field[~attr(:disabled)] end end
And you should be all set!