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.

What does an attribute look like anyway? Here is an example, which represents an image in HTML:

 <img src="some.jpg" alt="This is an alt text" style="width:100%" class="someClass">

This HTML element has 4 attributes:

  • the ‘src‘, whose value is “some.jpg”
  • the ‘alt‘, whose value is “This is an alt text”
  • the ‘style‘, whose value is “width:100%”
  • the ‘class‘, whose value is “someClass”
The wait methods

So, as i mentioned, there are 6 attribute related wait methods in ‘thewaiter’ library, all of which use Seleniums’ ‘getAttribute()’ method to read these attributes from the page. The wait methods available in ‘thewaiter’ library can be used for waiting for:

  • a specified attribute of a specified WebElement to equal an expected String
  • a specified attribute of a specified WebElement to equal an expected String, but ignoring the case of the expected and actual attribute values
  • a specified attribute of a specified WebElement to equal an expected String, but ignoring all the whitespace characters in the expected and actual attribute values
  • a specified attribute of a specified WebElement to contain an expected String
  • a specified attribute of a specified WebElement to contain an expected String, but ignoring the case of the expected and actual attribute value
  • a specified attribute of a specified WebElement to contain an expected String, but ignoring all the whitespace characters in the expected and actual attribute value
How getAttribute() works

What to keep in mind regarding the attribute value: when you read it via Selenium, you use the ‘getAttribute()’ method. It will return a String, that contains the entire attribute value.

Let’s think about the most common attribute, which is ‘class‘. Often when you are looking at the ‘class‘, you will see several ‘values‘ for it. Take a look below, where i exemplify a button:

<button type="button" class="btn btn-primary active">Active Primary Button</button>

Whenever we use selectors to identify the button based on ‘class‘, we tend to say that is has ‘several classes‘, namely: ‘btn’, ‘btn-primary’ and ‘active’ in this case. However, by calling ‘getAttribute()‘ on this element, for retrieving the value of the ‘class‘, we will just get one String that contains all the classes, just as shown above:  “btn btn-primary active”.

Therefore, since the wait methods are based on Seleniums’ getAttribute() method, make sure you know your expectations: if you have multiple ‘values‘ on the class, delimited by spaces, and you are interested in only one of them to be present on the WebElement (for example: ‘btn-primary’), use the ‘wait for contains’ methods. Otherwise, if you expected all of those ‘values‘ to be found in the ‘class‘ attribute, use the ‘wait for equals methods’.

You will see examples in this article, right after i show you what these wait methods are.

The wait methods: waitForElementAttributeEqualsString

With specified timeout:

public void waitForElementAttributeEqualsString(WebElement element, String attribute, String expectedString,
WebDriver driver, int specifiedTimeout) {
WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
ExpectedCondition<Boolean> elementAttributeEqualsString = arg0 -> element.getAttribute(attribute).equals
(expectedString);
wait.until(elementAttributeEqualsString);
}

With default timeout:

public void waitForElementAttributeEqualsString(WebElement element, String attribute, String expectedString,
WebDriver driver) {
waitForElementAttributeEqualsString(element, attribute, expectedString, driver, TIMEOUT);
}
The wait methods: waitForElementAttributeEqualsString_IgnoreCase

With specified timeout:

public void waitForElementAttributeEqualsString_IgnoreCase(WebElement element, String attribute, String
expectedString, WebDriver driver, int specifiedTimeout) {
WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
ExpectedCondition<Boolean> elementAttributeEqualsStringIgnoreCase = arg0 -> element.getAttribute(attribute)
.equalsIgnoreCase
(expectedString);
wait.until(elementAttributeEqualsStringIgnoreCase);
}

With default timeout:

public void waitForElementAttributeEqualsString_IgnoreCase(WebElement element, String attribute, String
expectedString, WebDriver driver) {
waitForElementAttributeEqualsString_IgnoreCase(element, attribute, expectedString, driver, TIMEOUT);
}
The wait methods: waitForElementAttributeEqualsString_IgnoreWhitespaces

With specified timeout:

public void waitForElementAttributeEqualsString_IgnoreWhitespaces(WebElement element, String attribute, String
expectedString, WebDriver driver, int specifiedTimeout) {
WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
ExpectedCondition<Boolean> elementAttributeEqualsStringIW = arg0 -> element.getAttribute(attribute)
.replaceAll("\\s", "").equals(expectedString.replaceAll("\\s", ""));
wait.until(elementAttributeEqualsStringIW);
}

With default timeout:

public void waitForElementAttributeEqualsString_IgnoreWhitespaces(WebElement element, String attribute, String
expectedString, WebDriver driver) {
waitForElementAttributeEqualsString_IgnoreWhitespaces(element, attribute, expectedString, driver, TIMEOUT);
}
The wait methods: waitForElementAttributeContainsString

With specified timeout:

public void waitForElementAttributeContainsString(WebElement element, String attribute, String expectedString,
WebDriver driver, int specifiedTimeout) {
WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
ExpectedCondition<Boolean> elementAttributeContainsString = arg0 -> element.getAttribute(attribute).contains
(expectedString);
wait.until(elementAttributeContainsString);
}

With default timeout:

public void waitForElementAttributeContainsString(WebElement element, String attribute, String expectedString,
WebDriver driver) {
waitForElementAttributeContainsString(element, attribute, expectedString, driver, TIMEOUT);
}
The wait methods: waitForElementAttributeContainsString_IgnoreCase

With specified timeout:

public void waitForElementAttributeContainsString_IgnoreCase(WebElement element, String attribute, String
expectedString, WebDriver driver, int specifiedTimeout) {
WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
ExpectedCondition<Boolean> elementAttributeContainsStringIC = arg0 -> element.getAttribute(attribute)
.toLowerCase()
.contains(expectedString.toLowerCase());
wait.until(elementAttributeContainsStringIC);
}

With default timeout:

public void waitForElementAttributeContainsString_IgnoreCase(WebElement element, String attribute, String
expectedString, WebDriver driver) {
waitForElementAttributeContainsString_IgnoreCase(element, attribute, expectedString, driver, TIMEOUT);
}
The wait methods: waitForElementAttributeContainsString_IgnoreWhitespaces

With specified timeout:

public void waitForElementAttributeContainsString_IgnoreWhitespaces(WebElement element, String attribute, String
expectedString, WebDriver driver, int specifiedTimeout) {
WebDriverWait wait = new WebDriverWait(driver, specifiedTimeout);
ExpectedCondition<Boolean> elementAttributeContainsStringIW = arg0 -> element.getAttribute(attribute)
.replaceAll("\\s", "")
.contains(expectedString.replaceAll("\\s", ""));
wait.until(elementAttributeContainsStringIW);
}

With default timeout:

public void waitForElementAttributeContainsString_IgnoreWhitespaces(WebElement element, String attribute, String
expectedString, WebDriver driver) {
waitForElementAttributeContainsString_IgnoreWhitespaces(element, attribute, expectedString, driver, TIMEOUT);
}

Examples

In order to show how these wait methods work, i created a page that can be opened in the browser, and that only has a checkbox and a label (a text in a <p> tag). The first time you open this page in the browser, that text has a black color:

After that, each time you click on the checkbox, the text changes color. When the checkbox is checked, the text is green.

When the checkbox is not checked, the text is red.

After each checkbox interaction, an attribute on the <p> element is changing, which determines the color: the style attribute. So, whenever the checkbox is checked, the ‘style’ attribute contains a ‘color: green;’ value, apart from another value, ‘display: block;’ (which is used for specifying where the text is displayed). The ‘color’ part of the ‘style’ attribute determines what color the corresponding page element will be.

Whenever the checkbox is not checked, the ‘color: red;’ value will be present in the ‘style’ attribute of the <p> label element, instead of the ‘color: green;’ one.

So, in order to check how the color changes on the label, i created some tests. First, i created a PageObject class in which i defined the WebElements corresponding to the checkbox and the label.

@FindBy(how = CSS, using = "#theCheckbox") public WebElement checkBoxElement;
@FindBy(how = CSS, using = "#theText") public WebElement textElement;

In the test class i just initialized the PageObject class that i stored the WebElements in, and i created a variable called ‘page‘ to use this class.

Then, the ‘checkTheCheckbox()’ method was created, which does nothing more than click on the checkbox.  The tests for waiting for the attributes are as follows (omitting the test method declaration, just focusing on the actual testing):

  • wait for attribute equals: in this test, i first opened the page. Then i clicked the checkbox for the first time and i waited for the text to become green. This means i waited for the ‘style‘ attribute to equal ‘display: block; color: green;‘. Notice that in this wait, since i am using ‘equals’ and the ‘style‘ attribute contains something else, not just the color part, i need to wait for the entire value for that ‘style‘ attribute to be the expected one. After this, i click the checkbox again and i want to verify that the text becomes red. For this i use another wait for element attribute equals method call, for which i wait for the ‘style‘ attribute to equal the ‘display: block; color: red;‘ value.
checkTheCheckbox();
waiter.waitForElementAttributeEqualsString(page.textElement,"style", "display: block; color: green;",
        driver);
checkTheCheckbox();
waiter.waitForElementAttributeEqualsString(page.textElement,"style", "display: block; color: red;",
        driver);
  • wait for attribute equals but ignoring case. Here it doesn’t matter whether the value of the attribute is in upper or lower case, or if you specify the expected value in a different case from the actual value. The wait method used in this test (waitForElementAttributeEqualsString_IgnoreCase) ignores the case of the expected and actual values, by comparing their lowerCase values. You just check that the text is the same, even if some letters are uppercase in the expected  text versus the actual text.
checkTheCheckbox();
waiter.waitForElementAttributeEqualsString_IgnoreCase(page.textElement,"style", "display: BLOCK; color: GREEN;",
        driver);
  • wait for attribute equals but ignoring whitespaces is useful when you are not sure how many whitespaces are in the actual value (spaces, new lines, tabs).
checkTheCheckbox();
waiter.waitForElementAttributeEqualsString_IgnoreWhitespaces(page.textElement,"style", "display:block;color:green;",
        driver);
  • wait for attribute contains: in this case, you want to wait for the checkbox color to become green, but you not interested in what other information is found in the ‘style‘ attribute. Therefore, you just want to make sure that the ‘style‘ attribute contains the color related information.
checkTheCheckbox();
waiter.waitForElementAttributeContainsString(page.textElement,"style", "color: green;",
        driver);
  • wait for attribute contains but ignoring case: here you wait for the ‘style‘ attribute to contain the color information, but you are not interested in whether upper case or lower case letters are used in the actual value. The wait method used here compares the expected and actual values after converting them to lower case.
checkTheCheckbox();
waiter.waitForElementAttributeContainsString_IgnoreCase(page.textElement,"style", "color: GREEN;",
        driver);
  • wait for attribute contains but ignoring whitespaces: here you just want to make sure that the actual value for the ‘style‘ attribute contains the color information, no matter how many whitespaces might be found in the ‘style‘ value.
checkTheCheckbox();
waiter.waitForElementAttributeContainsString_IgnoreWhitespaces(page.textElement,"style", "color:green;",
        driver);

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:

4 thoughts on “thewaiter: wait for WebElement attribute. To equal, contain a String, with variations.”

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 )

Connecting to %s

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