-
-
Notifications
You must be signed in to change notification settings - Fork 762
Expand file tree
/
Copy pathAppiumBy.java
More file actions
460 lines (405 loc) · 17.4 KB
/
AppiumBy.java
File metadata and controls
460 lines (405 loc) · 17.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.appium.java_client;
import com.google.common.base.Preconditions;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.openqa.selenium.By;
import org.openqa.selenium.By.Remotable;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.json.Json;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Strings.isNullOrEmpty;
@EqualsAndHashCode(callSuper = true)
public abstract class AppiumBy extends By implements Remotable {
@Getter
private final Parameters remoteParameters;
private final String locatorName;
protected AppiumBy(String selector, String locatorString, String locatorName) {
Preconditions.checkArgument(!isNullOrEmpty(locatorString), "Must supply a not empty locator value.");
this.remoteParameters = new Parameters(selector, locatorString);
this.locatorName = locatorName;
}
@Override
public List<WebElement> findElements(SearchContext context) {
return context.findElements(this);
}
@Override
public WebElement findElement(SearchContext context) {
return context.findElement(this);
}
@Override
public String toString() {
return String.format("%s.%s: %s", AppiumBy.class.getSimpleName(), locatorName, remoteParameters.value());
}
/**
* About Android accessibility
* https://developer.android.com/intl/ru/training/accessibility/accessible-app.html
* About iOS accessibility
* https://developer.apple.com/library/ios/documentation/UIKit/Reference/
* UIAccessibilityIdentification_Protocol/index.html
*
* @param accessibilityId id is a convenient UI automation accessibility Id.
* @return an instance of {@link AppiumBy.ByAndroidUIAutomator}
*/
public static By accessibilityId(final String accessibilityId) {
return new ByAccessibilityId(accessibilityId);
}
/**
* This locator strategy is only available in Espresso Driver mode.
*
* @param dataMatcherString is a valid json string detailing hamcrest matcher for Espresso onData().
* See <a href="http://appium.io/docs/en/writing-running-appium/android/espresso-datamatcher-selector/">
* the documentation</a> for more details
* @return an instance of {@link AppiumBy.ByAndroidDataMatcher}
*/
public static By androidDataMatcher(final String dataMatcherString) {
return new ByAndroidDataMatcher(dataMatcherString);
}
/**
* Refer to <a href="https://developer.android.com/training/testing/ui-automator">UI Automator</a> .
*
* @param uiautomatorText is Android UIAutomator string
* @return an instance of {@link ByAndroidUIAutomator}
*/
public static By androidUIAutomator(final String uiautomatorText) {
return new ByAndroidUIAutomator(uiautomatorText);
}
/**
* This locator strategy is only available in Espresso Driver mode.
*
* @param viewMatcherString is a valid json string detailing hamcrest matcher for Espresso onView().
* See <a href="http://appium.io/docs/en/writing-running-appium/android/espresso-datamatcher-selector/">
* the documentation</a> for more details
* @return an instance of {@link AppiumBy.ByAndroidViewMatcher}
*/
public static By androidViewMatcher(final String viewMatcherString) {
return new ByAndroidViewMatcher(viewMatcherString);
}
/**
* This locator strategy is available in Espresso Driver mode.
*
* @param tag is a view tag string
* @return an instance of {@link ByAndroidViewTag}
* @since Appium 1.8.2 beta
*/
public static By androidViewTag(final String tag) {
return new ByAndroidViewTag(tag);
}
/**
* For IOS it is the full name of the XCUI element and begins with XCUIElementType.
* For Android it is the full name of the UIAutomator2 class (e.g.: android.widget.TextView)
*
* @param selector the class name of the element
* @return an instance of {@link ByClassName}
*/
public static By className(final String selector) {
return new ByClassName(selector);
}
/**
* For IOS the element name.
* For Android it is the resource identifier.
*
* @param selector element id
* @return an instance of {@link ById}
*/
public static By id(final String selector) {
return new ById(selector);
}
/**
* For IOS the element name.
* For Android it is the resource identifier.
*
* @param selector element id
* @return an instance of {@link ByName}
*/
public static By name(final String selector) {
return new ByName(selector);
}
/**
* This type of locator requires the use of the 'customFindModules' capability and a
* separately-installed element finding plugin.
*
* @param selector selector to pass to the custom element finding plugin
* @return an instance of {@link ByCustom}
* @since Appium 1.9.2
*/
public static By custom(final String selector) {
return new ByCustom(selector);
}
/**
* This locator strategy is available only if OpenCV libraries and
* Node.js bindings are installed on the server machine.
*
* @param b64Template base64-encoded template image string. Supported image formats are the same
* as for OpenCV library.
* @return an instance of {@link ByImage}
* @see <a href="https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/image-comparison.md">
* The documentation on Image Comparison Features</a>
* @see <a href="https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js">
* The settings available for lookup fine-tuning</a>
* @since Appium 1.8.2
*/
public static By image(final String b64Template) {
return new ByImage(b64Template);
}
/**
* This locator strategy is available in XCUITest Driver mode.
*
* @param iOSClassChainString is a valid class chain locator string.
* See <a href="https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules">
* the documentation</a> for more details
* @return an instance of {@link AppiumBy.ByIosClassChain}
*/
public static By iOSClassChain(final String iOSClassChainString) {
return new ByIosClassChain(iOSClassChainString);
}
/**
* This locator strategy is available in XCUITest Driver mode.
*
* @param iOSNsPredicateString is an iOS NsPredicate String
* @return an instance of {@link AppiumBy.ByIosNsPredicate}
*/
public static By iOSNsPredicateString(final String iOSNsPredicateString) {
return new ByIosNsPredicate(iOSNsPredicateString);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode.
*
* @param selector is the value defined to the key attribute of the flutter element
* @return an instance of {@link AppiumBy.ByFlutterKey}
*/
public static FlutterBy flutterKey(final String selector) {
return new ByFlutterKey(selector);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode.
*
* @param selector is the Type of widget mounted in the app tree
* @return an instance of {@link AppiumBy.ByFlutterType}
*/
public static FlutterBy flutterType(final String selector) {
return new ByFlutterType(selector);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode.
*
* @param selector is the text that is present on the widget
* @return an instance of {@link AppiumBy.ByFlutterText}
*/
public static FlutterBy flutterText(final String selector) {
return new ByFlutterText(selector);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode.
*
* @param selector is the text that is partially present on the widget
* @return an instance of {@link AppiumBy.ByFlutterTextContaining}
*/
public static FlutterBy flutterTextContaining(final String selector) {
return new ByFlutterTextContaining(selector);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode.
*
* @param semanticsLabel represents the value assigned to the label attribute of semantics element
* @return an instance of {@link AppiumBy.ByFlutterSemanticsLabel}
*/
public static FlutterBy flutterSemanticsLabel(final String semanticsLabel) {
return new ByFlutterSemanticsLabel(semanticsLabel);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0.
*
* @param of represents the parent widget locator
* @param matching represents the descendant widget locator to match
* @param matchRoot determines whether to include the root widget in the search
* @param skipOffstage determines whether to skip offstage widgets
* @return an instance of {@link AppiumBy.ByFlutterDescendant}
*/
public static FlutterBy flutterDescendant(
final FlutterBy of,
final FlutterBy matching,
boolean matchRoot,
boolean skipOffstage) {
return new ByFlutterDescendant(of, matching, matchRoot, skipOffstage);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0.
*
* @param of represents the parent widget locator
* @param matching represents the descendant widget locator to match
* @return an instance of {@link AppiumBy.ByFlutterDescendant}
*/
public static FlutterBy flutterDescendant(final FlutterBy of, final FlutterBy matching) {
return flutterDescendant(of, matching, false, true);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0.
*
* @param of represents the child widget locator
* @param matching represents the ancestor widget locator to match
* @param matchRoot determines whether to include the root widget in the search
* @return an instance of {@link AppiumBy.ByFlutterAncestor}
*/
public static FlutterBy flutterAncestor(final FlutterBy of, final FlutterBy matching, boolean matchRoot) {
return new ByFlutterAncestor(of, matching, matchRoot);
}
/**
* This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0.
*
* @param of represents the child widget locator
* @param matching represents the ancestor widget locator to match
* @return an instance of {@link AppiumBy.ByFlutterAncestor}
*/
public static FlutterBy flutterAncestor(final FlutterBy of, final FlutterBy matching) {
return flutterAncestor(of, matching, false);
}
public static class ByAccessibilityId extends AppiumBy implements Serializable {
public ByAccessibilityId(String accessibilityId) {
super("accessibility id", accessibilityId, "accessibilityId");
}
}
public static class ByAndroidDataMatcher extends AppiumBy implements Serializable {
protected ByAndroidDataMatcher(String locatorString) {
super("-android datamatcher", locatorString, "androidDataMatcher");
}
}
public static class ByAndroidUIAutomator extends AppiumBy implements Serializable {
public ByAndroidUIAutomator(String uiautomatorText) {
super("-android uiautomator", uiautomatorText, "androidUIAutomator");
}
}
public static class ByAndroidViewMatcher extends AppiumBy implements Serializable {
protected ByAndroidViewMatcher(String locatorString) {
super("-android viewmatcher", locatorString, "androidViewMatcher");
}
}
public static class ByAndroidViewTag extends AppiumBy implements Serializable {
public ByAndroidViewTag(String tag) {
super("-android viewtag", tag, "androidViewTag");
}
}
public static class ById extends AppiumBy implements Serializable {
protected ById(String selector) {
super("id", selector, "id");
}
}
public static class ByName extends AppiumBy implements Serializable {
protected ByName(String selector) {
super("name", selector, "name");
}
}
public static class ByClassName extends AppiumBy implements Serializable {
protected ByClassName(String selector) {
super("class name", selector, "className");
}
}
public static class ByCustom extends AppiumBy implements Serializable {
protected ByCustom(String selector) {
super("-custom", selector, "custom");
}
}
public static class ByImage extends AppiumBy implements Serializable {
protected ByImage(String b64Template) {
super("-image", b64Template, "image");
}
}
public static class ByIosClassChain extends AppiumBy implements Serializable {
protected ByIosClassChain(String locatorString) {
super("-ios class chain", locatorString, "iOSClassChain");
}
}
public static class ByIosNsPredicate extends AppiumBy implements Serializable {
protected ByIosNsPredicate(String locatorString) {
super("-ios predicate string", locatorString, "iOSNsPredicate");
}
}
public abstract static class FlutterBy extends AppiumBy {
protected FlutterBy(String selector, String locatorString, String locatorName) {
super(selector, locatorString, locatorName);
}
}
public abstract static class FlutterByHierarchy extends FlutterBy {
private static final Json JSON = new Json();
protected FlutterByHierarchy(
String selector,
FlutterBy of,
FlutterBy matching,
Map<String, Object> properties,
String locatorName) {
super(selector, formatLocator(of, matching, properties), locatorName);
}
static Map<String, Object> parseFlutterLocator(FlutterBy by) {
Parameters params = by.getRemoteParameters();
return Map.of("using", params.using(), "value", params.value());
}
static String formatLocator(FlutterBy of, FlutterBy matching, Map<String, Object> properties) {
Map<String, Object> locator = new HashMap<>();
locator.put("of", parseFlutterLocator(of));
locator.put("matching", parseFlutterLocator(matching));
locator.put("parameters", properties);
return JSON.toJson(locator);
}
}
public static class ByFlutterType extends FlutterBy implements Serializable {
protected ByFlutterType(String locatorString) {
super("-flutter type", locatorString, "flutterType");
}
}
public static class ByFlutterKey extends FlutterBy implements Serializable {
protected ByFlutterKey(String locatorString) {
super("-flutter key", locatorString, "flutterKey");
}
}
public static class ByFlutterSemanticsLabel extends FlutterBy implements Serializable {
protected ByFlutterSemanticsLabel(String locatorString) {
super("-flutter semantics label", locatorString, "flutterSemanticsLabel");
}
}
public static class ByFlutterText extends FlutterBy implements Serializable {
protected ByFlutterText(String locatorString) {
super("-flutter text", locatorString, "flutterText");
}
}
public static class ByFlutterTextContaining extends FlutterBy implements Serializable {
protected ByFlutterTextContaining(String locatorString) {
super("-flutter text containing", locatorString, "flutterTextContaining");
}
}
public static class ByFlutterDescendant extends FlutterByHierarchy implements Serializable {
protected ByFlutterDescendant(FlutterBy of, FlutterBy matching, boolean matchRoot, boolean skipOffstage) {
super(
"-flutter descendant",
of,
matching,
Map.of("matchRoot", matchRoot, "skipOffstage", skipOffstage), "flutterDescendant");
}
}
public static class ByFlutterAncestor extends FlutterByHierarchy implements Serializable {
protected ByFlutterAncestor(FlutterBy of, FlutterBy matching, boolean matchRoot) {
super(
"-flutter ancestor",
of,
matching,
Map.of("matchRoot", matchRoot), "flutterAncestor");
}
}
}