Back when I started Watir, there was only one method to check for an element on the page – Element#exists?. Now, several versions later, there are three – Element#exists?, Element#visible? and Element#present?.
The three methods are not aliases of each other. They are different.
How are they different?
Exploring the Difference
From the watir-classic rdoc (and similarly in watir-webdriver), the three methods are described as:
- exists? – Returns whether this element actually exists.
- present? – Returns true if the element exists and is visible on the page
- visible? – If any parent element isn’t visible then we cannot write to the element. The only reliable way to determine this is to iterate up the DOM element tree checking every element to make sure it’s visible.
What does that actually mean or, more importantly, where does it matter?
Consider the following HTML page, which has one div tag that is visible (ie displayed) and one that is not.
<html> <body> <div id="1" style="display:block;">This text is displayed</div> <div id="2" style="display:none;">This text is not displayed</div> </body> </html>
When each method (exists?, present?, visible?) is run for the different elements (displayed, not displayed, non-existent), the following results are seen.
|Displayed (browser.div(:id => ‘1’))||true||true||true|
|Not Displayed (browser.div(:id => ‘2’))||true||false||false|
|Non-Existent (browser.div(:id => ‘3’))||false||false||exception|
Element#exists? checks if the element is in the DOM (or HTML). Element#visible? checks if the element can be seen by the user, but throws an exception if the element is not in the DOM. Element#present? is the same as Element#visible? except that it returns false, instead of an exception, when the element is not in the DOM.
While the three methods are definitely different, I think, at least from my experience, that you should typically be using Element#present?.
One point to keep in mind, especially for those working with legacy watir libraries/tests, is that .exists? can lead to false positives. Imagine you have a form. When the form is submitted, an error message is displayed for fields that fail validation (ex missing a required field). In some applications this will be implemented by simply changing the style of the element containing the error message from display:none to display:block. Now consider writing a test to check that the validation message is displayed. If you use .exists?, the test will have false positives (ie it will always pass since the element is always in the DOM). In this situation, .visible? or present? should have been used.