appium_lib 9.5.0 → 9.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/docs/android_docs.md +512 -287
- data/docs/ios_docs.md +906 -315
- data/docs/ios_xcuitest.md +4 -0
- data/lib/appium_lib/android/device.rb +39 -0
- data/lib/appium_lib/android/element/button.rb +36 -65
- data/lib/appium_lib/android/element/generic.rb +20 -12
- data/lib/appium_lib/android/helper.rb +4 -16
- data/lib/appium_lib/android/uiautomator2/element/button.rb +110 -0
- data/lib/appium_lib/android/uiautomator2/helper.rb +85 -0
- data/lib/appium_lib/common/command.rb +9 -1
- data/lib/appium_lib/common/helper.rb +5 -4
- data/lib/appium_lib/common/patch.rb +21 -5
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/common/wait.rb +1 -0
- data/lib/appium_lib/device/device.rb +13 -23
- data/lib/appium_lib/device/multi_touch.rb +60 -20
- data/lib/appium_lib/device/touch_actions.rb +17 -8
- data/lib/appium_lib/driver.rb +79 -19
- data/lib/appium_lib/ios/element/button.rb +5 -25
- data/lib/appium_lib/ios/element/generic.rb +4 -22
- data/lib/appium_lib/ios/element/text.rb +5 -25
- data/lib/appium_lib/ios/element/textfield.rb +31 -78
- data/lib/appium_lib/ios/helper.rb +11 -74
- data/lib/appium_lib/ios/mobile_methods.rb +0 -20
- data/lib/appium_lib/ios/patch.rb +2 -6
- data/lib/appium_lib/ios/xcuitest/device.rb +59 -0
- data/lib/appium_lib/ios/xcuitest/element.rb +24 -0
- data/lib/appium_lib/ios/xcuitest/element/button.rb +64 -0
- data/lib/appium_lib/ios/xcuitest/element/generic.rb +50 -0
- data/lib/appium_lib/ios/xcuitest/element/text.rb +61 -0
- data/lib/appium_lib/ios/xcuitest/element/textfield.rb +94 -0
- data/lib/appium_lib/ios/{xcuitest_gestures.rb → xcuitest/gestures.rb} +10 -23
- data/lib/appium_lib/ios/xcuitest/helper.rb +103 -0
- data/lib/appium_lib/ios/xcuitest/mobile_methods.rb +23 -0
- data/release_notes.md +6 -0
- metadata +14 -3
@@ -6,7 +6,7 @@ module Appium
|
|
6
6
|
|
7
7
|
# @return [String] Class name for button
|
8
8
|
def button_class
|
9
|
-
|
9
|
+
UIAButton
|
10
10
|
end
|
11
11
|
|
12
12
|
# Find the first UIAButton|XCUIElementTypeButton that contains value or by index.
|
@@ -16,12 +16,7 @@ module Appium
|
|
16
16
|
def button(value)
|
17
17
|
# return button at index.
|
18
18
|
return ele_index button_class, value if value.is_a? Numeric
|
19
|
-
|
20
|
-
if automation_name_is_xcuitest?
|
21
|
-
raise_error_if_no_element buttons(value).first
|
22
|
-
else
|
23
|
-
ele_by_json_visible_contains button_class, value
|
24
|
-
end
|
19
|
+
ele_by_json_visible_contains button_class, value
|
25
20
|
end
|
26
21
|
|
27
22
|
# Find all UIAButtons|XCUIElementTypeButtons containing value.
|
@@ -30,13 +25,7 @@ module Appium
|
|
30
25
|
# @return [Array<UIAButton|XCUIElementTypeButton>]
|
31
26
|
def buttons(value = false)
|
32
27
|
return tags button_class unless value
|
33
|
-
|
34
|
-
if automation_name_is_xcuitest?
|
35
|
-
elements = find_eles_by_predicate_include(class_name: button_class, value: value)
|
36
|
-
select_visible_elements elements
|
37
|
-
else
|
38
|
-
eles_by_json_visible_contains button_class, value
|
39
|
-
end
|
28
|
+
eles_by_json_visible_contains button_class, value
|
40
29
|
end
|
41
30
|
|
42
31
|
# Find the first UIAButton|XCUIElementTypeButton.
|
@@ -57,23 +46,14 @@ module Appium
|
|
57
46
|
# @param value [String] the value to match exactly
|
58
47
|
# @return [UIAButton|XCUIElementTypeButton]
|
59
48
|
def button_exact(value)
|
60
|
-
|
61
|
-
raise_error_if_no_element buttons_exact(value).first
|
62
|
-
else
|
63
|
-
ele_by_json_visible_exact button_class, value
|
64
|
-
end
|
49
|
+
ele_by_json_visible_exact button_class, value
|
65
50
|
end
|
66
51
|
|
67
52
|
# Find all UIAButtons|XCUIElementTypeButtons that exactly match value.
|
68
53
|
# @param value [String] the value to match exactly
|
69
54
|
# @return [Array<UIAButton|XCUIElementTypeButton>]
|
70
55
|
def buttons_exact(value)
|
71
|
-
|
72
|
-
elements = find_eles_by_predicate(class_name: button_class, value: value)
|
73
|
-
select_visible_elements elements
|
74
|
-
else
|
75
|
-
eles_by_json_visible_exact button_class, value
|
76
|
-
end
|
56
|
+
eles_by_json_visible_exact button_class, value
|
77
57
|
end
|
78
58
|
end # module Ios
|
79
59
|
end # module Appium
|
@@ -4,46 +4,28 @@ module Appium
|
|
4
4
|
# @param value [String] the value to search for
|
5
5
|
# @return [Element]
|
6
6
|
def find(value)
|
7
|
-
|
8
|
-
raise_error_if_no_element finds(value).first
|
9
|
-
else
|
10
|
-
ele_by_json_visible_contains '*', value
|
11
|
-
end
|
7
|
+
ele_by_json_visible_contains '*', value
|
12
8
|
end
|
13
9
|
|
14
10
|
# Find all elements containing value
|
15
11
|
# @param value [String] the value to search for
|
16
12
|
# @return [Array<Element>]
|
17
13
|
def finds(value)
|
18
|
-
|
19
|
-
elements = find_eles_by_predicate_include value: value
|
20
|
-
select_visible_elements elements
|
21
|
-
else
|
22
|
-
eles_by_json_visible_contains '*', value
|
23
|
-
end
|
14
|
+
eles_by_json_visible_contains '*', value
|
24
15
|
end
|
25
16
|
|
26
17
|
# Find the first element exactly matching value
|
27
18
|
# @param value [String] the value to search for
|
28
19
|
# @return [Element]
|
29
20
|
def find_exact(value)
|
30
|
-
|
31
|
-
raise_error_if_no_element finds_exact(value).first
|
32
|
-
else
|
33
|
-
ele_by_json_visible_exact '*', value
|
34
|
-
end
|
21
|
+
ele_by_json_visible_exact '*', value
|
35
22
|
end
|
36
23
|
|
37
24
|
# Find all elements exactly matching value
|
38
25
|
# @param value [String] the value to search for
|
39
26
|
# @return [Array<Element>]
|
40
27
|
def finds_exact(value)
|
41
|
-
|
42
|
-
elements = find_eles_by_predicate value: value
|
43
|
-
select_visible_elements elements
|
44
|
-
else
|
45
|
-
eles_by_json_visible_exact '*', value
|
46
|
-
end
|
28
|
+
eles_by_json_visible_exact '*', value
|
47
29
|
end
|
48
30
|
|
49
31
|
private
|
@@ -6,7 +6,7 @@ module Appium
|
|
6
6
|
|
7
7
|
# @return [String] Class name for text
|
8
8
|
def static_text_class
|
9
|
-
|
9
|
+
UIAStaticText
|
10
10
|
end
|
11
11
|
|
12
12
|
# Find the first UIAStaticText|XCUIElementTypeStaticText that contains value or by index.
|
@@ -15,12 +15,7 @@ module Appium
|
|
15
15
|
# @return [UIAStaticText|XCUIElementTypeStaticText]
|
16
16
|
def text(value)
|
17
17
|
return ele_index static_text_class, value if value.is_a? Numeric
|
18
|
-
|
19
|
-
if automation_name_is_xcuitest?
|
20
|
-
raise_error_if_no_element texts(value).first
|
21
|
-
else
|
22
|
-
ele_by_json_visible_contains static_text_class, value
|
23
|
-
end
|
18
|
+
ele_by_json_visible_contains static_text_class, value
|
24
19
|
end
|
25
20
|
|
26
21
|
# Find all UIAStaticTexts|XCUIElementTypeStaticTexts containing value.
|
@@ -29,13 +24,7 @@ module Appium
|
|
29
24
|
# @return [Array<UIAStaticText|XCUIElementTypeStaticText>]
|
30
25
|
def texts(value = false)
|
31
26
|
return tags static_text_class unless value
|
32
|
-
|
33
|
-
if automation_name_is_xcuitest?
|
34
|
-
elements = find_eles_by_predicate_include(class_name: static_text_class, value: value)
|
35
|
-
select_visible_elements elements
|
36
|
-
else
|
37
|
-
eles_by_json_visible_contains static_text_class, value
|
38
|
-
end
|
27
|
+
eles_by_json_visible_contains static_text_class, value
|
39
28
|
end
|
40
29
|
|
41
30
|
# Find the first UIAStaticText|XCUIElementTypeStaticText.
|
@@ -54,23 +43,14 @@ module Appium
|
|
54
43
|
# @param value [String] the value to match exactly
|
55
44
|
# @return [UIAStaticText|XCUIElementTypeStaticText]
|
56
45
|
def text_exact(value)
|
57
|
-
|
58
|
-
raise_error_if_no_element texts_exact(value).first
|
59
|
-
else
|
60
|
-
ele_by_json_visible_exact static_text_class, value
|
61
|
-
end
|
46
|
+
ele_by_json_visible_exact static_text_class, value
|
62
47
|
end
|
63
48
|
|
64
49
|
# Find all UIAStaticTexts|XCUIElementTypeStaticTexts that exactly match value.
|
65
50
|
# @param value [String] the value to match exactly
|
66
51
|
# @return [Array<UIAStaticText|XCUIElementTypeStaticText>]
|
67
52
|
def texts_exact(value)
|
68
|
-
|
69
|
-
elements = find_eles_by_predicate(class_name: static_text_class, value: value)
|
70
|
-
select_visible_elements elements
|
71
|
-
else
|
72
|
-
eles_by_json_visible_exact static_text_class, value
|
73
|
-
end
|
53
|
+
eles_by_json_visible_exact static_text_class, value
|
74
54
|
end
|
75
55
|
end # module Ios
|
76
56
|
end # module Appium
|
@@ -8,50 +8,14 @@ module Appium
|
|
8
8
|
|
9
9
|
# @return [String] Class name for text field
|
10
10
|
def text_field_class
|
11
|
-
|
11
|
+
UIATextField
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [String] Class name for secure text field
|
15
15
|
def secure_text_field_class
|
16
|
-
|
16
|
+
UIASecureTextField
|
17
17
|
end
|
18
18
|
|
19
|
-
private
|
20
|
-
|
21
|
-
# @private
|
22
|
-
# for XCUITest
|
23
|
-
def _textfield_with_predicate
|
24
|
-
raise_error_if_no_element _textfields_with_predicate.first
|
25
|
-
end
|
26
|
-
|
27
|
-
# @private
|
28
|
-
# for XCUITest
|
29
|
-
def _textfields_with_predicate
|
30
|
-
elements = tags_include(class_names: [text_field_class, secure_text_field_class])
|
31
|
-
select_visible_elements elements
|
32
|
-
end
|
33
|
-
|
34
|
-
# Appium
|
35
|
-
def _textfield_visible
|
36
|
-
{ typeArray: [UIATextField, UIASecureTextField], onlyVisible: true }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Appium
|
40
|
-
def _textfield_exact_string(value)
|
41
|
-
exact = { target: value, substring: false, insensitive: false }
|
42
|
-
exact_obj = { name: exact, label: exact, value: exact }
|
43
|
-
_textfield_visible.merge(exact_obj)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Appium
|
47
|
-
def _textfield_contains_string(value)
|
48
|
-
contains = { target: value, substring: true, insensitive: true }
|
49
|
-
contains_obj = { name: contains, label: contains, value: contains }
|
50
|
-
_textfield_visible.merge(contains_obj)
|
51
|
-
end
|
52
|
-
|
53
|
-
public
|
54
|
-
|
55
19
|
# Find the first TextField that contains value or by index.
|
56
20
|
# Note: Uses XPath
|
57
21
|
# @param value [String, Integer] the text to match exactly.
|
@@ -62,21 +26,13 @@ module Appium
|
|
62
26
|
index = value
|
63
27
|
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
64
28
|
index -= 1 # eles_by_json and _textfields_with_predicate is 0 indexed.
|
65
|
-
result =
|
66
|
-
_textfields_with_predicate[index]
|
67
|
-
else
|
68
|
-
eles_by_json(_textfield_visible)[index]
|
69
|
-
end
|
29
|
+
result = eles_by_json(_textfield_visible)[index]
|
70
30
|
raise _no_such_element if result.nil?
|
71
31
|
return result
|
72
32
|
|
73
33
|
end
|
74
34
|
|
75
|
-
|
76
|
-
raise_error_if_no_element textfields(value).first
|
77
|
-
else
|
78
|
-
ele_by_json _textfield_contains_string value
|
79
|
-
end
|
35
|
+
ele_by_json _textfield_contains_string value
|
80
36
|
end
|
81
37
|
|
82
38
|
# Find all TextFields containing value.
|
@@ -84,35 +40,20 @@ module Appium
|
|
84
40
|
# @param value [String] the value to search for
|
85
41
|
# @return [Array<TextField>]
|
86
42
|
def textfields(value = false)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
elements = tags_include class_names: [text_field_class, secure_text_field_class], value: value
|
91
|
-
select_visible_elements elements
|
92
|
-
else
|
93
|
-
return eles_by_json _textfield_visible unless value
|
94
|
-
eles_by_json _textfield_contains_string value
|
95
|
-
end
|
43
|
+
return eles_by_json _textfield_visible unless value
|
44
|
+
eles_by_json _textfield_contains_string value
|
96
45
|
end
|
97
46
|
|
98
47
|
# Find the first TextField.
|
99
48
|
# @return [TextField]
|
100
49
|
def first_textfield
|
101
|
-
|
102
|
-
_textfield_with_predicate
|
103
|
-
else
|
104
|
-
ele_by_json _textfield_visible
|
105
|
-
end
|
50
|
+
ele_by_json _textfield_visible
|
106
51
|
end
|
107
52
|
|
108
53
|
# Find the last TextField.
|
109
54
|
# @return [TextField]
|
110
55
|
def last_textfield
|
111
|
-
result =
|
112
|
-
_textfields_with_predicate.last
|
113
|
-
else
|
114
|
-
eles_by_json(_textfield_visible).last
|
115
|
-
end
|
56
|
+
result = eles_by_json(_textfield_visible).last
|
116
57
|
raise _no_such_element if result.nil?
|
117
58
|
result
|
118
59
|
end
|
@@ -121,23 +62,35 @@ module Appium
|
|
121
62
|
# @param value [String] the value to match exactly
|
122
63
|
# @return [TextField]
|
123
64
|
def textfield_exact(value)
|
124
|
-
|
125
|
-
raise_error_if_no_element textfields_exact(value).first
|
126
|
-
else
|
127
|
-
ele_by_json _textfield_exact_string value
|
128
|
-
end
|
65
|
+
ele_by_json _textfield_exact_string value
|
129
66
|
end
|
130
67
|
|
131
68
|
# Find all TextFields that exactly match value.
|
132
69
|
# @param value [String] the value to match exactly
|
133
70
|
# @return [Array<TextField>]
|
134
71
|
def textfields_exact(value)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
72
|
+
eles_by_json _textfield_exact_string value
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# Appium
|
78
|
+
def _textfield_visible
|
79
|
+
{ typeArray: [UIATextField, UIASecureTextField], onlyVisible: true }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Appium
|
83
|
+
def _textfield_exact_string(value)
|
84
|
+
exact = { target: value, substring: false, insensitive: false }
|
85
|
+
exact_obj = { name: exact, label: exact, value: exact }
|
86
|
+
_textfield_visible.merge(exact_obj)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Appium
|
90
|
+
def _textfield_contains_string(value)
|
91
|
+
contains = { target: value, substring: true, insensitive: true }
|
92
|
+
contains_obj = { name: contains, label: contains, value: contains }
|
93
|
+
_textfield_visible.merge(contains_obj)
|
141
94
|
end
|
142
95
|
end # module Ios
|
143
96
|
end # module Appium
|
@@ -189,12 +189,8 @@ module Appium
|
|
189
189
|
# Return the iOS version as an array of integers
|
190
190
|
# @return [Array<Integer>]
|
191
191
|
def ios_version
|
192
|
-
|
193
|
-
|
194
|
-
else
|
195
|
-
ios_version = execute_script 'UIATarget.localTarget().systemVersion()'
|
196
|
-
ios_version.split('.').map(&:to_i)
|
197
|
-
end
|
192
|
+
ios_version = execute_script 'UIATarget.localTarget().systemVersion()'
|
193
|
+
ios_version.split('.').map(&:to_i)
|
198
194
|
end
|
199
195
|
|
200
196
|
# Get the element of type class_name at matching index.
|
@@ -219,15 +215,7 @@ module Appium
|
|
219
215
|
|
220
216
|
# @private
|
221
217
|
def string_attr_exact(class_name, attr, value)
|
222
|
-
|
223
|
-
if attr == '*'
|
224
|
-
%((//#{class_name})[@*[.="#{value}"]])
|
225
|
-
else
|
226
|
-
%((//#{class_name})[@#{attr}="#{value}"])
|
227
|
-
end
|
228
|
-
else
|
229
|
-
%(//#{class_name}[@visible="true" and @#{attr}="#{value}"])
|
230
|
-
end
|
218
|
+
%(//#{class_name}[@visible="true" and @#{attr}="#{value}"])
|
231
219
|
end
|
232
220
|
|
233
221
|
# Find the first element exactly matching class and attribute value.
|
@@ -254,15 +242,7 @@ module Appium
|
|
254
242
|
|
255
243
|
# @private
|
256
244
|
def string_attr_include(class_name, attr, value)
|
257
|
-
|
258
|
-
if attr == '*'
|
259
|
-
%((//#{class_name})[@*[contains(translate(., "#{value.upcase}", "#{value}"), "#{value}")]])
|
260
|
-
else
|
261
|
-
%((//#{class_name})[contains(translate(@#{attr}, "#{value.upcase}", "#{value}"), "#{value}")])
|
262
|
-
end
|
263
|
-
else
|
264
|
-
%(//#{class_name}[@visible="true" and contains(translate(@#{attr},"#{value.upcase}", "#{value}"), "#{value}")])
|
265
|
-
end
|
245
|
+
%(//#{class_name}[@visible="true" and contains(translate(@#{attr},"#{value.upcase}", "#{value}"), "#{value}")])
|
266
246
|
end
|
267
247
|
|
268
248
|
# Find the first element exactly matching attribute case insensitive value.
|
@@ -346,13 +326,7 @@ module Appium
|
|
346
326
|
# @param class_name [String] the tag to match
|
347
327
|
# @return [Element]
|
348
328
|
def last_ele(class_name)
|
349
|
-
|
350
|
-
visible_elements = tags class_name
|
351
|
-
raise _no_such_element if visible_elements.empty?
|
352
|
-
visible_elements.last
|
353
|
-
else
|
354
|
-
ele_index class_name, 'last()'
|
355
|
-
end
|
329
|
+
ele_index class_name, 'last()'
|
356
330
|
end
|
357
331
|
|
358
332
|
# Returns the first **visible** element matching class_name
|
@@ -360,11 +334,7 @@ module Appium
|
|
360
334
|
# @param class_name [String] the class_name to search for
|
361
335
|
# @return [Element]
|
362
336
|
def tag(class_name)
|
363
|
-
|
364
|
-
raise_error_if_no_element tags(class_name).first
|
365
|
-
else
|
366
|
-
ele_by_json(typeArray: [class_name], onlyVisible: true)
|
367
|
-
end
|
337
|
+
ele_by_json(typeArray: [class_name], onlyVisible: true)
|
368
338
|
end
|
369
339
|
|
370
340
|
# Returns all visible elements matching class_name
|
@@ -372,12 +342,7 @@ module Appium
|
|
372
342
|
# @param class_name [String] the class_name to search for
|
373
343
|
# @return [Element]
|
374
344
|
def tags(class_name)
|
375
|
-
|
376
|
-
elements = @driver.find_elements :class, class_name
|
377
|
-
select_visible_elements elements
|
378
|
-
else
|
379
|
-
eles_by_json(typeArray: [class_name], onlyVisible: true)
|
380
|
-
end
|
345
|
+
eles_by_json(typeArray: [class_name], onlyVisible: true)
|
381
346
|
end
|
382
347
|
|
383
348
|
# Returns all visible elements matching class_names and value
|
@@ -390,22 +355,8 @@ module Appium
|
|
390
355
|
def tags_include(class_names:, value: nil)
|
391
356
|
return unless class_names.is_a? Array
|
392
357
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
predicate = if value
|
397
|
-
%((#{c_names}) && ) +
|
398
|
-
%((name contains[c] "#{value}" || label contains[c] "#{value}" || value contains[c] "#{value}"))
|
399
|
-
else
|
400
|
-
c_names
|
401
|
-
end
|
402
|
-
|
403
|
-
elements = @driver.find_elements :predicate, predicate
|
404
|
-
select_visible_elements elements
|
405
|
-
else
|
406
|
-
class_names.flat_map do |class_name|
|
407
|
-
value ? eles_by_json_visible_contains(class_name, value) : tags(class_name)
|
408
|
-
end
|
358
|
+
class_names.flat_map do |class_name|
|
359
|
+
value ? eles_by_json_visible_contains(class_name, value) : tags(class_name)
|
409
360
|
end
|
410
361
|
end
|
411
362
|
|
@@ -419,22 +370,8 @@ module Appium
|
|
419
370
|
def tags_exact(class_names:, value: nil)
|
420
371
|
return unless class_names.is_a? Array
|
421
372
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
predicate = if value
|
426
|
-
%((#{c_names}) && ) +
|
427
|
-
%((name ==[c] "#{value}" || label ==[c] "#{value}" || value ==[c] "#{value}"))
|
428
|
-
else
|
429
|
-
c_names
|
430
|
-
end
|
431
|
-
|
432
|
-
elements = @driver.find_elements :predicate, predicate
|
433
|
-
select_visible_elements elements
|
434
|
-
else
|
435
|
-
class_names.flat_map do |class_name|
|
436
|
-
value ? eles_by_json_visible_exact(class_name, value) : tags(class_name)
|
437
|
-
end
|
373
|
+
class_names.flat_map do |class_name|
|
374
|
+
value ? eles_by_json_visible_exact(class_name, value) : tags(class_name)
|
438
375
|
end
|
439
376
|
end
|
440
377
|
|