This doc is a step-by-step guide to writing (or auto-generating) semantic locators.
Semantic locators have one required part, the ARIA role, and two optional parts, accessible name and ARIA attributes. The role and name are almost always enough to identify elements.
In the locator {button 'OK'}
the role is button
and the accessible name is
OK
.
Usually you won't have to write semantic locators by hand as they can be easily auto-generated from a Chrome extension, an interactive playground, or from code.
An easy way to create Semantic Locators for your app is to auto-generate them with a Chrome Extension.
Install the extension and click the icon next to the URL bar to get started.
The interactive semantic locator playground auto-generates semantic locators for elements in some HTML you enter. It can be useful for:
- Writing locators for many elements at once
- Sharing HTML snippets with their a11y data
- Debugging the semantics of an element
Locator generation is available from the semantic locator libraries. If you already have some other types of locators you can generate semantic locators for these elements by temporarily adding generation code to existing tests.
The following example logs generated semantic locators to the console. However, you could go further, for example, automatically re-writing your tests to use semantic locators. We'd love to see what you build in this space!
import com.google.semanticlocators.BySemanticLocator;
...
WebElement targetElement = driver.findElement(By.xpath("//div[@aria-label='Cheese']"));
System.out.println("Semantic locator: " + BySemanticLocator.closestPreciseLocatorFor(targetElement));
from semantic_locators import closest_precise_locator_for
...
target_element = driver.find_element(By.XPATH, "//div[@aria-label='Cheese']");
print("Semantic locator: " + closest_precise_locator_for(target_element));
import {closestPreciseLocatorFor} from 'semantic-locators/gen'
...
const targetElement = document.getElementById('cheese');
console.log('Semantic locator: ' + closestPreciseLocatorFor(targetElement));
If for some reason auto-generation doesn't work for you, the Accessibility tab of browser developer tools can help you easily write semantic locators.
- Open the Developer Console by pressing F12.
- [Chrome] Select the target element with the element picker (⌘+Shift+C or
Ctrl+Shift+C) then navigate to the Accessibility tab.
. [Firefox] Navigate to the Accessibility tab, click the picker icon (top left of Dev tools), then click the target element. - Check the name and role of the element. For an element with the role
button
and nameCreate
, the semantic locator is{button 'Create'}
.
If the accessible name is dynamic, or is too long for your test, you can use a
wildcard value. Values accept *
as a wildcard (e.g., '* view'
,
'https://*.google.com/*'
).
<button aria-label="Today, 1st April"> <!-- {button 'Today*'} -->
Today
</button>
It's not always necessary to specify a name - some elements have no accessible
name, or a completely dynamic one. {list}
is a valid locator if you know
there's only going to be one list on the page.
<ul> <!-- {list} -->
<li aria-label="Cheese">Cheese</li> <!-- {listitem 'Cheese'} -->
<li aria-label="Chocolate">Chocolate</li> <!-- {listitem 'Chocolate'} -->
</ul>
Using the above strategies might still return multiple elements. In this case you can make a semantic locator more precise in a few ways.
Semantic locators can be combined, with later elements being descendants of earlier elements.
Auto-generated locators will contain multiple elements if a single element doesn't uniquely identify the target.
<ul>
<li aria-label="Cheese">
<button aria-label="Eat"> <!-- {listitem 'Cheese'} {button 'Eat'} -->
Eat cheese
</button>
</li>
<li aria-label="Chocolate">
<button aria-label="Eat"> <!-- {listitem 'Chocolate'} {button 'Eat'} -->
Eat chocolate
</button>
</li>
</ul>
Semantic locators can locate elements based on attributes such as checked
and
disabled
. Both native html (<button disabled>
) and explicit semantics
( aria-disabled="true"
) are included.
The source of truth for supported attributes is
SUPPORTED_ATTRIBUTES
.
Note: Auto-generated semantic locators don't yet include attributes.
<h1>Cheese</h1>
<label>
<input type="checkbox"> <!-- {checkbox 'Edible' checked:false} -->
Edible
</label>
<br>
<button disabled>Eat</button> <!-- {button 'Eat' disabled:true} -->
Sometimes (e.g., when working with lists) nested elements may both match the
same locator. In this case you can use the outer
keyword to match only the
outermost element.
<ul> <!-- outer {list} -->
<li> <!-- outer {listitem} -->
<ul> <!-- {listitem} {list} -->
<li>Cheese</li> <!-- {listitem} {listitem} -->
</ul>
</li>
</ul>