The information in this card is no longer accurate for modern Capybaras.
Short version
- Capybara has a global option (
Capybara.ignore_hidden_elements
) that determines whether Capybara sees or ignores hidden elements. - Prefer not to change this global option, and use the
:visible
option when callingpage.find(...)
. This way the behavior is only changed for this onefind
and your step doesn't have confusing side effects. - Every Capybara driver has its own notion of "visibility".
Long version
Capybara has an option (Capybara.ignore_hidden_elements
) to configure the default query behavior of finding nodes within the DOM. It's default value is false
. That means that your css or xpath queries will find all nodes in the document regardless of their visibility on the page. You can overwrite this behavior for an individual query by passing the :visible => true|false
option.
# default behavior for hidden elements
# Capybara.ignore_hidden_elements = false
# find all elements (hidden or visible)
page.all(".articles .article[id='foo']")
# find visible elements only (overwrite the standard behavior just for this query)
page.all(".articles .article[id='foo']", :visible => true)
# changing the default behavior (e.g. in your features/support/env.rb file)
Capybara.ignore_hidden_elements = true
# now the query just finds visible nodes by default
page.all(".articles .article[id='foo']")
# but you can change the default behaviour by passing the :visible option again
page.all(".articles .article[id='foo']", :visible => false)
But there is still one unanswered question. Capybara supports different drivers like RackTest
or Selenium
. The driver's interface defines a method called visible?
for nodes which raises an NotImplementedError
. That means each driver has to implement it's own detection when an element on the page is visible or not. I'll give you a short description of what visible?
does for RackTest
and Selenium
.
How Capybara::Driver::Node#visible? works for RackTest and Selenium
RackTest
RackTest is a simple browser simulator that is just aware of plain HTML represented as a string (HTTP response body). It does not evaluate CSS or JavaScript. It uses Nokogiri for parsing the response body. This way you can use query selectors to find nodes, click links and so on. Since CSS and JS are not respected, the visible?
method can only look for a style="display: none"
attribute set for the node or it's ancestors. Furthermore the visibility: hidden
rule is not checked at all.
Selenium
Selenium
Show archive.org snapshot
is an integration test framework that consists of different tools to test websites and web-applications with real browsers. Capybara has a driver for Selenium that wraps around
selenium-webdriver
Show archive.org snapshot
which is a Ruby binding to remote control real browsers via Selenium's WebDriver
API. What does that mean for capybara's visible?
method? Due to the fact that a real browser is used for your website tests, the browser itself is aware of all visible and hidden elements since it parses CSS rules and JavaScript, too.
Conclusion
In my opinion I would not recommend to ignore hidden elements by default unless you know what you are doing. The fact that hidden elements (by CSS or JS) can't be detected by RackTest but by Selenium makes it hard to change a test's driver.