Tag Archives: wait

waiter2: Useful methods for working with dropdowns and Select

When it comes to selecting values from a classic HTML dropdown, in Selenium you need to perform a few tasks: first, define a WebElement that represents the dropdown as page element; then, using the WebElement, create a Select object; using the Select object, you can then choose an option from the dropdown. This latter option can be done by: visible text (specifying the option’s label), ‘value’ attribute (of the <option> HTML tag found under the <select> tag representing the dropdown, corresponding to which option you want to choose), or by index (position in the list of <option> tags).

Continue reading waiter2: Useful methods for working with dropdowns and Select

waiter2: Typing into fields

When it comes to typing, in the ‘waiter2’ library there are quite a few methods dedicated to this task. But there is a reason why there are so many (32 to be precise): they are different variations, given certain parameters, as the name suggests for each of them. Here are the considerations, whose combinations will give the method signatures:

Continue reading waiter2: Typing into fields

waiter2: Clicking on page elements

Clicking on a page element is easy to do, however sometimes this action might fail. This can be either because the element we want to click is not yet present on the page, or is not visible, or does not yet allow interactions. To help make sure the click succeeds, here are my dedicated wait based click methods.

Clicking a page element: click

There are 4 methods for clicking on a page element in the ‘waiter2’ library: 2 of them take the timeout parameter, 2 don’t. Additionally, 2 of them take a WebElement (defined with @FindBy) as parameter, 2 take a By variable:

public void click(WebElement elementToClick)
public void click(WebElement elementToClick, int specificTimeout)
public void click(By selectorForElementToClick)
public void click(By selectorForElementToClick, int specificTimeout) 

It is worth mentioning that there will never be a ‘waitForElementToBeDisplayed’ method in the library, simply because it is not needed. For example, when trying to click on a page element, there is no need to wait for it to be displayed before clicking. The logic inside the ‘click’ method from ‘waiter2’ retries clicking the element any time an Exception is encountered. If the element would not be present, the NoSuchElementException would be thrown for each click, until it either is displayed, or the timeout value has elapsed. Similarly, if the page element were present but not visible, or not clickable, the click action is tried until it succeeds or the timeout elapses. Any Exception that can be encountered while clicking is treated the same, because the generic ‘Exception’ is checked for and treated.

So basically, calling the click method while the element to be clicked is not yet ready, but in the process of being ready, will reliably click on it (given it loads within the specified timeout).

In case the element is not clickable for any reason within the specified timeout, a RunTimeException is thrown, with the message:

"waiter2.FAILURE: Could not successfully click on '" + elementToClick + "' within "
        + specificTimeout + " seconds."

The provided selector will be displayed, so that the tester knows what selector was looked for. This helps debug the failure.

Since version: 1.0

The code

The ‘click’ method variants that take a WebElement as parameter are:

public void click(WebElement elementToClick) {
    click(elementToClick, TIMEOUT);
}
public void click(WebElement elementToClick, int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver,
            Duration.ofSeconds(specificTimeout));
    try {
        ExpectedCondition<Boolean> condition = arg -> {
            try {
                elementToClick.click();
                return true;
            } catch (Exception e) {
                return false;
            }
        };
        wait.until(condition);
    }
    catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: Could not successfully click on '" + elementToClick + "' within "
                + specificTimeout + " seconds.");
    }
}

The ‘click’ method variants that take a By as parameter are:

public void click(By selectorForElementToClick) {
    click(selectorForElementToClick, TIMEOUT);
}
public void click(By selectorForElementToClick, int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver,
            Duration.ofSeconds(specificTimeout));
    try {
        ExpectedCondition<Boolean> condition = arg -> {
            try {
                driver.findElement(selectorForElementToClick).click();
                return true;
            } catch (Exception e) {
                return false;
            }
        };
        wait.until(condition);
    }
    catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: Could not successfully click on '" + selectorForElementToClick + "' within "
                + specificTimeout + " seconds.");
    }
}

Usage examples

The best usage for the ‘click’ method would be: providing a WebElement defined in a page object class with an @FindBy annotation. For example, for a page on which there is a button to click, whose id is “buttonToClick”, the corresponding WebElement is:

@FindBy(id = "buttonToClick") public WebElement buttonToClick;

Don’t forget that as per the setup, you need to do a PageFactory.initElements before using the WebElement. In the test, in order to click on this page element, you would just need to pass the WebElement as parameter to the ‘click’ method (shown here with the default timeout value):

waiter.click(page.buttonToClick);

In case you cannot create the WebElement through the @FindBy annotation, because it gets generated dynamically in the test, you can pass a By variable to the ‘click’ method. There are 2 ways you can do that: either by creating a By variable somewhere in the test and passing it to the method once it has the correct value. Or by creating a String variable somewhere in the test that represents the selector, then passing it to a By.yourSelectorType once it gets assigned the correct value. Below are some examples for the same button as above.

If you want to create a By variable, it would look like the following one (here obviously it represents an id):

By byForButtonToClick = By.id("buttonToClick");

You can now use it in the ‘click’ method:

waiter.click(byForButtonToClick);

If instead you want to create a variable only for the String representing a selector:

String selectorForButtonToClick = "buttonToClick";

Then, to click the corresponding element:

waiter.click(By.id(selectorForButtonToClick));

Note1: If the selector value is static (it is always the same), use the @FindBy approach. Only use the By approach if you cannot use the @FindBy one, due to not knowing at the beginning of the test what the selector will be (as it gets generated along the way).

Note 2: If you are using the By or the corresponding String only to click that item once, and not anywhere else in the test, DO NOT create a separate variable to store these. Just pass them inline, directly into the ‘click’ method, like, for example:

waiter.click(By.id("buttonToClick"));

In case the element specified with @FindBy cannot be clicked due to any reason within the specified timeout, the following RunTimeException is thrown:

java.lang.RuntimeException: waiter2.FAILURE: Could not successfully click on 'Proxy element for: DefaultElementLocator 'By.cssSelector: nonExistentElement'' within 30 seconds.

In case the element specified with By cannot be clicked on due to any reason within the specified timeout, the following RunTimeException is thrown:

java.lang.RuntimeException: waiter2.FAILURE: Could not successfully click on 'By.cssSelector: nonExistentElement' within 30 seconds.

Incorrect usage!

Never do the following:

WebElement buttonToClick = driver.findElement(By.id("buttonToClick"));
waiter.click(buttonToClick);

Why? Because if the button to click is not displayed when the ‘findElement’ method runs, the test fails at that step, and the ‘click’ method never executes.

So that’s it for clicking on page elements, which of course, include more than just a button. The test code can be found here. Next up i will discuss some further useful methods, so stay tuned!

waiter2: Opening a page and waiting for it to load

In this post I will describe what the get, wait for page load and wait for jquery to load methods from the ‘waiter2’ library do, and how to use them in your tests. For setup details, please read the previous post.

Waiting for a page to load: waitForPageLoadComplete

There are 2 methods with the name ‘waitForPageLoadComplete’. The first one does not take any parameters. The second one takes an int as parameter, corresponding to how many seconds to wait for the page to finish loading successfully. I will refer to the no parameter variant in the following paragraph.

This method simply waits for the page document and corresponding static resources to finish loading for up to 30 seconds (the default timeout set in the method). The method uses the ‘document.readyState’ property to check for this. When the value of this property is ‘complete’, the wait method exits successfully. If the condition is not met within the specified timeout, the method throws a RunTimeException, with the following message: “waiter2.FAILURE: Page did not finish loading within 30 seconds.”. This message should make it easy to identify, in the test output, why the test failed (in case the page did not load successfully during the specified timeout period).

Since version: 1.0

The code

The code of this method is:

public void waitForPageLoadComplete() {
    waitForPageLoadComplete(TIMEOUT);
}

This method actually calls the method variant that takes a specified timeout as parameter. It sets that timeout to the default value of 30 seconds, defined in the Waiter class through the TIMEOUT constant. This latter method is:

public void waitForPageLoadComplete(int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(specificTimeout));
    try {
        wait.until(driver -> String
                .valueOf(((JavascriptExecutor)
                        driver).executeScript("return document.readyState")).equals("complete"));
    } catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: Page did not finish loading within " + specificTimeout + " seconds.");
    }
}

Note: ideally you wouldn’t use this method directly. It is called from a method described below for opening a page (called ‘get’). Normally you would wait for a page to load after opening it.

Usage examples

Inside a test, once the waiter class was initialized and a driver instance was created, calling this method is simply done as:

waiter.waitForPageLoadComplete();

Waiting for jQuery to load: waitForJQuery

In order to wait for jQuery to finish loading, one of the 2 variants of the waitForJQuery method can be used: one without passing the timeout value as parameter (whose default timeout is 30 seconds) and another one that takes an int timeout value. If there is no jQuery on the page, the method exits immediately, successfully. Otherwise, in case it is present, the jQuery.active property is waited for, up to the defined timeout, to equal 0.

Since version: 1.0

The code

The method without parameters is as follows (and calls the other variant of the method, passing to it the TIMEOUT constant to specify 30 seconds as timeout):

public void waitForJQuery() {
    waitForJQuery(TIMEOUT);
}

The variant which takes an int parameter for the timeout is as follows:

public void waitForJQuery(int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver,
            Duration.ofSeconds(specificTimeout));
    try {
        ExpectedCondition<Boolean> condition = arg -> {
            try {
                return (Boolean) ((JavascriptExecutor)
                       
                       driver).executeScript("return jQuery.active == 0");
            } catch (Exception e) {
                return true;
            }
        };
        wait.until(condition);
    } catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: JQuery did not finish loading within "
                + specificTimeout + " seconds.");
    }
}

Note: like with waitForPageLoadComplete ideally you wouldn’t use this method directly. It is also called from a method described below for opening a page (called ‘get’).

Opening a page and waiting for it to load, together with jQuery: get

The ‘get’ method will be used for: opening a URL in the browser, followed by waiting for the page to load (by calling the waitForPageLoadComplete method), followed by waiting for jQuery to finish loading if present (by calling the waitForJQuery method).

For ‘get’ there are also 2 variants: one without a timeout parameter, and one to which you can pass an int for the timeout. For the version without the timeout parameter, the method will wait for up to 30 seconds for the page to load after opening the URL (which is done by calling Selenium’s ‘get’ method), then for up to 30 seconds for jQuery. So in total there will be a wait of up to 60 seconds. The other parameter taken by the method is a String that represents the URL you want to open.

Since version: 1.0

The code

The variant of the ‘get’ method with default timeout is (this method calls the one described right below it):

public void get(String url) {
    get(url, TIMEOUT);
}

The variant of the ‘get’ method to which you need to pass an int timeout value is:

public void get(String url, int specificTimeout) {
    driver.get(url);
    waitForPageLoadComplete(specificTimeout);
    waitForJQuery(specificTimeout);
}

Usage examples

Due to the methods called inside the ‘get’ method, in your tests you never have to call those methods yourself. Here of course I am talking about the wait for page and jQuery to load ones. This helps reduce the code you write in each of your tests, since otherwise you would have to write 3 lines of code every time you opened a page. Now you just need to write 1. To open a valid URL, just pass in the valid URL, and either no timeout value or a desired int value, representing seconds. For the first case, you would proceed as follows:

waiter.get("https://www.selenium.dev/documentation/");

Or, to wait for 60 seconds instead of the default 30:

waiter.get("https://www.selenium.dev/documentation/", waiter.MEDIUM_TIMEOUT);

So that’s it regarding the methods for opening and waiting for the page to load. The test code can be found here. Next up I will discuss some further useful methods, so stay tuned!

thewaiter: wait for WebElement attribute. To equal, contain a String, with variations.

An attribute of an HTML tag (or WebElement as you might know it from Selenium) stores valuable information about the state of that element. If we are thinking of checkboxes, a “checked” attribute will signal whether the checkbox is selected or not. For a link, the “href” attribute will tell us what location on the web it points to.

There will be times when your Selenium tests will need for an attribute of a WebElement to have an expected value. This signals that the state you expect your product to be in is correct. Before any other steps will be performed, you will need to make sure that the value of the attribute is correct, and for this process asserts are quite frequent. Enter “thewaiter” library, which has methods for you to wait for the attributes, not only to equal a text, but to also contain it, or to equal/contain it ignoring whitespaces or the case. Continue reading thewaiter: wait for WebElement attribute. To equal, contain a String, with variations.

How WebDriverWait works differently for WebElements defined by driver.findElement versus PageFactory initialization

When it comes to using WebDriverWait to wait for WebElement properties,like text or attributes, when sending WebElements as properties generated via PageFactory, that will work properly. However when using ‘driver.findElement()’ to identify the WebElements required as parameters in the WebDriverWaits, that will fail. Here is the reason why. Continue reading How WebDriverWait works differently for WebElements defined by driver.findElement versus PageFactory initialization

Use waits as assertions for your Selenium tests

Selenium tests tend to make a lot of use of assertions, to check that some actions have been performed on the front-end or that some WebElement properties are the expected ones. And by assertions, I mean, mostly: assertEquals or assertTrue, as these are the most commonly used ones.

Assertions fail too often due to the condition they are checking not being fulfilled by the time the assertion code executes. Had the assertion run a few seconds later, in many cases, it would have passed. It’s all about timing. In my previous posts I described some of the WebDriverWait based methods you can find in my ‘thewaiter’ library. In this post I want to highlight how you can use these methods to replace your assertions. Continue reading Use waits as assertions for your Selenium tests

thewaiter: wait for WebElement text. To equal, contain a String with variations.

Element text is something you will often check for when writing Selenium tests. Whether it equals a given String, or contains a given String. But you can extend your checks to whether: the element text equals/contains a String ignoring the case of the two, or whether the element text equals/contains a String ignoring any whitespace the two might contain. Continue reading thewaiter: wait for WebElement text. To equal, contain a String with variations.

thewaiter: wait for an element to be displayed with Selenium

A very hot topic when testing with Selenium is how to wait for a WebElement to be displayed. I wrote about this some while back, and that post is one of my most read on this blog. In this new post i will revisit the subject, by providing a new version of that method, using Java 8. It can be found in ‘thewaiter’ library in two variants: with a default timeout, and with a signature that allows a timeout parameter to be specified when calling it. Continue reading thewaiter: wait for an element to be displayed with Selenium

thewaiter: waiting for a URL in the browser to equal or contain a String, with Selenium

In some tests it is not enough to just wait for a page to fully load, but instead you need to make sure that the URL corresponding to that page is the expected one. Maybe you clicked on a button and need to make sure an expected page/URL opened, or maybe you are opening a page but a redirect changes the URL to something else than the initial page had. For such tests you can use the URL related wait methods from ‘thewaiter’ library, to wait until the URL is the correct one, before performing the rest of the test. Continue reading thewaiter: waiting for a URL in the browser to equal or contain a String, with Selenium