Full Path Is Not an Option
Let's look at the web page below and think of good XPATH expressions for
UserName input field.
<input name="usrName" id="UserName" class="textbox" autocomplete="off" type="text">
<input name="pwd" id="Password" class="textbox" autocomplete="off" type="password">
is better than
because full expression that enumerates nodes from root of a DOM tree to one of it's leaves gets broken after almost any update of a web page.
If there is no ID then
is still better than
A Tree or Not a Tree
Here is another example.
<div role="group" title="Favorities" aria-expanded="false">Favorities</div>
<div role="group" title="Recent" aria-expanded="true">Recent</div>
<div role="treeitem"><a title="Accounts payable > Vendors">All vendors</a></div>
<div role="treeitem"><a title="Procurement and sourcing > Purchase orders">All purchase orders</a></div>
<div role="group" title="Workspaces" aria-expanded="false">Workspaces</div>
<div role="group" title="Modules" aria-expanded="true">Modules</div>
<a role="treeitem" title="Cash and bank management">Cash and bank management</a>
<a role="treeitem" title="Cost management">Cost management</a>
<a role="treeitem" title="General ledger">General ledger</a>
This is a three level tree but nodes of second and third levels are both children of the tree root. So there is no relationship
parent-child between second and third level nodes.
First level of the tree is presented by a single root node with role
tree. Second level consists of nodes with role
group. And third includes nodes with role
treeitem. Also if a second level node has
aria-expanded="false" then it's descendants are not present in the DOM tree (
Workspaces are examples of such nodes).
How to reliably navigate to a third level node?
If the node is visible it can be found as
But such XPATH expressions will return more than one result. So instead of a tree item we may click on a link in
Better search for the text from the tree root
And if the required result should be always a node with
role="treeitem" we can use
If the second level node is collapsed (it can be determined from the attribute
aria-expanded) then our expressions will not work. So to reliably reach an arbitrary node in the tree we need to know a path to it from the root. The algorithm of finding a node in pseudo notation will look like
- Find second level node by its name.
- If it is collapsed then expand it.
- Find third level node by its name.
So knowing XPATH expression of a node may be insufficient to find and interact with it.
Another example of this is a node that appears only when mouse is hovered over a UI control, it can be a sub menu item or even a simple link.
XPATH Building Blocks
Now when you have an idea of how reliable identification of elements in Web UI looks like we present a list of syntactic examples you can use for building resilient XPATH expressions.
Element with ID
Element with id attribute set to a given value.
Element by Index
input element on the page.
Element with Text
Link with a given text.
Sometimes text contains extra spaces or carriage return symbols. To filter them out use
Element with Class
Sometimes an element may belong to several classes.
<div class="column columnHeader sortable"></div>
To match a specific class with XPATH use
//div[contains(concat(' ', normalize-space(@class), ' '), ' columnHeader ')]
Notice spaces in
' columnHeader ' - second argument to
Element with Attribute
Find an element which contains a specific attribute. For example, to find all
divelements which have
id attribute do:
Element without Attribute
Find an element which does not contain a specific attribute. In this example we need a
div element with
role set to
main and without
//div[@role='main' and not(@style)]//div[@data-target="selectionArea"]
Element with Child Element with Specific Text
Select an element which contains a child element with a given text.
Specific Parent of Element
Select parent node of an element with a given text.
Find a Cell with Specific Text in a Given Column of a Table
Let's assume there is a table of standard structure and we want to search column
2 for a cell with text
Click in Last Row of a Table
To click in a cell of a last row in a table (for example, it may be a row for inserting a new record and you want to click on Insert button) use last() function.