Skip to content

Commit 5a899f9

Browse files
authored
docs: FindBy doc update (#1311)
1 parent c7cf1b1 commit 5a899f9

File tree

6 files changed

+168
-11
lines changed

6 files changed

+168
-11
lines changed

docs/Advanced-By.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Standard Selectors
2+
3+
## AndroidFindBy / iOSXCUITFindBy / WindowsFindBy
4+
5+
# Advanced Selectors
6+
7+
## iOS's String Predicates
8+
9+
You can specify a [predicate](https://developer.apple.com/documentation/foundation/nspredicate)
10+
in your Class Chain to limit the number of matched items. There's
11+
[a detailed guide to that](https://appium.io/docs/en/writing-running-appium/ios/ios-predicate/index.html)
12+
on the Appium Docs website with some Appium-specific considerations.
13+
14+
## iOS's Class Chain Queries
15+
16+
Our XCUiTest integration has full support for the 'Class Chain' concept. This
17+
can do much of what XPath does...but faster. Note that many Class Chains leverage
18+
String Predicates too.
19+
20+
### String Predicates in Class Chains
21+
22+
There's a special array-style syntax for defining predicates in a Class Chain:
23+
24+
```
25+
// Start with [
26+
// Followed by `
27+
// Followed by some text
28+
// Followed by `
29+
// End with ]
30+
[`label != 'a'`]
31+
[`isWDVisible == 1`]
32+
[`value < 0`]
33+
```
34+
35+
#### Searching Descendents
36+
37+
If you replace the backticks (`` ` ``) around a predicate with dollar signs (`$`),
38+
then the Class Chain will match against the children, grandchildren, and other
39+
descendants of each element.
40+
41+
```
42+
// Find a cell element with the label 'here'
43+
XCUIElementTypeCell[`label == 'here'`]
44+
// Find a cell element which contains SOMETHING ELSE that has the label 'here'
45+
XCUIElementTypeCell[$label == 'here'$]
46+
```
47+
48+
#### Handling Quote Marks
49+
50+
Most of the time, you can treat pairs of single quotes or double quotes
51+
interchangably. If you're searching with a string that contains quote marks,
52+
though, you [need to be careful](https://stackoverflow.com/q/14116217).
53+
54+
```c
55+
// Make sure to escape each quote mark that matches your delimiter
56+
"text with \"some\" 'quote' marks"
57+
// To NSPredicate, the line above and the line below are equivalent
58+
'text with "some" \'quote\' marks'
59+
```
60+
```java
61+
// When defining a iOSXCUITFindBy annotation, you'll be constrained by the
62+
// Java string-quoting rules too.
63+
@iOSXCUITFindBy(iOSClassChain = "**/SomeElement[`'text with \"some\" \\\'quote\\\' marks'`]")
64+
```
65+
66+
### External References
67+
68+
Refer to [the official WebDriverAgent query docs](https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules)
69+
to learn more about the general concept.
70+
71+
### Sample usage:
72+
73+
```java
74+
// Selector for image elements
75+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeImage")
76+
77+
// Selector for the first image element on screen
78+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeImage[1]")
79+
// Selector for the second image element on screen
80+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeImage[2]")
81+
// Selector for the last image element on screen
82+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeImage[-1]")
83+
// Selector for the penultimate image element on screen
84+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeImage[-2]")
85+
86+
// Selector for every cell with the name 'Foo' (single quote style)
87+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeCell[`name == 'Foo'`]")
88+
// Selector for every cell with the name "Foo" (double quote style)
89+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeCell[`name == \"Foo\"`]")
90+
91+
// Selector for every cell with a name that starts with 'Foo' (single quote style)
92+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeCell[`name BEGINSWITH 'Foo'`]")
93+
// Selector for every cell with a name that starts with "Foo" (double quote style)
94+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeCell[`name BEGINSWITH \"Foo\"`]")
95+
96+
// Selector for every cell with a name that starts with "it's not"
97+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeCell[`name BEGINSWITH \"it's not\"`]")
98+
99+
// Selector that'll match every top-level element on screen
100+
@iOSXCUITFindBy(iOSClassChain = "*")
101+
// Selector that'll match every leaf element on screen (watch out: this can be SLOW)
102+
@iOSXCUITFindBy(iOSClassChain = "**/*")
103+
104+
// You can place an index after a predicate: the following finds the last image element with name 'Foo'
105+
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeCell[`name == 'Foo'`][-1]")
106+
```
107+
108+
## Android's uiAutomator String
109+
110+
Available when using [AndroidBy](AndroidBy) and [AndroidFindBy](AndroidFindBy) with
111+
[appium-uiautomator2-server](https://github.com/appium/appium-uiautomator2-server). This
112+
string will be used by the server to construct a UiSelector or UiScrollable object.
113+
114+
### External References
115+
116+
For an overview of what the backend is capable of, please check out the
117+
118+
* [Main UI Automator Guide](https://developer.android.com/training/testing/ui-automator)
119+
* [UiScrollable API docs](https://developer.android.com/reference/androidx/test/uiautomator/UiScrollable)
120+
and
121+
* [UiSelector API docs](https://developer.android.com/reference/androidx/test/uiautomator/UiSelector)
122+
123+
### Sample Strings
124+
125+
Here are some ways you could configure a UiSelector in your project:
126+
127+
```java
128+
// Create a selector that looks for the text "Hello World":
129+
@AndroidFindBy(uiAutomator = "new UiSelector().text(\"Hello World\")")
130+
131+
// Create a selector that tries to find an ImageView:
132+
@AndroidFindBy(uiAutomator = "new UiSelector().className(\"android.widget.ImageView\")")
133+
134+
// Create a selector that matches resource ids against a regular expression:
135+
private static final String looksLikeAPage = "page_number_\d*";
136+
@AndroidFindBy(uiAutomator = "new UiSelector().resourceIdMatches(\"" + looksLikeAPage + "\")")
137+
138+
// The agent also supports some abbreviated forms - all 3 of the below
139+
// strings are equivalent.
140+
@AndroidFindBy(uiAutomator = "new UiSelector().className(\"android.widget.EditText\")")
141+
@AndroidFindBy(uiAutomator = "UiSelector().className(\"android.widget.EditText\")")
142+
@AndroidFindBy(uiAutomator = ".className(\"android.widget.EditText\")")
143+
144+
// You can connect up conditions to search for multiple things at once
145+
@AndroidFindBy(uiAutomator = ".resourceId(\"android:id/list\").classNameMatches(\"\.*RecyclerView\").index(3)")
146+
```
147+
148+
..and here are some that create UiScrollable objects:
149+
150+
```java
151+
private static final String ourImageSelector = ".className(\"android.widget.ImageView\")";
152+
private static final String ourListSelector = ".className(\"android.widget.ListView\")";
153+
154+
// Create a scrollable associated with a list (by itself, this doesn't do anything useful...)
155+
@AndroidFindBy(uiAutomator = "new UiScrollable(" + ourListSelector + ")")
156+
157+
// Create a scrollable that scrolls forward along a list until it finds an ImageView:
158+
@AndroidFindBy(uiAutomator = "new UiScrollable(" + ourListSelector + ").scrollIntoView(" + ourImageSelector + ")")
159+
160+
```

src/main/java/io/appium/java_client/MobileBy.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ protected MobileBy(MobileSelector selector, String locatorString) {
6262
}
6363

6464
/**
65-
* Read http://developer.android.com/intl/ru/tools/testing-support-library/
66-
* index.html#uia-apis
65+
* Refer to https://developer.android.com/training/testing/ui-automator
6766
* @param uiautomatorText is Android UIAutomator string
6867
* @return an instance of {@link io.appium.java_client.MobileBy.ByAndroidUIAutomator}
6968
*/
@@ -87,7 +86,7 @@ public static By AccessibilityId(final String accessibilityId) {
8786
/**
8887
* This locator strategy is available in XCUITest Driver mode.
8988
* @param iOSClassChainString is a valid class chain locator string.
90-
* See <a href="https://github.com/facebook/WebDriverAgent/wiki/Queries">
89+
* See <a href="https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules">
9190
* the documentation</a> for more details
9291
* @return an instance of {@link io.appium.java_client.MobileBy.ByIosClassChain}
9392
*/

src/main/java/io/appium/java_client/pagefactory/AndroidBy.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@
2121
*/
2222
public @interface AndroidBy {
2323
/**
24-
* It is an Android UIAutomator string.
25-
* Read http://developer.android.com/intl/ru/tools/testing-support-library/
26-
* index.html#uia-apis
24+
* A String that can build an Android UiSelector or UiScrollable object.
25+
* Refer to https://developer.android.com/training/testing/ui-automator
2726
*
2827
* @return an Android UIAutomator string
2928
*/

src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@
3636
@Repeatable(AndroidFindBySet.class)
3737
public @interface AndroidFindBy {
3838
/**
39-
* It is an Android UIAutomator string.
40-
* Read http://developer.android.com/intl/ru/tools/testing-support-library/
41-
* index.html#uia-apis
39+
* A String that can build an Android UiSelector or UiScrollable object.
40+
* Refer to https://developer.android.com/training/testing/ui-automator
4241
*
4342
* @return an Android UIAutomator string
4443
*/

src/main/java/io/appium/java_client/pagefactory/iOSXCUITBy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/**
2525
* The Class Chain locator is similar to xpath, but it's faster and can only
2626
* search direct children elements. See the
27-
* <a href="https://github.com/facebook/WebDriverAgent/wiki/Queries">
27+
* <a href="https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules">
2828
* documentation</a> for more details.
2929
*
3030
* @return iOS class chain

src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/**
3232
* The Class Chain locator is similar to xpath, but it's faster and can only
3333
* search direct children elements. See the
34-
* <a href="https://github.com/facebook/WebDriverAgent/wiki/Queries">
34+
* <a href="https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules">
3535
* documentation</a> for more details.
3636
*
3737
* @return iOS class chain

0 commit comments

Comments
 (0)