appium_lib 9.5.0 → 9.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|