Skip to main content

Serenity Page Elements

Introduction#

In most Selenium-based test automation frameworks, CSS or XPath selectors are commonly used to locate elements on a page. Serenity BDD provides a simpler way of interacting with common UI components, which can avoid needing to use XPath or CSS expressions.

For example, the following HTML code illustrates a few different ways to represent a button:

<button type="button" class="btn btn-primary">Login</button><input type="submit" value="Login">

In Serenity, we could interact with these using XPath or CSS, e.g.

$("css:input[value='Login']").click()

or

$("xpath://button[.='Login']").click()

However, if the UI implementation switched from one to another, the test would break.

Serenity Page Elements provide a more intuitive way to identify many common UI elements. Using Serenity Page Elements, we can use a more expression like this:

import net.serenitybdd.screenplay.ui.Button;...$(Button.withText("Login")).click();

Or for a Screenplay test, you could do the following:

actor.attemptsTo(    Click.on(Button.withText("Login")));

Under the hood, Serenity will look for either <button> elements, or <input> elements of type submit, that display the "Login" text.

Another common location strategy is to use attributes like id or name, or test-specific attributes like data-test.

Suppose we have the following HTML code:

<button type="button" class="btn btn-primary" data-test="login-button">Login</button>

We could click on this button with the following code:

$(Button.withNameOrId("login-button")).click();

Or in Screenplay, we could do the following:

actor.attemptsTo(    Click.on(Button.withNameOrId("login-button")));

In this case, Serenity will look for <button> elements, or <input> elements of type submit, with a value, id, data-test or aria-label attribute of "login-button".

This means that, in many cases, you can use the Button class directly in your code, without having to inspect the page structure first.

Serenity Page Elements are found in the serenity-screenplay-webdriver module, but they can be used in both Screenplay and Action Class-based tests.

There are many different types of page elements available. All of them have the withNameOrId() method, but some have other methods for more specific locator strategies, such as withLabel() for checkboxes.

The following table gives an overview of the different types of PageElement available:

Element typeExample
ButtonsButton.withText("A Button")
CheckboxesCheckbox.withValue("Ferrari")
DropdownsDropdown.withLabel("---Pick Your Car---")
ImagesImage.withAltText("Girl in a jacket")
Input FieldsInputField.withPlaceholder("Enter the customer name")
LinkLink.withIcon("glyphicon-cloud")
PageElementPageElement.locatedBy(".item").containingText("Item 1")
RadioButtonRadioButton.withNameOrId("red-button")

Let's look at each type of page element in more detail.

Buttons#

The Button page element locates a <button> element with a specific tect, or an <input> element of type submit with a specific value.

Suppose we have the following HTML code:

<button type="button">A Button</button><input type="submit" value="Submit Me!" name="submit-button" data-test="submit-the-button"><input type="button" value="Press Here"><button type="button"><i class="glyphicon glyphicon-home"></i>Home</button>

We could use the following expressions to identify these elements:

StrategyExample
By textButton.withText("A Button")
By valueButton.withText("Press Here")
By nameButton.withNameOrId("submit-button")
By data-test attributeButton.withNameOrId("submit-the-button")
By iconButton.withIcon("glyphicon-home")
tip

The withNameOrId() method will match the id, name, data-test or aria-label attribute for any kind of Page Element, so we won't always repeat them everywhere in the following sections.

Checkbox#

This element will match an <input> element of type "checkbox", with a specified value, data-test, or class attribute value.

Suppose we have the following HTML:

<input type="checkbox" id="vehicle1" value="Bike" class="vehicule-option"><label for="vehicle1"> I have a bike</label><br><input type="checkbox" id="vehicle2" value="Car" class="vehicule-option"><label for="vehicle2"> I have a car</label><br><input type="checkbox" id="vehicle3" value="Boat" class="vehicule-option" checked><label for="vehicle3"> I have a boat</label><br>

We could use the following expressions to identify these elements:

StrategyExample
By idCheckbox.withNameOrId("vehicle1")
By valueCheckbox.withValue("Bike")
By labelCheckbox.withLabel("I have a bike")

Dropdown#

The Dropdown page element lets us work with a <select> dropdown list. Suppose we had the following HTML:

<label for="cars">Choose a car:</label><select name="cars" id="cars">    <option value="">---Pick Your Car---</option>    <option value="volvo">Volvo</option>    <option value="saab">Saab</option>    <option value="mercedes">Mercedes</option>    <option value="audi">Audi</option></select>

We could use the following expressions to identify these elements:

StrategyExample
By name or idDropdown.withNameOrId("cars")
By labelDropdown.withLabel("Choose a car:")
By default optionDropdown.withLabel("---Pick Your Car---")

Image#

The Image page element lets us interact with <img> elements. For example, suppose we had the following HTML code:

<img src="img_girl.jpg" alt="Girl in a jacket" width="500" height="600">

We could use the following expressions to identify these elements:

StrategyExample
By alt textImage.withAltText("Girl in a jacket")
By srcImage.withSrc("img_girl.jpg")
By src (starting with)Image.withSrcStartingWith("img_")
By src (ending with)Image.withSrcEndingWith("girl.jpg")

InputField#

The InputField page element represents an <input> element in a form, with or without a <label>. For example, suppose we had the following HTML code:

<label for="customer_name">Customer Name</label><input type="text" id="customer_name" name="customername" placeholder="Enter the customer name" />

We could use the following expressions to identify these elements:

StrategyExample
By nameInputField.withNameOrId("customername")
By idInputField.withNameOrId("customer_name")
By placeholderInputField.withPlaceholder("Enter the customer name")
By labelInputField.withLabel("Customer Name")

Link#

The Link page element interacts with HTML <a> elements. For example, suppose we have the following HTML code:

<!-- A simple link ---><a href="...">Link 1</a><br/><!-- A link with a title --><a href="..." title="Link Number 2">Link 2</a><br/><!-- A link with an icon and a text--><a href="#" onclick="update('Link 3')"><i class="glyphicon glyphicon-cloud"></i>Link 3</a><br/>

We could use the following expressions to identify these elements:

StrategyExample
By link textLink.withText("Link 1")
By link titleLink.withTitle("Link Number 2")
By partial link textLink.containing("ink")
By starting textLink.startingWith("Link")
By iconLink.withIcon("glyphicon-cloud")

PageElement#

The PageElement page element represents any element on a page. For example, suppose we have the following HTML code:

<div id="container" data-test="the-container" class="a-container">    <div class="item">        <h2>Item 1 heading</h2>        <div>            <span class="description">Item 1 description</span>        </div>    </div>    <div class="item">        <h2>Item 2 heading</h2>        <div>            <span class="description">Item 2 description</span>        </div>    </div></div>

We could use the following expressions to identify elements in this code:

StrategyExample
By idPageElement.withNameOrId("container")
By data-test valuePageElement.withNameOrId("the-container")
Containing a text valuePageElement.withNameOrId("item").containingText("Item 1")
Containing a text value (with a CSS locator)PageElement.locatedBy(".item").containingText("Item 1")

RadioButton#

The RadioButton page element represents a set of radio buttons. For example, suppose we have the following HTML code:

<input type="radio" id="html" name="fav_language" value="HTML" class="html-radio"><label for="html">Choose HTML</label><br><input type="radio" id="css" name="fav_language" value="CSS"><label for="css">Choose CSS</label><br><input type="radio" id="javascript" name="fav_language" value="JavaScript"><label for="javascript">Choose JavaScript</label><br><br>

We could use the following expressions to identify these elements:

StrategyExample
By idRadioButton.withNameOrId("html")
By labelRadioButton.withLabel("Choose CSS")
By valueRadioButton.withValue("JavaScript")

Using Page Elements in Action Classes

You can also use Page Elements in your normal (non-Screenplay) tests, simply by using the Page Element expression as a locator. For example:

public class LoginActions extends UIInteractionSteps {
    @Step("Login as a standard user")    public void asAStandardUser() {        $(InputField.withPlaceholder("Username")).type("standard_user");        $(InputField.withPlaceholder("Password")).type("secret_sauce");        $(Button.withText("Login")).click();    }}

Page Elements can be used with all of the usual methods for locating elements in a UI Interaction class, including:

MethodExample
$$(Button.withText("Login")).click();
findfind(Button.withText("Login")).click();
$$$$(Checkbox.withNameOrId("vehicle-option")).forEach(WebElementFacade::click);
findAllfindAll(Checkbox.withNameOrId("vehicle-option")).forEach(WebElementFacade::click);