question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Advanced usage of native '-ios uiautomation' search strategy on IOS

See original GitHub issue

Hi folks,

First I want to say that it’s not a bug but rather advanced usage guide. May be you’ll find it useful to add into docs.

I’d like to share my experience in using ‘-ios uiautomation’ search strategy with Predicates. After using Instruments/UIAutomation tool for a long time I paid attention on the following methods in UIAutomation JavaScript API:

(UIAElement) UIAElementArray.firstWithPredicate(PredicateString predicateString)
(UIAElementArray) UIAElementArray.withPredicate(PredicateString predicateString)

And it turned out that native JS search strategy (powered by Apple) provides much more flexibility than I was thinking before, it is almost just like Xpath. Predicates can be used to restrict an elements set to select only those ones for which some condition is true.

For example:

appiumDriver.findElementsByIosUIAutomation("collectionViews()[0].cells().withPredicate(\"ANY staticTexts.isVisible == TRUE\")")

- will select only those UIACollectionCell elements that have visible UIAStaticText child elements, and themselves are childs of 1st UIACollectionView element that should be located under the main app window. Here staticTexts() and isVisible() are methods available in UIAElementArray and UIAElement classes respectively. Note that UIAElementArray numbering begins with 0 unlike Xpath where indexes counting starts from 1

Here’s a list of available Predicates

(mostly taken from Predicates Programming Guide)

Basic Comparisons

= , ==

  • The left-hand expression is equal to the right-hand expression:
tableViews()[1].cells().firstWithPredicate("label == 'Olivia' ")

same in Xpath: /UIATableView[2]/UIATableCell[@label = 'Olivia'][1]

= , =>

  • The left-hand expression is greater than or equal to the right-hand expression.

<= , =<

  • The left-hand expression is less than or equal to the right-hand expression.
  • The left-hand expression is greater than the right-hand expression.

<

  • The left-hand expression is less than the right-hand expression.

!= , <>

  • The left-hand expression is not equal to the right-hand expression.

BETWEEN

  • The left-hand expression is between, or equal to either of, the values specified in the right-hand side. The right-hand side is a two value array (an array is required to specify order) giving upper and lower bounds. For example, 1 BETWEEN { 0 , 33 }, or $INPUT BETWEEN { $LOWER, $UPPER }. In Objective-C, you could create a BETWEEN predicate as shown in the following example:
NSPredicate *betweenPredicate =
    [NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];

This creates a predicate that matches ( ( 1 <= attributeValue ) && ( attributeValue <= 10 ) )

Boolean Value Predicates

TRUEPREDICATE

  • A predicate that always evaluates to TRUE .

FALSEPREDICATE

  • A predicate that always evaluates to FALSE.

Basic Compound Predicates

AND , &&

  • Logical AND.

OR , ||

  • Logical OR.

NOT , !

  • Logical NOT.

String Comparisons

String comparisons are by default case and diacritic sensitive. You can modify an operator using the key characters c and d within square braces to specify case and diacritic insensitivity respectively, for example firstName BEGINSWITH[cd] $FIRST_NAME

BEGINSWITH

  • The left-hand expression begins with the right-hand expression.
scrollViews()[3].buttons().firstWithPredicate("name BEGINSWITH 'results toggle' ")

same in Xpath: /UIAScrollView[4]/UIAButton[starts-with(@name, 'results toggle')][1]

CONTAINS

  • The left-hand expression contains the right-hand expression.
tableViews()[1].cells().withPredicate("ANY collectionViews[0].buttons.name CONTAINS 'opera'")

same in Xpath: /UIATableView[2]/UIATableCell[UIACollectionView[1]/UIAButton[contains(@name, 'opera')]]

ENDSWITH

  • The left-hand expression ends with the right-hand expression.

LIKE

  • The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters. In Mac OS X v10.4, wildcard characters do not match newline characters.
tableViews()[0].cells().firstWithPredicate("name LIKE '*Total: $*' ")

same in Xpath: /UIATableView[1]/UIATableCell[matches(@name, '.*Total: \$.*')][1]

MATCHES

  • The left hand expression equals the right hand expression using a regex -style comparison according to ICU v3 (for more details see the ICU User Guide for Regular Expressions).
tableViews().firstWithPredicate("value MATCHES '.*of 7' ")

same in Xpath: /UIATableView[matches(@value, '.*of 7')][1]

Aggregate Operations

ANY , SOME

  • Specifies any of the elements in the following expression. For example ANY children.age < 18 .
tableViews()[0].cells().firstWithPredicate("SOME staticTexts.name = 'red'").staticTexts().withName('red')

same in Xpath: /UIATableView[1]/UIATableCell[UIAStaticText/@name = 'red'][1]/UIAStaticText[@name = 'red']

ALL

  • Specifies all of the elements in the following expression. For example ALL children.age < 18 .

NONE

  • Specifies none of the elements in the following expression. For example, NONE children.age < 18 . This is logically equivalent to NOT (ANY ...) .

IN

  • Equivalent to an SQL IN operation, the left-hand side must appear in the collection specified by the right-hand side. For example, name IN { 'Ben', 'Melissa', 'Matthew' } . The collection may be an array, a set, or a dictionary—in the case of a dictionary, its values are used.

array[index]

  • Specifies the element at the specified index in the array.

array[FIRST]

  • Specifies the first element in the array.

array[LAST]

  • Specifies the last element in the array.

array[SIZE]

  • Specifies the size of the array
elements()[0].tableViews()[0].cells().withPredicate("staticTexts[SIZE] > 2")

same in Xpath: /*[1]/UIATableView[1]/UIATableCell[count(UIAStaticText) > 2]

Identifiers

C style identifier

  • Any C style identifier that is not a reserved word.

#symbol

  • Used to escape a reserved word into a user identifier.

[]{octaldigit}{3}

  • Used to escape an octal number ( \ followed by 3 octal digits).

[][xX]{hexdigit}{2}

  • Used to escape a hex number ( \x or \X followed by 2 hex digits).

[][uU]{hexdigit}{4}

  • Used to escape a Unicode number ( \u or \U followed by 4 hex digits).

Literals

Single and double quotes produce the same result, but they do not terminate each other. For example, "abc" and 'abc' are identical, whereas "a'b'c" is equivalent to a space-separated concatenation of a, 'b', c.

FALSE , NO

  • Logical false.

TRUE , YES

  • Logical true.

NULL , NIL

  • A null value.

SELF

  • Represents the object being evaluated.

“text”

  • A character string.

‘text’

  • A character string.

Comma-separated literal array

  • For example, { 'comma', 'separated', 'literal', 'array' } .

Standard integer and fixed-point notations

  • For example, 1 , 27 , 2.71828 , 19.75 .

Floating-point notation with exponentiation

  • For example, 9.2e-5 .

0x

  • Prefix used to denote a hexadecimal digit sequence.

0o

  • Prefix used to denote an octal digit sequence.

0b

  • Prefix used to denote a binary digit sequence.

Reserved Words

The following words are reserved: AND, OR, IN, NOT, ALL, ANY, SOME, NONE, LIKE, CASEINSENSITIVE, CI, MATCHES, CONTAINS, BEGINSWITH, ENDSWITH, BETWEEN, NULL, NIL, SELF, TRUE, YES, FALSE, NO, FIRST, LAST, SIZE, ANYKEY, SUBQUERY, CAST, TRUEPREDICATE, FALSEPREDICATE

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Reactions:2
  • Comments:16 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
Jonahsscommented, Jun 27, 2016

Ah that’s a reasonable question. Sorry I don’t remember the specifics and it seems Apple took down the Instruments documentation because Instruments will not be available in iOS 10. So it may be better to not use the native ios automation locator strategy.

Appium will support ios 10 with XCUITest, but we removed the native ios automation locator strategy. Going with Accessibility ID or XPath is a better bet for the future.

0reactions
lock[bot]commented, Apr 29, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Understanding basics of iOS uiautomation selector strategy ...
I have been trying to understand how to use iOS UiAutomation locator strategy and find elements using it but it's not working on...
Read more >
UIAutomation (iOS)
The way to start a session using the UIAutomation driver is to set the platformName capability in your new session request to the...
Read more >
Ios Ui Automation Tutorial Pdf
like this ios ui automation tutorial pdf, but end up in harmful ... manage dependencies • How best to use Rust's advanced compiler...
Read more >
Advanced Locator Strategies in Appium
Appium implements a number of locator strategies that are specific to different mobile devices. Learn about the three available for both ...
Read more >
Ios predicate - appium - Read the Docs
It is worth looking at '-ios uiautomation' search strategy with Predicates. UIAutomation JavaScript API has following methods which can are very useful.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found