How Targeting Works in UIlicious

What is UIlicious?

UIlicious is a UI automation testing tool for web applications that uses test scripts to simulate, test, and validate end-user workflows by targeting UI elements like buttons, menu items, navigation, etc.

Even if your web application's HTML code for UI changes, the test is valid if the user journey remains the same.

The UIlicious core principle is to test the user journey, not HTML.

UIlicious encourages you to write tests as if you are telling a friend over the phone how to use a particular website.

How Targeting Works

UIlicious looks specifically at the semantic HTML, ARIA label attributes, and alternative text for images provided in your code as it crawls through the structure of your site.

Semantic HTML are elements that provide a clear meaning to both you and your computer. For example, a <title> element is semantical because you as a reader understand the element's purpose is to represent a title.

ARIA label attributes also help make web pages more accessible and provide more context for elements seen on screen readers and other similar devices. For example, an interactive element could be a button used for searching with an aria-label that describes its use. We would then write: <button aria-label="Search">.

If you are interested in learning more about semantic HTML, please take a look at Mozilla firefox's Semantic HTMLopen in new window and ARIA - Accessibilityopen in new window documentation.

Let's imagine a scenario where we are going to use Google Maps to search for a specific place on the map, and use the following script in UIlicious to tell the tool we want to search:

UIlicious Script Example:

// UIlicious Script for Google Map Search​
// Step 1
I.goTo("https://www.google.com.sg/maps")
// Step 2
I.fill("Search", "Merlion, Singapore") // It's a half-fish, half-lion statue
// Step 3
I.click("Search")

UIlicious can successfully complete Step 1 and Step 2, but how does our tool know that the button (circled in red in our example below) is both clickable and labeled "Search"?

Let's take a look at the HTML code behind our Google Maps.

Example:

Using the Inspect tool provided by our browser, we can see that our Search <button> is given an accessible name using aria-label="Search".

Example:

So, when we run our tests, UIlicious can make educated guesses based on the context provided in our HTML code.

Targeting Similar Elements

What happens if there are multiple elements with the same keyword?

UIlicious will make an educated guess to resolve the ambiguity using semantics, accessibility, and the previous commands you use in a script.

Using Semantics

For example, if I.click("Sign in") matches a h1 element and a button element, the UIlicious is more likely to click on the button which semantically indicates that the element is clickable.

Using Previous Commands

UIlicious focuses on user journeys, so it tries to think like a user when moving through your web application.

UIlicious will also look at your previous commands to identify the target element.

For example, on the Twitter page below, the "Log In" button appears twice on the page.

Example:

The UI.licious Studio displays the left panel of a given website and the right panel of UI.licious commands.

UIlicious will infer that it should target the closest button element to submit the form because the previous commands were to fill in the username and password.

UIlicious Script Example:

// UIlicious Script for Twitter LoginI.goTo("https://twitter.com")
I.fill("Username", "brucewayne")
I.fill("Password", "supersecretpassword")// Even though there's two log in buttons, 
// this will click on the nearest button to the "username" and "password" fields.  
I.click("Log in")

Alternatives to Targeting Elements

Using the I.see command

Sometimes, we want UIlicious to target an element that may look ambiguous in comparison to other elements on the same webpage.

In other automation tools, it can require you to write a script using the position of the element or CSS or XPath selectors, which can be faulty since both can change over time.

I.see() is one of the basic commands of UIlicious that allows you to assert or validate that the element exists within the page.

Let's say we want to purchase a specific type of rose called "Love, Actually" for a friend from a popular flower shop called Far East Floraopen in new window.

In the example below, we can see that there are several types of roses with the same "View Details" button.

Using the I.see command in our script, we can give clues to UIlicious to set its anchor point specifically on the "PY06 - Love, Actually" roses.

Then, the UIlicious test engine is smart enough to infer that you would like to specifically click the "View Details" button under "PY06 - Love, Actually" roses.

Example:

UIlicious Script Example:

I.goTo("https://www.fareastflora.com")

// Let's search for roses
I.fill("Search", "Roses")
I.pressEnter();

// Use the I.see command to give UIlicious a focus point
I.see("PY06 - Love, Actually")
I.click("PY06 - Love, Actually")

// Let's add the flowers to our cart
I.click("Add To Cart")

// Checkout the flowers
I.click("Checkout")
I.click("Continue as a Guest")

Hinting with I.see.hint command

All commands that interact with the webpage, such as I.see, I.fill, I.click, implicitly sets a hint for subsequent commands on the area of the page in focus when targeting elements. You can use I.see.hint command, which like the normal I.see command, checks if a text or element is displayed on the page, but it also explicty sets an hint with a stronger weight than the implicit hints.

Hints are useful when there are multiple elements on the page with the same label.

For example, on a catalogue page with an "Add to Cart" button for each product, you can use the I.see command on a product's name before using I.click on the "Add to Cart" button, in order to get the I.click command to click on the "Add to Cart" button for the product seen using the I.see command. You can see a demonstration of this effect in the example below which uses a real-world ecommerce site.

// Let's go to a flower shop and search for a nice bouquet of Sunflower
I.goTo("https://www.fareastflora.com")
I.fill("Search" , "Sunflower")
I.pressEnter()
I.select("Sort by", "Price")

// Use I.see.hint to set a focus on the product card
I.see.hint("Citrine Birthstone")

// I.click will use the hint from I.see to decide what to click
I.click("View Details")

// I'm at the correct page
I.amAt("/citrine-birthstone-november-hand-bouquet-31236.html")

Limiting the scan area using UI.Context

In some cases, we need to limit the scan area for the UIlicious test engine to identify target elements when we cannot use commands like I.see and I.see.hint.

In the example below, there are two identical forms to log in and create an account.

This can be confusing for UIlicious to decide which form to fill in since both have an identical set of usernames and passwords.

Let's say we want to specifically target the login form.

To solve this issue, we can use UI.context to specify a region, the login form, so that UIlicious will scan and identify our target element.

See the UIlicious script below.

Note: UI.context() also allows you explicitly focus on an iFrame by targeting the <iframe> element or XPath.

Example:

The web page has two forms: a login form and a create account form. The login form is directly above the create account form.
Please log in to your Qacker News account or create one to continue.
<br>
<br>
<!-- our login form-->
<form id="login-form">
  <div>username: <input type="text"></div>
  <div>password: <input type="password"></div>
  <button type="submit">login</button>
</form>
<br>

<!-- our register form -->
<form id="register-form">
    <div>username: <input type="text"></div>
    <div>password: <input type="password"></div>
    <button type="submit">create account</button>
</div>

To limit the scan area to the login form, we can set the UI.context to use a CSS id Selector, #login-form, that identifies the Login Form like this:

UIlicious Code Example:

I.see("Please log in") // This looks at the entire page for this phrase.

UI.context("#login-form", function(){    
I.fill("username", "[email protected]")  
I.fill("password", "password")  
I.click("login")
})

Handling <iframe> using UI.Context

In some cases such as targeting an <iframe>, using the commands, I.see or I.see.hint, is not a choice because of how the <iframe> element is composed, like a pop-up or modal. As a result, the UIlicious test engine cannot access or target the elements inside of an <iframe>.

To interact with elements in an <iframe>, you must explicitly select the iframe as the context using UI.context.

Inside of the UI.context brackets, { } , all of the commands listed will only apply to that specific <iframe> or element.

In the example below, we have a pop-up window that has a unique class of .trust_popframe. We cannot target the content of this pop-up window with I.see or I.see.hint because it is located within an <iframe>.

Example:

Using CSS/XPath Selectors

We do not recommend using CSS and XPath selectors because it can make your test results unstable since class and ID names can change over time and cause your code to become unreadable.

You can use CSS and XPath Selectors as an alternative to targeting elements.

I.click("#signin-button") // click on the element with the id "signin-button"
I.click("//table[1]//tr[1]//td[1]") // click on the first cell of the first row of the first table
Last Updated: