Skip to content

Query Methodology

Karl Krukow edited this page Mar 24, 2016 · 15 revisions

Syntax

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:

coordinate

[ 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
    }
}

id

string

Matches elements with a given accessibilityIdentifer

text

string

Matches elements who have a given text, label, title, or placeholderValue

text_like

string

As text, but diacritical- & case-insensitive substring match. E.g. text_like : 'NåNa' matches 'Banana'

type

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.

property

"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.

property_like

"key=value" or { key: string, value: string }

As property but using diacritical- & case-insensitive substring match. See text_like

child

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".

descendant

json

As child but can match descendants at any level.

index

int

Specifies which index of the results you want to return. This specifier is always evaluated last.

Evaluation

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];
Clone this wiki locally