Capybara allows you to select DOM elements, e.g. by using field
, find_field(...)
or field_labeled(...)
:
role_select = field_labeled('Role')
In the example above, role_select
is now a Capybara::Driver::Node
. You can call a number of methods on such a node, e. g. in order to click it or to make a selection on its descendants. These methods should be the same regardless of the driver Capybara is using (drivers are e.g. the headless Rack::Test or Selenium).
It is a stupid idea to call #node
on such a Capybara node, as you see here:
selection = role_select.node.search(".//option[@selected = 'selected']")
Why is this stupid? Because #node
returns the internal node representation used by the driver, e.g. instances Nokogiri::XML::Element
if you are using Rack::Test, or of Selenium::WebDriver::Element
if you are using Selenium. Because the API of these classes vary from driver to driver, the code above is now Rack::Test only and won't work with Selenium. Remember that the whole point of Capybara is to be able to switch out drivers without code changes.
If possible, don't call methods on #node
and use the driver-independent Capybara API for everything. The example above should be written like this:
selection = role_select.find(:xpath, ".//option[@selected = 'selected']")
We're guilty of this in many of the step definitions we've posted. If you encounter such a piece of code, please rewrite it to be driver-neutral and update the note.