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.
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