When Capybara locates elements in the DOM, by default it allows only accessing visible elements -- when you are using a driver that supports it (e.g. Selenium, not the default Rack::Test
driver).
Consider the following HTML:
<div class="test1">One<div>
<div class="test2">Two</div>
With some CSS:
.test1 { display: block }
.test2 { display: none }
We will be using Capybara's find
below, but this applies to any Capybara finder methods.
Default: visible: :visible
or visible: true
As described above, by default Capybara finds only visible elements.
-
find('.test1')
finds the.test1
element -
find('.test2')
raises aCapybara::ElementNotFound
error, as the.test2
element is not rendered.
Using find(...)
means the same as find(..., visible: true)
or find(..., visible: :visible)
.
Note that you could change the default behavior by setting the ignore_hidden_elements
config option. However, ignoring invisible elements is a useful default.
Ignoring visibility with visible: :all
or visible: false
If you want to access the hidden .test2
element, you can do so by supplying an option visible: :all
.
Note that this only removes the visibility restriction, meaning:
-
find('.test1', visible: :all)
finds the.test1
element -
find('.test2', visible: :all)
finds the.test2
element
Note that Capybara also supports visible: false
as a synonym for visible: :all
.
Since it is not always clear that visible: false
means "both hidden and visible elements", I suggest you prefer :all
over false
.
Finding invisible elements with visible: :hidden
What if you want to test that .test1
is not visible? Use visible: :hidden
-
find('.test1', visible: :hidden)
raises aCapybara::ElementNotFound
error, as the.test1
element is not hidden. -
find('.test2', visible: :hidden)
finds the.test2
element
As an example, an RSpec test which tries to confirm an element exists but is currently not visible, would say:
expect(page).to have_css('.test2', visible: :hidden)