Checking for an element – exists?, visible?, present?

Observation

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

RDoc description

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?

Code example

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.

Element .exists? .present? .visible?
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.

Conclusion

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.

This entry was posted in Watir, Watir-Classic, Watir-Webdriver and tagged , , , , , . Bookmark the permalink.

6 Responses to Checking for an element – exists?, visible?, present?

  1. Jowett zhang says:

    Hello! This is a useful information. I met such problem. Some element exists, but not present, seems it cannot be operated, ie. click or other operations? If so, how to make it?

    • Justin Ko says:

      It would really depend on the page. First off, you should make sure that you are actually interacting with the right element. Then you need to figure out why the element is not visible. Is there an action that a user must take before they see the element – eg click something, mouse over something, etc? Watir is meant to mimic a user, so the script needs to do the same triggering actions.

      Can you provide a page that reproduces the issue?

  2. Roddy says:

    There is no “block” property in CSS; both divs in your example are shown. Did you mean “display: block” and “display: none”?

  3. David West says:

    funny enough if you use PageObject, some versions use .present? under the covers for .visible? and don’t even work with .present.

    Example code:

    on(MyPage) do |page|
    page.submit if page.div_element(id: ‘MyDiv’).visible?
    end

    .visible? in this case works with no exception if there is no div#MyDiv

    At least in Page Object 1.2.0 this is how PageObject::Platforms::WatirWebdriver::Element#visible? is defined

    def visible?
    element.present?
    end

    .present? throws an error in this case (looks not defined)

    If you ask me, this inconsistency adds to the confusion that could already exist here.

    • Justin Ko says:

      Agreed, that has been a cause of confusion.

      The good news is that the problem should be fixed in Page-Object v2.1. At least it looks like Page-Object no longer defines the #visible? and #present? methods. Instead it just delegate the methods directly to Watir. In other words, Page-Object and Watir should be consistent now.

Leave a comment