-
Notifications
You must be signed in to change notification settings - Fork 16
Query Methodology
A Query is composed of a JSON
object that contains specifiers. A specifier
is a key-value pair that helps to specify which element(s) you are interested in finding. Supported specifiers are as follows:
[ x, y ] or { x: #, y : # }
Specifies whatever element the OS returns at x, y. E.g.
{
"coordinate": [ 100, 200 ]
}
or
{
"coordinate" : {
"x" : 100,
"y" : 200
}
}
string
Matches elements with a given accessibilityIdentifer
string
Matches elements who have a given text
, label
, title
, or placeholderValue
string
As text
, but diacritical- & case-insensitive substring match. E.g. text_like : 'NåNa' matches 'Banana'
string
Matches elements of a given type
, which is XCUIElementType
. The strings passed in are case insensitive and are fairly intuitively mapped to their XCUI counterparts. E.g. button
maps to XCUIElementTypeButton
. These are also parallels to the UIA
class types used by Appium and the like.
"key=value" or { key: string, value: string }
Uses predicates to match. E.g.
"property" : "title=banana"
or
"property" : {
"key": "title",
"value": "banana"
}
would match an object with the title property set to banana
.
The reason you'd use this over text
is because text
is a four-part predicate and as such is a bit slower.
"key=value" or { key: string, value: string }
As property
but using diacritical- & case-insensitive substring match. See text_like
json
Specifies that you are looking for a child element of whatever was matched by the current set of specifiers. The value is its own set of sub-specifiers, using the same possible keys as above. Can only match 1st generation children of the currently matched element(s)
E.g.
{
"type" : "ScrollView",
"property" : "title=News",
"child" : {
"type" : "button",
"text_like" : "subscribe"
}
}
This finds a scrollview whose title equals "News" and then looks for a child of that element of type 'button' with some text similar to "subscribe".
json
As child
but can match descendants at any level.
int
Specifies which index of the results you want to return. This specifier is always evaluated last.
In the XCUITestServer, queries are evaluated top to bottom in the view hierarchy, starting with the Application element (which is analogous to the root view or window
of an application and contains all other views). A query may specify an element at a particular level or a descendant of that level, but never a parent/ascendent (this is a current limitation of XCUITest and iOS accessibility).
By default, you will always get results in an array form, even if there is only one element.
Examples:
POST /query {
"property_like" : "title=facebook",
"type" : "icon",
"index" : 1
}
To evaluate this, we start by grabbing the XCUIApplication
object. Then we look for any descendants matching either of the specifiers (property_like
or type
). index
is always matched last so we ignore that for now.
Suppose we match on property_like
first. What we'd do is build a query on the XCUIApplication
object which matches any descendants that have a property called title
whose value looks like *facebook*
. Then we apply the next specifier (type
) to that same query. Lastly we apply the index
. The fully composed query looks like:
Descendant of XCUIApplication
that have a property 'title' like '*facebook*'
and are of type 'XCUIElementTypeIcon'
at index 1
In Objective-C, this is
[[[[[CBApplication currentApplication].query descendantsMatchingType:XCUIElementTypeAny]
matchingPredicate:[NSPredicate predicateWithString:"title LIKE[cd] *facebook*"]]
matchingType:XCUIElementTypeIcon]
elementBoundByIndex:1];