Web Testing - Using XPath Queries¶
Purpose¶
When testing web applications you will explicitly or implicitly use XPath expressions to query the browser DOM for elements based on the scenario under test. This section explains how XPath queries are used in Rapise and how to make your browser testing more flexible and adaptive to changes in the application you test.
XPath Fundamentals¶
XPath uses path expressions to select nodes in an XML document such as HTML. The node is selected by following a path or steps.
Refer to XPATH Tutorial for more details.
Rapise XPath Extensions¶
Frames¶
Web pages sometimes use HTML frames. The XPath works inside the frame contents. Rapise has a special syntax (that is not part of standard XPath) to combine multiple XPath statements into a single line:
//frame[@name='main']@@@//a[3]
The special statement @@@
is used as a separator for XPath statements pointing to constituent frames.
The top-level frame is found by name main
//frame[@name='main']
Then the frame's contents is searched for the <a>
element that is a 3d child of it's parent element.
//a[3]
Note
Segments of a locator separated by @@@
can be both xpath and css. For example the following locators are equivalent:
1 2 3 4 |
|
Shadow DOM¶
Another XPath extension is related to Shadow DOM. It's borders are typically closed for XPath. In such a case a locator for an element inside Shadow DOM has two parts separated by @#@
delimiter. First part (can be XPATH or CSS) should point to the Shadow Root in the Light DOM. Second part (always CSS) should point to a child element of the Shadow Root. In the case of nested Shadow DOMs there will be multiple @#@
delimiters.
Example of a locator:
automatically built by WebSpy
/html/body[1]/section[1]/div/guid-generator[1]@#@css=input:first-of-type
//guid-generator@#@css=input
Find the example of a simple page with Shadow DOM on UI Testing Playground.
Piercing Shadow DOM¶
Rapise 8.2+ is able to pierce Shadow DOM. It means that if a CSS selector does not use @#@
delimiter described above then Rapise will search for an element without taking into account Shadow DOM borders.
For example on this page:
<section>
<div>
<guid-generator>
# shadow-root (open)
<input class="edit-field" id="editField">
<button class="button-generate" id="buttonGenerate"><i class="fa fa-cog"></i></button>
<button class="button-copy" id="buttonCopy"><i class="fa fa-clone"></i></button>
</guid-generator>
</div>
</section>
we may find <input>
element with
css=input
css=input[id='editField']
css=guid-generator input
css=guid-generator > input
Note
Shadow DOM piercing feature may break existing tests as locators recorded earlier may start to find more elements. In this case make locators more specific.
Automatic XPath Generation on Record and Learn¶
When you do a recording session, interact with web elements or learn them - Rapise generates XPath locators for the elements. You can view XPath of an object in the property grid:
Usage¶
In Web Spy¶
In some advanced cases you may need to construct XPath query manually. For this purpose we recommend using the Web Spy tool:
If you enter in the XPath query at the top, when you click Test it will display all of the DOM elements that match the query:
You can now refine the query to only find the item you want to test.
When you have created the query in the Web Spy that returns the HTML element that you were expecting, you can click on the Learn button in the Web Spy toolbar to learn that element. What this will do is create a new Rapise object in the Object Tree that maps to this specific XPath.
For example, if you want to find a specific book in a grid of books
you can search by its name using text()
XPath function:
//td[text()='Oliver Twist']
Then learn this object as Oliver_Twist so that you can access it in your code as SeS("Oliver_Twist")
. Every time you call a function on Oliver_Twist, Rapise will use the learned XPath expression and use that to evaluate which HTML element in the web page to access.
Dynamic Queries¶
In addition to learning objects based on specific XPath, there is HTMLObject.DoDOMQueryXPath action that can be used to query for elements in the web page:
var res = SeS('MainContent_grdBooks').DoDOMQueryXPath('.//td[text()="Oliver Twist"]');
Tester.Message(res.length);
This will dynamically query for any HTML element that is a child of the learned MainContent_grdBooks object that matches the XPath. In this example it will look for any table cell that has the content of the book name.
You can also find an object dynamically without having any object in the object tree. To do this use Navigator.SeSFind action.