Mehavarnan Murugan
Mehavarnan Murugan

Reputation: 107

Selenium: Check for the presence of element

In real-time automation, do we check for the presence of every element (in test) before performing some action on them?

Wherever there is a findElement statement, there is a chance of NoSuchElementException. Should we check for the presence of the element every time?

Does every findElement statement need to be surrounded by a try-catch block?

Upvotes: 4

Views: 10307

Answers (5)

undetected Selenium
undetected Selenium

Reputation: 193218

Answering your questions one by one:

  • "In real-time automation, do we check for the presence of every element(in test) before performing some action on them": Yes, as per best practices, whenever user is redirected to a new page, you need to ensure the state of the element as per your desired action.

There are three most widely used ExpectedConditions which can be used in conjunction with WebDriverWait to validate an element's state as follows:

presenceOfElementLocated

presenceOfElementLocated(By locator) is defined as follows:

public static ExpectedCondition<WebElement> presenceOfElementLocated(By locator)

Description: An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.

visibilityOfElementLocated

visibilityOfElementLocated(By locator) is defined as follows:

public static ExpectedCondition<WebElement> visibilityOfElementLocated(By locator)

Description: An expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.

elementToBeClickable

elementToBeClickable(By locator) is defined as follows:

public static ExpectedCondition<WebElement> elementToBeClickable(By locator)

Description: An expectation for checking an element is visible and enabled such that you can click it.

  • "Wherever there is a findElement statement, there is a chance of NoSuchElementException": No, not at all. If you construct a proper Locator Strategy, you won't face NoSuchElementException.

Here you will find a detailed discussion on NoSuchElementExeption, selenium unable to locate element

  • Does every findElement statement need to be surrounded by try-catch block: No, not always. If your usecase involves handling of both affirmative and negative scenarios then a try-catch {} block is perfecto.

Upvotes: 1

DMart
DMart

Reputation: 2461

Short answer: No.

Longer answer: One approach is to wait until a "page is finished" indicator to use an explicit wait. This will signal you're safe to findElement's as needed. If one of those elements isn't available, the test will fail, indicating it couldn't find the element. Using Explicit waits as needed (when you expect the page/DOM to change) within the test.

But again, there is some opinion to this question and its answers. Checking/waiting for elements to be present every step along the way does have a cost in the time to run and may just prolong a test that could fail quicker.

Upvotes: 0

Bill Hileman
Bill Hileman

Reputation: 2836

The most direct, simplest way to check for the existence of a web element is to use findElements() (notice the plural) which returns an array, i.e.,

if (driver.findElements(By.xpath("//a")).isEmpty())
    // No links exist

The same method can be used to check for a single element; it does not have to be an array. A returned .size() of zero means there weren't any matches, and thus the desired element is not in the DOM.

A better method, some would argue, is to wrap the .findElement in a method which does do try/catch and logs/responds accordingly to various results, like element not found, or stale element, etc.

I use both methods in my tests, and use my own exists function with the .findElements logic, but I use the wrapper for other scenarios.

Upvotes: 0

lTyl
lTyl

Reputation: 156

There are two cases to account for:

  1. Is the element present; meaning does it exist in the DOM.
  2. Is the element visible; meaning it is in DOM and does not have a hidden or equivalent flag.

For the first case, I use the following helper method:

this.waitForElement = function(locator) {
    browser.wait(function() {
      return browser.isElementPresent(locator);
    }, testData.Timeout.TWO_MINUTES);
};

This will wait for an arbitrary amount of time for the element matching the provided locator to become present (It exists in the DOM).

For the second case, I use this helper method:

this.waitForElementIsVisible = function(el){
    let EC = protractor.ExpectedConditions;
    browser.wait(EC.visibilityOf(el), testData.Timeout.TWO_MINUTES, "Element did not become visible after 2 minutes");
};

This takes a WebElement as the single parameter and waits until the element becomes visible (it exists in the DOM and is not hidden via a CSS style or something).

As a bonus, I also found this helper method to be useful for testing error states in a form:

this.waitForElementIsClickable = function(el){
    let EC = protractor.ExpectedConditions;
    browser.wait(EC.elementToBeClickable(el), testData.Timeout.TWO_MINUTES, "Element did not become clickable after 2 minutes");
};

Takes a WebElement as the first parameter and waits until that WebElement can be clicked.

Note, I am using Protractor, and reference Protractor in these snippets. So unless you are using Protractor as well, it's likely these will not work 100% through a straight copy+paste. It should be easy enough to tweak them to suite your setup, though.

Upvotes: 3

GPT14
GPT14

Reputation: 819

You may find the use of the class AbstractWebDriverEventListener particularly useful. This class implements the interface WebDriverEventListener which defines before and after hooks for the events triggered by WebDriver.

One such before hook beforeFindBy could be implemented to check the presence of element. For example:

public void beforeFindBy(By by, WebElement element, WebDriver driver) {
    // Explicit wait to check for the presence of the element using the "by" locator
}

Similarly the before hook beforeClickOn could be implemented to check that the element is clickable before the click event is performed on that element.

Upvotes: 1

Related Questions