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.

The classic approach for such a task would be something like: open the page or interact with the UI in a way that triggers a page redirect, wait for it to load (or use the undesirable Thread.sleep) and assert that driver.getCurrentUrl() (which is the code for extracting the current URL of the opened page) equals the expected String.

By using the URL related wait methods from ‘thewaiter’ library, you will wait for the URL to equal or contain an expected String, which removes the need for the assert and the sleep.

The wait methods

Because the URL is a String, when you wait for it, you can wait for quite a few events (these are implemented in ‘thewaiter’ library):

  • for the URL to equal an expected String
  • for the URL to contain an expected String
  • for the URL to equal an expected String, ignoring the case of both Strings
  • for the URL to contain an expected String, ignoring the case of both Strings
  • for a URL to start with an expected String

See below details for each of these methods. Each of these methods has two variants: one which has an additional parameter which is the timeout value, the other one without the parameter. The method without this parameter will use the default timeout value from the Waiter class.

What these methods do:

  • within the allocated timeout period, they extract the browser’s URL, by using ‘driver.getCurrentUrl()‘, and compare the value of the resulting URL with the expected one. This is done every half a second, until the timeout is up, or the condition was successful, within the timeout period.
  • if the condition is met when the check is made, meaning the URL is what you expect it to be (depending on the method, you will check if it equals or contains something), there is an additional wait that executes, which is the waitForPageLoadComplete. This was added so that you don’t only wait for the URL in the browser, but also for the page to be fully available, should you try to interact with it further. Therefore, in your tests, you don’t need to add a call to waitForPageLoadComplete after calling the wait for URL methods.
  • if the condition is not met (the URL is different than the expected one), other attempts are made, every half a second, until either the timeout elapses or the URL is the expected one (within the allocated timeout).
  • if the timeout period expires and the condition is still not true, a TimeoutException is thrown
  • note that if the condition was met, which means the waitForPageLoadComplete also executes, it will also wait for up to the same timeout period. That means: if let’s say you use the default timeout period (which is 30 seconds), you will wait for up to 30 seconds for the URL to be what you expected, plus an additional up to 30 seconds for the page to wait. Hopefully the site moves fast, and you will only wait a little bit before the wait method is done successfully. If instead of using the default timeout period, you specify the timeout you want, than the url related part of the wait method will wait for up to the specified timeout, then the page load method will also wait up to that specified timeout.

You can also use a method that opens a URL and waits for another one to be loaded. This is just a method that first calls the get method from ‘thewaiter’ library, then calls the waitForUrl method described below, which waits for the URL to be a specific one.

First, the code for all the URL wait methods is shown below, after which an Examples section show the usage of each of them.

The wait methods: waitForUrl

These methods check that the URL is an expected one. With the timeout parameter that needs to be provided to the method:

public void waitForUrl(String url, WebDriver driver, int specifiedTimeout) {
   WebDriverWait wait = new WebDriverWait(driver,    specifiedTimeout);
   ExpectedCondition<Boolean> urlIsCorrect = arg0 ->               driver.getCurrentUrl().equals(url);
   wait.until(urlIsCorrect);
   waitForPageLoadComplete(driver, specifiedTimeout);
}

The variant without the timeout parameter:

public void waitForUrl(String url, WebDriver driver) {
    waitForUrl(url, driver, TIMEOUT);
}
The wait methods: waitForUrlContains

These methods wait for the URL to contain an expected String. With the timeout parameter that needs to be provided to the method:

public void waitForUrlContains(String expectedString, WebDriver driver, int specifiedTimeout) {
   WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
   ExpectedCondition<Boolean> urlIsCorrect = arg0 ->    driver.getCurrentUrl().contains(expectedString);
   wait.until(urlIsCorrect);
   waitForPageLoadComplete(driver, specifiedTimeout);
}

The variant without the timeout parameter:

public void waitForUrlContains(String expectedString, WebDriver driver) {
   waitForUrlContains(expectedString, driver, TIMEOUT);
}
The wait methods: waitForUrl_IgnoreCase

These methods wait for a URL to equal an expected String but without taking into account the case of the two. So, for example, “https”  and “HttPs” are equal from this methods’ perspective.

With the timeout parameter that needs to be provided to the method:

public void waitForUrl_IgnoreCase(String url, WebDriver driver, int specifiedTimeout) {
   WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
   ExpectedCondition<Boolean> urlIsCorrect = arg0 ->    driver.getCurrentUrl().toLowerCase().equals(url.toLowerCase());
   wait.until(urlIsCorrect);
   waitForPageLoadComplete(driver, specifiedTimeout);
}

The variant without the timeout parameter:

public void waitForUrl_IgnoreCase(String url, WebDriver driver) {
   waitForUrl_IgnoreCase(url, driver, TIMEOUT);
}
The wait methods: waitForUrlContains_IgnoreCase

These methods wait for the URL to contain an expected String, but without taking the case into consideration. As as example:  if using “http://thisUrl&#8221; as the current URL, and “URL” as the String expected to be part of the URL, the wait method will be successful.

With the timeout parameter that needs to be provided to the method:

public void waitForUrlContains_IgnoreCase(String expectedString, WebDriver driver, int specifiedTimeout) {
   WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
   ExpectedCondition<Boolean> urlIsCorrect = arg0 ->    driver.getCurrentUrl().toLowerCase().contains(expectedString.toLowerCase());
   wait.until(urlIsCorrect);
   waitForPageLoadComplete(driver, specifiedTimeout);
}

The variant without the timeout parameter:

public void waitForUrlContains_IgnoreCase(String expectedString, WebDriver driver) {
waitForUrlContains_IgnoreCase(expectedString, driver, TIMEOUT);
}
The wait methods: waitForUrlStartsWith

This method waits for a URL to start with an expected prefix. It uses the “startsWith” method from Java’s String class to check the prefix. However i did not find, in the official documentation, how many characters this prefix can have. From my tries, it works with 5 characters, but i am not sure about a longer String. So use with care.

With the timeout parameter that needs to be provided to the method:

public void waitForUrlStartsWith(String expectedString, WebDriver driver, int specifiedTimeout) {
   WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
   ExpectedCondition<Boolean> urlIsCorrect = arg0 ->   driver.getCurrentUrl().startsWith(expectedString);
   wait.until(urlIsCorrect);
   waitForPageLoadComplete(driver, specifiedTimeout);
}

The variant without the timeout parameter:

public void waitForUrlStartsWith(String expectedString, WebDriver driver) {
   waitForUrlStartsWith(expectedString, driver, TIMEOUT);
}
The wait methods: getUrlAndWaitForUrl

These methods simply open a specified URL, then wait for another specified URL to load in the browser, and also for the page corresponding to the latter URL to fully load.

With the timeout parameter that needs to be provided to the method:

public void getUrlAndWaitForUrl(String urlToGet, String urlToWaitFor, WebDriver driver, int specifiedTimeout) {
driver.get(urlToGet);
waitForUrl(urlToWaitFor, driver, specifiedTimeout);
}

The variant without the timeout parameter:

public void waitForPageLoadComplete(WebDriver driver) {
waitForPageLoadComplete(driver, TIMEOUT);
}
Examples

In order to see how these methods work, let’s take a look at some examples. You can see all the code from these examples at the following GitHub location:  https://github.com/iamalittletester/learning-project/blob/master/src/test/java/waitertests/UrlTest.java . In case you are wondering, the ‘click‘ methods used below are also part of ‘thewaiter’ library and are described in my previous post.

  • Wait for URL to equal String: You go to a page. In the search field you need to type the search term, which is ‘checkstyle’. After hitting Enter from the keyboard, you need to check that you are redirected to the search results page for the term you just searched. In this example, since i am searching on my own blog, i need to wait for the URL to become: https://imalittletester.com/?s=checkstyle . Because i am using this wait, i do not need to add another assertion that would check that the URL is correct, since instead i am WAITING for it to become correct. The default timeout of 30 seconds (defined in ‘thewaiter’ library) is used, so no timeout parameter will be passed to the wait method (which, by the way, is called waitForUrl). The test is as follows:
waiter.click(page.searchButton, driver);
page.searchField.sendKeys("checkstyle");
page.searchField.sendKeys(Keys.ENTER);
waiter.waitForUrl("https://imalittletester.com/?s=checkstyle", driver);
  • Wait for the URL to contain a String: In this example you will again search for a term, but this time, you will only wait for the search result page to contain a String (not equal it). You will only be interested in the results page to contain the exact word you typed in the search box. The wait method used will be  waitForUrlContains, and it will use the default timeout value from ‘thewaiter’ library.
waiter.click(page.searchButton, driver);
page.searchField.clear();
page.searchField.sendKeys("waiter");
page.searchField.sendKeys(Keys.ENTER);
waiter.waitForUrlContains("waiter", driver);
  • Waiting for a url to equal an expected String but ignoring the case: In this example you will search for a term with a mix of upper and lower case letters, but you are not interested if in the result page url the term you searched for is in upper case or lower case. You are just interested that the search term that was used was kept and added to the url, even if the case is not the same. The waitForUrl_IgnoreCase method is used for this purpose, with the default timeout value.
waiter.click(page.searchButton, driver);
page.searchField.clear();
page.searchField.sendKeys("CheckStyle");
page.searchField.sendKeys(Keys.ENTER);
//the actual URL that will open here is: https://imalittletester.com/?s=CheckStyle
waiter.waitForUrl_IgnoreCase("https://imalittletester.com/?s=checkstyle", driver);
  • Wait for a url to contain a String, ignoring the case: in this case the search is done for a term containing only upper case, but for the search results page we are only interested in it containing the word searched by. The case of the search term is irrelevant, therefore it will be ignored, by using the ‘waitForUrlContains_IgnoreCase‘ method, with default timeout.
waiter.click(page.searchButton, driver);
page.searchField.clear();
page.searchField.sendKeys("WAITER");
page.searchField.sendKeys(Keys.ENTER);
//the actual url that will open is: https://imalittletester.com/?s=WAITER
waiter.waitForUrlContains_IgnoreCase("waiter", driver);
  • Opening a URL and waiting for another URL to be loaded (waiting for a redirect).
 waiter.getUrlAndWaitForUrl("https://imalittletester.com/", "https://imalittletester.com/", driver);
  • Same as before, but with a specified timeout of 5 seconds:
 waiter.getUrlAndWaitForUrl("https://imalittletester.com/", "https://imalittletester.com/", driver, 5);
  • Waiting for a URL to start with a prefix: below is an example in which you open a URL, and wait for the URL in the browser to start with a specified prefix, a String.
waiter.get("http://imalittletester.com", driver);
waiter.waitForUrlStartsWith("https", driver);

For examples on how to use these same methods by specifying the additional timeout parameter, please refer to the example classes described at the end of this post.

Where to find the code and  examples

The GitHub repo of thewaiter library, with a “how to use” documentation:

https://github.com/iamalittletester/thewaiter

The downloadable release version of thewaiter:

https://mvnrepository.com/artifact/com.imalittletester/thewaiter

The library’s javadoc:

http://javadoc.io/doc/com.imalittletester/thewaiter/1.0

The tests that use the methods from this post:

https://github.com/iamalittletester/learning-project/blob/master/src/test/java/waitertests/UrlTest.java

https://github.com/iamalittletester/learning-project/blob/master/src/test/java/waitertests/GetTest.java

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.