Sahi Accessor API Basics
Overview
Browser Accessor APIs help access elements on the browser. They need to be executed on the browser and not in the proxy. They should be used as parameters to Browser Action APIs.All accessor APIs take an identifier and an optional domRelation.
- Identifiers can either be a numerical index or a property as specified in each case.
- Identifiers which are not numerical, can either be a string or a javascript regular expression.
- Identifiers which are strings can also have an index along with them in square brackets as part of the string.
Identifying unique element
For example,<a href="http://sahi.co.in" id="sahi_link">Link to Sahi website</a>
can be represented in the following ways:
_link(12) | Using index in the page; assuming it is the 13th link on the page. |
_link("sahi_link") | Using id as string |
_link(/.*_link/) | Using id as regular expression |
_link("Link to Sahi website") | Using visible text as string |
_link(/Link to .* website/) | Using visible text as regular expression |
_link("/Link to .* website/") | Using visible text as regular expression |
_link({id:"sahi_link"}) | Using an associative array with id |
_link({sahiText:"/Link to .*/"}) | Using an associative array with visible text as regular expression |
_link({className:"low",sahiText:"/Link.*/"}) | Using an associative array with multiple attributes like className and sahiText |
Identifying element among similar elements
For example,<table>
<tr>
<td>User One</td>
<td id="del1"><a href="/deleteUser?id=1">delete</a></td>
</tr>
<tr>
<td>User Two</td>
<td id="del2"><a href="/deleteUser?id=2">delete</a></td>
</tr>
</table>
There are two delete links in this table and there may be more.
_link("delete") | points to the first delete link. This is the same as _link("delete[0]") |
_link("delete[1]") | points to the second delete link; Note that indexing starts at 0 |
_link("/del/[1]") | points to the second delete link; Note that indexing starts at 0 |
Using indexes works fine as long as the page is static, but it is not recommended for dynamic applications,
as it makes scripts fail when changes are made to the web pages.
Use of DOM Relation APIs
When elements are not uniquely identifiable by themselves, we should try to identify them in relation to either some element near them or by the element in which they are contained._near
is a DOM relation marker which specifies that the element should be searched near another element.
_in
is a DOM relation marker which specifies that the element should be searched within another element.
For example, in the above case, the second delete link is near User Two.
_link(0, _near(_cell("User Two"))) |
points to the 0th link near cell with text "User Two". Note that the index is 0 here since it is the nearest link. |
_link("delete", _near(_cell("User Two"))) |
points to the nearest link with text "delete" near cell with text "User Two". Note that we do not need to specify "delete[1]" since it is the delete. link nearest to User Two. |
_link(/del/, _near(_cell("User Two"))) |
points to the nearest link with text which matches regular expression /del/ near cell with text "User Two". |
_link("delete[2]", _near(_cell("User Two"))) |
points to the 3rd nearest link with text "delete" near cell with text "User Two". |
_link("/del/[2]", _near(_cell("User Two"))) |
points to the 3rd nearest link with text matching /del/ near cell with text "User Two". Note how the regular expression is appended with the index in square brackets and quoted to make it a string |
_link(0, _in(_cell("del2"))) | points to the 0th link in cell with id "del2" |
_link("delete", _in(_cell("del2"))) | points to the link with text "delete" within cell with id "del2" |
Use of Positional Relation APIs
Position relations like under, rightOf, leftOf etc. relate one element to another via their position.One important frequent requirement in web applications is the assertion of elements in a column of a grid. For example
<table>
<tr>
<td>Name</td>
<td>Delete</td>
<td>Status</td>
</tr>
<tr>
<td>User One</td>
<td id="del1"><a href="/deleteUser?id=1">delete</a></td>
<td>Active</td>
</tr>
<tr>
<td>User Two</td>
<td id="del2"><a href="/deleteUser?id=2">delete</a></td>
<td>Inactive</td>
</tr>
</table>
Name | Delete | Status |
User One | delete | Active |
User Two | delete | Inactive |
_cell(0, _near(_cell("User One")), _under(_cell("Status"))) | Finds first cell near User One and under Status |
_cell(0, _rightOf(_cell("User One")), _under(_cell("Status"))) | Finds first cell to the right
of User One and under Status |
_cell("Inactive", _under(_cell("Status"))) | Finds first Inactive cell under Status |
_near vs _rightOf or_leftOf
Using _near where the element to be found may or may not exist can give you unexpected results.For example, in the table below
Name | Delete | Status |
User One | delete | Active |
User Two | ? | Inactive |
Let us say we are looking to check if a delete link exists against all users.
_assertExists(_link("delete", _near(_cell("User Two"))))
may be expected to fail, but it passes.
_link("delete", _near(_cell("User Two")))
actually points to the above highlighted link.
This is because, _near is a DOM relation API and finds an element within 7 ancestors (parent nodes) of the given anchor. In our case this link was found within 2 ancestors of the cell in the next row.
The correct way of asserting this would be
_assertExists(_link("delete", _rightOf(_cell("User Two"))))
.
_rightOf forces location only along the same line
Forcing Sahi Pro to ignore case when identifying elements
_setAccessorIgnoreCase
Since: | Sahi Pro | Desktop Add-On | Mobile Add-On | SAP Add-On | AI Assist Add-On |
5.1.0 | 7.5.0 | 7.5.0 | NA | NA |
Available for modes: Browser | Windows | Java | Android | iOS
_setAccessorIgnoreCase($isIgnore)
Arguments
$isIgnore | boolean | true or false |
Returns
null |
Sahi Pro Flowcharts Action :Set Accessor Ignore Case
Details
If
For example, given a link with text "Home",
If
If
_setAccessorIgnoreCase
is used with isIgnore
parameter as true, on further steps, case differences will be ignored in identifiers of Accessors.
For example, given a link with text "Home",
_link("Home")
will identify the element, but not _link("HOME")
or _link("home")
.
If
_setAccessorIgnoreCase
is added with isIgnore
parameter as true, then the same element can be identified using _link("Home")
, _link("HOME")
or _link("home")
_assertExists(_link("Home")); // SUCCESS
_assertExists(_link("HOME")); // FAILURE
_assertExists(_link("/home/")); // FAILURE
_setAccessorIgnoreCase(true);
_assertExists(_link("Home")); // SUCCESS
_assertExists(_link("HOME")); // SUCCESS
_assertExists(_link("/home/")); // SUCCESS
_setAccessorIgnoreCase(false);
_assertExists(_link("Home")); // SUCCESS
_assertExists(_link("HOME")); // FAILURE
_assertExists(_link("/home/")); // FAILURE
info
The default value of _setAccessorIgnoreCase is false. It can be forced to be true by default by adding
sahi.accessor.ignore_case=true
to sahi/userdata/config/userdata.properties