Selectors
To perform any action on an element (e.g. clicking a button), you need to specify the element at which the action is being executed. This differs from the web technology you are using. Read the following instructions, depending on the UI technology of the application to be tested.
Info
Selectors are typically created using our Qmate Suite, but it is important to note that this tool is currently only available for internal use at SAP. For further information as internal, please refer to our official Qmate documentation.
UI5
Supported Selector Properties
The supported properties for any UI5 based application are the following:
const selector = {
"elementProperties": { ... },
"ancestorProperties": { ... },
"parentProperties": { ... },
"siblingProperties": { ... },
"prevSiblingProperties": { ... },
"nextSiblingProperties": { ... },
"childProperties": { ... },
"descendantProperties": { ... }
};
The selector consists of one mandatory selector called elementProperties, representing the target element where the action should be applied to and seven optional selectors:
-
ancestorProperties, parentProperties: While the
parentProperties
can be used only as direct parent of the element, theancestorProperties
can be used for any level of ancestry (parent, grandparent, grand-grand etc.). -
childProperties, descendantProperties : The difference between them is, that the
childProperties
can be used only as direct child of the element, whereas thedescendantProperties
can be use for any level of descendance (child, grandson, grand-grand etc.). -
siblingProperties, prevSiblingProperties, nextSiblingProperties: The
siblingProperties
can be any sibling, whereas theprevSiblingProperties
can be only the direct previous sibling andnextSiblingProperties
can be only the direct next sibling.
You have to define at least one property in elementProperties
. This could be metadata
or any other property of the Overview below.
Sample
"elementProperties":{
"metadata": "sap.m.Button",
"<ui5Property>": "*Any UI5 Property/Aggregation/Association"
"id": "*myId",
"viewName": "*myView*Name",
"viewId": "*id*viewId",
"bindingContextPath": "/ProductCategories(nodeKey=guid't12321-123213-34rer332', enabled='true', category='LT')"
"text": [{"path": "oDataModelName>companyChangedManually"}, {"path": "*enabled"}],
"tooltip": [{"path": "i18n>welcomeDescription"}]
"domProperties": {
"nodeName": "li",
"class": "*sapMButton"
"tooltip": "*text*"
},
"ancestorProperties": {
"metadata":"sap.m.ColumnListItem",
"ancestorProperties": {
"metadata": "sap.m.Table",
"items": {"path": "oDataModelName>PurchaseOrderItems"},
"siblingProperties": {...},
...
},
},
"descendantProperties": {"metadata":"sap.m.Icon"},
"siblingProperties": {"metadata":"sap.m.Input"},
}
Tip
For most of the cases it will be sufficient to provide only the elementProperties. Qmate Suite will generate the minimal unique selector for you.
Overview
The following properties apply to all selector types (elementProperties, ancestorProperties, parentProperties, siblingProperties, prevSiblingProperties, nextSiblingProperties, childProperties, descendantProperties).
Property | Description | Sample | Format | Remark |
---|---|---|---|---|
metadata |
the control type | "metadata": "sap.m.Button" , "metadata": "sap.m.Input" |
string: "property": "value" |
|
<ui5Property> |
UI5 properties including aggregations and associations, as defined in the official UI5 API | "text": "Amount" , "tooltip": "Amount" , "title": "Currency" , "enabled": true |
string: "property": "value" , numeric: "property": 123 , boolean: "property": true |
|
id |
the ID of the control | "id": "myButtonId" , "id": "my*Id*" |
string: "property": "value" |
|
viewName |
the view name | "viewName": "myViewName" , "viewName": "*view*" |
string: "property": "value" |
|
viewId |
the view ID | "viewId": "*myViewId*" |
string: "property": "value" |
|
bindingContextPath |
the binding context path | "bindingContextPath": "/odata/entity('1')" , "bindingContextPath": "/odata/entity(*)*" |
string: "property": "value" |
|
binding property paths | the binding property paths of the model (for all types of properties: UI properties, aggregations, associations) | "text":[{"path": "oDataModelName>companyChangedManually"}] , "title": {"path": "oDataModelName>companyChangedTitle"} , "items": {"path": "oDataModelName>PurchaseOrderItems"} , "enabled": [{"path": "company*Enabled*"}] , |
json: "items": {"path": ...} , array: "items": [{"path": ...}, {"path": ...} ...] |
model name is optional |
i18n keys | the binding properties path for i18n | "tooltip": [{"path": "i18n>welcomeDescription"}] , "tooltip": {"path": "i18n>welcomeDescription"} , "tooltip": [{"path": "*i18n*welcomeDescription"}] |
json: "items": {"path": ...} , array: "items": [{"path": ...}, {"path": ...} ...] |
i18n is a model, and therefore all the above mentioned rules (as described in binding property paths) apply |
domProperties |
the properties of the DOM | "domProperties": {"nodeName": "div", "class": "buttonNU* class2*", "id": "my*Id*"} |
string: "property": "value" , numeric: "property": 123 , boolean: "property": true |
can be used if the UI5 Virtual DOM is not sufficient |
Info
Wildcards are supported for all properties, aggregation and associations
"text": "my*text*"
Nested Properties
In case you need to specify the element based on its surrounding, you can define nested properties.
"elementProperties": {
...
"ancestorProperties": {
"metadata": "sap.m.ColumnListItem",
"ancestorProperties": {
"metadata": "sap.m.Table",
"items": { "path": "oDataModelName>PurchaseOrderItems" },
"siblingProperties": {...},
...
},
}
};
Info
Nesting is enabled infinitely for ancestorProperties, siblingProperties and descendantProperties. Be cautious, the more level of nesting you add the slower your script will be.
Usage of Selectors
For almost every UI5 action we provide, you can pass the selector directly to the function like:
it("Step 01: click on 'Save' button", async function () {
const selector = {
"elementProperties": {
"metadata": "sap.m.Button",
"text": "Save"
}
};
await ui5.userInteraction.click(selector);
});
Non UI5
Defining the element
For all non UI5 applications you can define the element in different ways. We provide all common functionalities to get an element by its ID, Class or any other CSS attribute. Hence, you can not pass any selector directly to the function performing an action. Instead, you have to define the element first with one of the provided methods.
// Get an element by its ID
const elem = await nonUi5.element.getById("button-abc");
// Get an element by its class (pass an index if there are more than one elements with the same class)
const elem = await nonUi5.element.getByClass(".button", 0);
// Get an element by its attribute value of "title"
const elem = await nonUi5.element.getByCss("input[title='name']");
// Get an element by its class and text value
const elem = await nonUi5.element.getByCssContainingText(".button", "Save");
Info
To get a complete overview about all possible methods, please see nonUi5.element.
Getting the attributes manually
To get the properties of an element manually, please follow the steps below:
-
Open the dev-tools F12 and switch to the Elements Tab.
-
Select the element (right click ➜ inspect)
-
Find any attribute or set of attributes to identify the element clearly.
-
To verify the uniqueness of the element, switch to the Console tab of the dev-tools and type in the following command using your found attribute/s:
$$("[<attr>='<attrValue>']");
Warning
If there are more than one elements found, try to find another attribute or add some more attributes until you will find a single element (you can still pass an index to the reuse function if you are not able to find a unique selector).
Usage
To perform the action, pass the defined element to the action function.
it("Step 01: click on 'Save' button", async function () {
const elem = await nonUi5.element.getByCss(".saveButton");
await nonUi5.userInteraction.click(elem);
});