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
As described above, by default Capybara finds only visible elements.
-
find('.test1')finds the.test1element -
find('.test2')raises aCapybara::ElementNotFounderror, as the.test2element 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
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.test1element -
find('.test2', visible: :all)finds the.test2element
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::ElementNotFounderror, as the.test1element is not hidden. -
find('.test2', visible: :hidden)finds the.test2element
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)