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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/docs/android_docs.md +512 -287
  4. data/docs/ios_docs.md +906 -315
  5. data/docs/ios_xcuitest.md +4 -0
  6. data/lib/appium_lib/android/device.rb +39 -0
  7. data/lib/appium_lib/android/element/button.rb +36 -65
  8. data/lib/appium_lib/android/element/generic.rb +20 -12
  9. data/lib/appium_lib/android/helper.rb +4 -16
  10. data/lib/appium_lib/android/uiautomator2/element/button.rb +110 -0
  11. data/lib/appium_lib/android/uiautomator2/helper.rb +85 -0
  12. data/lib/appium_lib/common/command.rb +9 -1
  13. data/lib/appium_lib/common/helper.rb +5 -4
  14. data/lib/appium_lib/common/patch.rb +21 -5
  15. data/lib/appium_lib/common/version.rb +2 -2
  16. data/lib/appium_lib/common/wait.rb +1 -0
  17. data/lib/appium_lib/device/device.rb +13 -23
  18. data/lib/appium_lib/device/multi_touch.rb +60 -20
  19. data/lib/appium_lib/device/touch_actions.rb +17 -8
  20. data/lib/appium_lib/driver.rb +79 -19
  21. data/lib/appium_lib/ios/element/button.rb +5 -25
  22. data/lib/appium_lib/ios/element/generic.rb +4 -22
  23. data/lib/appium_lib/ios/element/text.rb +5 -25
  24. data/lib/appium_lib/ios/element/textfield.rb +31 -78
  25. data/lib/appium_lib/ios/helper.rb +11 -74
  26. data/lib/appium_lib/ios/mobile_methods.rb +0 -20
  27. data/lib/appium_lib/ios/patch.rb +2 -6
  28. data/lib/appium_lib/ios/xcuitest/device.rb +59 -0
  29. data/lib/appium_lib/ios/xcuitest/element.rb +24 -0
  30. data/lib/appium_lib/ios/xcuitest/element/button.rb +64 -0
  31. data/lib/appium_lib/ios/xcuitest/element/generic.rb +50 -0
  32. data/lib/appium_lib/ios/xcuitest/element/text.rb +61 -0
  33. data/lib/appium_lib/ios/xcuitest/element/textfield.rb +94 -0
  34. data/lib/appium_lib/ios/{xcuitest_gestures.rb → xcuitest/gestures.rb} +10 -23
  35. data/lib/appium_lib/ios/xcuitest/helper.rb +103 -0
  36. data/lib/appium_lib/ios/xcuitest/mobile_methods.rb +23 -0
  37. data/release_notes.md +6 -0
  38. 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
- automation_name_is_xcuitest? ? XCUIElementTypeButton : UIAButton
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- automation_name_is_xcuitest? ? XCUIElementTypeStaticText : UIAStaticText
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- automation_name_is_xcuitest? ? XCUIElementTypeTextField : UIATextField
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
- automation_name_is_xcuitest? ? XCUIElementTypeSecureTextField : UIASecureTextField
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 = if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
88
- return tags_include(class_names: [text_field_class, secure_text_field_class]) unless value
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
- if automation_name_is_xcuitest?
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 = if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
136
- elements = tags_exact class_names: [text_field_class, secure_text_field_class], value: value
137
- select_visible_elements elements
138
- else
139
- eles_by_json _textfield_exact_string value
140
- end
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
- if automation_name_is_xcuitest?
193
- @driver.capabilities['platformVersion']
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
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
- if automation_name_is_xcuitest?
394
- c_names = class_names.map { |class_name| %(type == "#{class_name}") }.join(' || ')
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
- if automation_name_is_xcuitest?
423
- c_names = class_names.map { |class_name| %(type == "#{class_name}") }.join(' || ')
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