appium_lib 6.0.0 → 7.0.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +28 -0
  4. data/.travis.yml +10 -0
  5. data/Rakefile +9 -1
  6. data/android_tests/Gemfile +1 -1
  7. data/android_tests/Rakefile +20 -13
  8. data/android_tests/lib/android/specs/android/element/alert.rb +1 -1
  9. data/android_tests/lib/android/specs/android/element/button.rb +2 -2
  10. data/android_tests/lib/android/specs/android/element/generic.rb +1 -2
  11. data/android_tests/lib/android/specs/android/element/text.rb +2 -3
  12. data/android_tests/lib/android/specs/android/element/textfield.rb +2 -2
  13. data/android_tests/lib/android/specs/android/helper.rb +5 -3
  14. data/android_tests/lib/android/specs/android/patch.rb +2 -2
  15. data/android_tests/lib/android/specs/common/device.rb +16 -9
  16. data/android_tests/lib/android/specs/common/device_touchaction.rb +5 -2
  17. data/android_tests/lib/android/specs/common/element/window.rb +1 -1
  18. data/android_tests/lib/android/specs/common/helper.rb +14 -15
  19. data/android_tests/lib/android/specs/common/patch.rb +11 -9
  20. data/android_tests/lib/android/specs/common/version.rb +3 -3
  21. data/android_tests/lib/android/specs/common/web_context.rb +2 -3
  22. data/android_tests/lib/android/specs/driver.rb +38 -29
  23. data/android_tests/lib/android/specs/install.rb +3 -3
  24. data/android_tests/lib/format.rb +6 -8
  25. data/android_tests/lib/run.rb +25 -17
  26. data/android_tests/readme.md +4 -2
  27. data/appium_lib.gemspec +13 -11
  28. data/contributing.md +1 -1
  29. data/docs/android_docs.md +358 -274
  30. data/docs/ios_docs.md +333 -270
  31. data/docs/migration.md +10 -0
  32. data/docs_gen/make_docs.rb +3 -1
  33. data/ios_tests/Gemfile +1 -1
  34. data/ios_tests/Rakefile +17 -10
  35. data/ios_tests/appium.txt +1 -1
  36. data/ios_tests/lib/common.rb +8 -4
  37. data/ios_tests/lib/format.rb +5 -7
  38. data/ios_tests/lib/ios/specs/common/element/window.rb +1 -1
  39. data/ios_tests/lib/ios/specs/common/helper.rb +40 -39
  40. data/ios_tests/lib/ios/specs/common/patch.rb +15 -11
  41. data/ios_tests/lib/ios/specs/common/version.rb +3 -3
  42. data/ios_tests/lib/ios/specs/common/web_context.rb +1 -2
  43. data/ios_tests/lib/ios/specs/device/device.rb +7 -7
  44. data/ios_tests/lib/ios/specs/device/multi_touch.rb +6 -8
  45. data/ios_tests/lib/ios/specs/device/touch_actions.rb +12 -12
  46. data/ios_tests/lib/ios/specs/driver.rb +23 -22
  47. data/ios_tests/lib/ios/specs/ios/element/alert.rb +6 -2
  48. data/ios_tests/lib/ios/specs/ios/element/button.rb +2 -2
  49. data/ios_tests/lib/ios/specs/ios/element/generic.rb +1 -1
  50. data/ios_tests/lib/ios/specs/ios/element/text.rb +4 -1
  51. data/ios_tests/lib/ios/specs/ios/element/textfield.rb +6 -6
  52. data/ios_tests/lib/ios/specs/ios/helper.rb +5 -5
  53. data/ios_tests/lib/ios/specs/ios/patch.rb +2 -2
  54. data/ios_tests/lib/run.rb +1 -1
  55. data/ios_tests/readme.md +3 -3
  56. data/ios_tests/upload/sauce_storage.rb +8 -8
  57. data/ios_tests/upload/upload.rb +1 -1
  58. data/lib/appium_lib/android/client_xpath.rb +7 -7
  59. data/lib/appium_lib/android/element/alert.rb +2 -2
  60. data/lib/appium_lib/android/element/button.rb +16 -16
  61. data/lib/appium_lib/android/element/generic.rb +12 -13
  62. data/lib/appium_lib/android/element/text.rb +5 -5
  63. data/lib/appium_lib/android/element/textfield.rb +5 -5
  64. data/lib/appium_lib/android/helper.rb +82 -52
  65. data/lib/appium_lib/android/mobile_methods.rb +2 -2
  66. data/lib/appium_lib/android/patch.rb +3 -3
  67. data/lib/appium_lib/common/element/window.rb +1 -1
  68. data/lib/appium_lib/common/helper.rb +30 -35
  69. data/lib/appium_lib/common/patch.rb +22 -20
  70. data/lib/appium_lib/common/version.rb +3 -3
  71. data/lib/appium_lib/common/wait.rb +9 -10
  72. data/lib/appium_lib/device/device.rb +39 -33
  73. data/lib/appium_lib/device/multi_touch.rb +5 -7
  74. data/lib/appium_lib/device/touch_actions.rb +14 -15
  75. data/lib/appium_lib/driver.rb +97 -76
  76. data/lib/appium_lib/ios/element/alert.rb +1 -1
  77. data/lib/appium_lib/ios/element/button.rb +5 -5
  78. data/lib/appium_lib/ios/element/generic.rb +5 -6
  79. data/lib/appium_lib/ios/element/text.rb +5 -5
  80. data/lib/appium_lib/ios/element/textfield.rb +15 -15
  81. data/lib/appium_lib/ios/helper.rb +103 -90
  82. data/lib/appium_lib/ios/mobile_methods.rb +2 -2
  83. data/lib/appium_lib/ios/patch.rb +4 -4
  84. data/lib/appium_lib/logger.rb +7 -5
  85. data/lib/appium_lib/rails/duplicable.rb +3 -1
  86. data/readme.md +7 -1
  87. data/release_notes.md +152 -0
  88. metadata +28 -54
@@ -16,4 +16,4 @@ module Appium
16
16
  driver.send(:bridge).dismissAlert
17
17
  end
18
18
  end # module Ios
19
- end # module Appium
19
+ end # module Appium
@@ -7,7 +7,7 @@ module Appium
7
7
  # @param value [String, Integer] the value to exactly match.
8
8
  # If int then the UIAButton at that index is returned.
9
9
  # @return [UIAButton]
10
- def button value
10
+ def button(value)
11
11
  # return button at index.
12
12
  return ele_index UIAButton, value if value.is_a? Numeric
13
13
  ele_by_json_visible_contains UIAButton, value
@@ -17,7 +17,7 @@ module Appium
17
17
  # If value is omitted, all UIAButtons are returned.
18
18
  # @param value [String] the value to search for
19
19
  # @return [Array<UIAButton>]
20
- def buttons value=false
20
+ def buttons(value = false)
21
21
  return tags UIAButton unless value
22
22
  eles_by_json_visible_contains UIAButton, value
23
23
  end
@@ -37,15 +37,15 @@ module Appium
37
37
  # Find the first UIAButton that exactly matches value.
38
38
  # @param value [String] the value to match exactly
39
39
  # @return [UIAButton]
40
- def button_exact value
40
+ def button_exact(value)
41
41
  ele_by_json_visible_exact UIAButton, value
42
42
  end
43
43
 
44
44
  # Find all UIAButtons that exactly match value.
45
45
  # @param value [String] the value to match exactly
46
46
  # @return [Array<UIAButton>]
47
- def buttons_exact value
47
+ def buttons_exact(value)
48
48
  eles_by_json_visible_exact UIAButton, value
49
49
  end
50
50
  end # module Ios
51
- end # module Appium
51
+ end # module Appium
@@ -1,32 +1,31 @@
1
1
  module Appium
2
2
  module Ios
3
-
4
3
  # Find the first element containing value
5
4
  # @param value [String] the value to search for
6
5
  # @return [Element]
7
- def find value
6
+ def find(value)
8
7
  ele_by_json_visible_contains '*', value
9
8
  end
10
9
 
11
10
  # Find all elements containing value
12
11
  # @param value [String] the value to search for
13
12
  # @return [Array<Element>]
14
- def finds value
13
+ def finds(value)
15
14
  eles_by_json_visible_contains '*', value
16
15
  end
17
16
 
18
17
  # Find the first element exactly matching value
19
18
  # @param value [String] the value to search for
20
19
  # @return [Element]
21
- def find_exact value
20
+ def find_exact(value)
22
21
  ele_by_json_visible_exact '*', value
23
22
  end
24
23
 
25
24
  # Find all elements exactly matching value
26
25
  # @param value [String] the value to search for
27
26
  # @return [Array<Element>]
28
- def finds_exact value
27
+ def finds_exact(value)
29
28
  eles_by_json_visible_exact '*', value
30
29
  end
31
30
  end # module Ios
32
- end # module Appium
31
+ end # module Appium
@@ -7,7 +7,7 @@ module Appium
7
7
  # @param value [String, Integer] the value to find.
8
8
  # If int then the UIAStaticText at that index is returned.
9
9
  # @return [UIAStaticText]
10
- def text value
10
+ def text(value)
11
11
  return ele_index UIAStaticText, value if value.is_a? Numeric
12
12
  ele_by_json_visible_contains UIAStaticText, value
13
13
  end
@@ -16,7 +16,7 @@ module Appium
16
16
  # If value is omitted, all UIAStaticTexts are returned
17
17
  # @param value [String] the value to search for
18
18
  # @return [Array<UIAStaticText>]
19
- def texts value=false
19
+ def texts(value = false)
20
20
  return tags UIAStaticText unless value
21
21
  eles_by_json_visible_contains UIAStaticText, value
22
22
  end
@@ -36,15 +36,15 @@ module Appium
36
36
  # Find the first UIAStaticText that exactly matches value.
37
37
  # @param value [String] the value to match exactly
38
38
  # @return [UIAStaticText]
39
- def text_exact value
39
+ def text_exact(value)
40
40
  ele_by_json_visible_exact UIAStaticText, value
41
41
  end
42
42
 
43
43
  # Find all UIAStaticTexts that exactly match value.
44
44
  # @param value [String] the value to match exactly
45
45
  # @return [Array<UIAStaticText>]
46
- def texts_exact value
46
+ def texts_exact(value)
47
47
  eles_by_json_visible_exact UIAStaticText, value
48
48
  end
49
49
  end # module Ios
50
- end # module Appium
50
+ end # module Appium
@@ -9,36 +9,36 @@ module Appium
9
9
  def _textfield_visible
10
10
  {
11
11
  typeArray: [UIATextField, UIASecureTextField],
12
- onlyVisible: true,
12
+ onlyVisible: true
13
13
  }
14
14
  end
15
15
 
16
16
  # @private
17
- def _textfield_exact_string value
17
+ def _textfield_exact_string(value)
18
18
  exact = {
19
19
  target: value,
20
20
  substring: false,
21
- insensitive: false,
21
+ insensitive: false
22
22
  }
23
23
  exact_obj = {
24
24
  name: exact,
25
25
  label: exact,
26
- value: exact,
26
+ value: exact
27
27
  }
28
28
  _textfield_visible.merge(exact_obj)
29
29
  end
30
30
 
31
31
  # @private
32
- def _textfield_contains_string value
32
+ def _textfield_contains_string(value)
33
33
  contains = {
34
34
  target: value,
35
35
  substring: true,
36
- insensitive: true,
36
+ insensitive: true
37
37
  }
38
38
  contains_obj = {
39
39
  name: contains,
40
40
  label: contains,
41
- value: contains,
41
+ value: contains
42
42
  }
43
43
  _textfield_visible.merge(contains_obj)
44
44
  end
@@ -49,16 +49,16 @@ module Appium
49
49
  # @param value [String, Integer] the text to match exactly.
50
50
  # If int then the TextField at that index is returned.
51
51
  # @return [TextField]
52
- def textfield value
52
+ def textfield(value)
53
53
  # Don't use ele_index because that only works on one element type.
54
54
  # iOS needs to combine textfield and secure to match Android.
55
55
  if value.is_a? Numeric
56
56
  index = value
57
- raise "#{index} is not a valid index. Must be >= 1" if index <= 0
57
+ fail "#{index} is not a valid index. Must be >= 1" if index <= 0
58
58
  index -= 1 # eles_by_json is 0 indexed.
59
59
 
60
60
  result = eles_by_json(_textfield_visible)[index]
61
- raise _no_such_element if result.nil?
61
+ fail _no_such_element if result.nil?
62
62
  return result
63
63
  end
64
64
 
@@ -69,7 +69,7 @@ module Appium
69
69
  # If value is omitted, all TextFields are returned.
70
70
  # @param value [String] the value to search for
71
71
  # @return [Array<TextField>]
72
- def textfields value=false
72
+ def textfields(value = false)
73
73
  return eles_by_json _textfield_visible unless value
74
74
  eles_by_json _textfield_contains_string value
75
75
  end
@@ -84,22 +84,22 @@ module Appium
84
84
  # @return [TextField]
85
85
  def last_textfield
86
86
  result = eles_by_json(_textfield_visible).last
87
- raise _no_such_element if result.nil?
87
+ fail _no_such_element if result.nil?
88
88
  result
89
89
  end
90
90
 
91
91
  # Find the first TextField that exactly matches value.
92
92
  # @param value [String] the value to match exactly
93
93
  # @return [TextField]
94
- def textfield_exact value
94
+ def textfield_exact(value)
95
95
  ele_by_json _textfield_exact_string value
96
96
  end
97
97
 
98
98
  # Find all TextFields that exactly match value.
99
99
  # @param value [String] the value to match exactly
100
100
  # @return [Array<TextField>]
101
- def textfields_exact value
101
+ def textfields_exact(value)
102
102
  eles_by_json _textfield_exact_string value
103
103
  end
104
104
  end # module Ios
105
- end # module Appium
105
+ end # module Appium
@@ -5,7 +5,7 @@ module Appium
5
5
  # Password character returned from value of UIASecureTextField
6
6
  # @param length [Integer] the length of the password to generate
7
7
  # @return [String] the returned string is of size length
8
- def ios_password length=1
8
+ def ios_password(length = 1)
9
9
  8226.chr('UTF-8') * length
10
10
  end
11
11
 
@@ -17,17 +17,17 @@ module Appium
17
17
  # @option element [Object] the element to search. omit to search everything
18
18
  # @option class_name [String,Symbol] the class name to filter on. case insensitive include match.
19
19
  # @return [String]
20
- def get_page element=source_window(0), class_name=nil
20
+ def get_page(element = source_window(0), class_name = nil)
21
21
  lazy_load_strings # populate @strings_xml
22
22
  class_name = class_name.to_s.downcase
23
23
 
24
24
  # @private
25
- def empty ele
26
- (ele['name'] || ele['label'] || ele['value']) == nil
25
+ def empty(ele)
26
+ (ele['name'] || ele['label'] || ele['value']).nil?
27
27
  end
28
28
 
29
29
  # @private
30
- def fix_space s
30
+ def fix_space(s)
31
31
  # if s is an int, we can't call .empty
32
32
  return nil if s.nil? || (s.respond_to?(:empty) && s.empty?)
33
33
  # ints don't respond to force encoding
@@ -51,6 +51,9 @@ module Appium
51
51
  visible = fix_space element['visible']
52
52
  type = fix_space element['type']
53
53
 
54
+ # TODO: Rubocop warning cleanup
55
+ # rubocop:disable Metrics/BlockNesting
56
+
54
57
  # if class_name is set, mark non-matches as invisible
55
58
  visible = (type.downcase.include?(class_name)).to_s if class_name
56
59
  if visible && visible == 'true'
@@ -75,6 +78,7 @@ module Appium
75
78
  puts " value: #{value}" if value
76
79
  puts " hint: #{hint}" if hint
77
80
  end
81
+ # rubocop:enable Metrics/BlockNesting
78
82
 
79
83
  # there may be many ids with the same value.
80
84
  # output all exact matches.
@@ -93,10 +97,10 @@ module Appium
93
97
  match_str = ''
94
98
  max_len = id_matches.keys.max_by(&:length).length
95
99
 
96
- # [0] = key, [1] = value
97
- id_matches.each do |key, value|
100
+ # [0] = key, [1] = val
101
+ id_matches.each do |key, val|
98
102
  arrow_space = ' ' * (max_len - key.length).to_i
99
- match_str += ' ' * 7 + "#{key} #{arrow_space}=> #{value}\n"
103
+ match_str += ' ' * 7 + "#{key} #{arrow_space}=> #{val}\n"
100
104
  end
101
105
  puts " id: #{match_str.strip}\n"
102
106
  end
@@ -122,7 +126,7 @@ module Appium
122
126
  # @option class [Symbol] class name to filter on
123
127
  #
124
128
  # @return [void]
125
- def page opts={}
129
+ def page(opts = {})
126
130
  if opts.is_a?(Hash)
127
131
  window_number = opts.fetch :window, -1
128
132
  class_name = opts.fetch :class, nil
@@ -154,7 +158,7 @@ module Appium
154
158
  # Gets the JSON source of window number
155
159
  # @param window_number [Integer] the int index of the target window
156
160
  # @return [JSON]
157
- def source_window window_number=0
161
+ def source_window(window_number = 0)
158
162
  # appium 1.0 still returns JSON when getTree() is invoked so this
159
163
  # doesn't need to change to XML. If getTree() is removed then
160
164
  # source_window will need to parse the elements of getTreeForXML()\
@@ -168,7 +172,7 @@ module Appium
168
172
  #
169
173
  # @param window_number [Integer] the int index of the target window
170
174
  # @return [void]
171
- def page_window window_number=0
175
+ def page_window(window_number = 0)
172
176
  get_page source_window window_number
173
177
  nil
174
178
  end
@@ -176,7 +180,7 @@ module Appium
176
180
  # Find by id
177
181
  # @param id [String] the id to search for
178
182
  # @return [Element]
179
- def id id
183
+ def id(id)
180
184
  find_element :id, id
181
185
  end
182
186
 
@@ -184,32 +188,32 @@ module Appium
184
188
  # @return [Array<Integer>]
185
189
  def ios_version
186
190
  ios_version = execute_script 'UIATarget.localTarget().systemVersion()'
187
- ios_version.split('.').map { |e| e.to_i }
191
+ ios_version.split('.').map(&:to_i)
188
192
  end
189
193
 
190
194
  # Get the element of type class_name at matching index.
191
195
  # @param class_name [String] the class name to find
192
196
  # @param index [Integer] the index
193
197
  # @return [Element]
194
- def ele_index class_name, index
195
- raise 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
198
+ def ele_index(class_name, index)
199
+ fail 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
196
200
  elements = tags(class_name)
197
201
 
198
202
  if index == 'last()'
199
203
  result = elements.last
200
204
  else
201
205
  # elements array is 0 indexed
202
- index -= 1
206
+ index -= 1
203
207
  result = elements[index]
204
208
  end
205
209
 
206
- raise _no_such_element if result.nil?
210
+ fail _no_such_element if result.nil?
207
211
  result
208
212
  end
209
213
 
210
214
  # @private
211
- def string_attr_exact class_name, attr, value
212
- %Q(//#{class_name}[@visible="true" and @#{attr}='#{value}'])
215
+ def string_attr_exact(class_name, attr, value)
216
+ %(//#{class_name}[@visible="true" and @#{attr}='#{value}'])
213
217
  end
214
218
 
215
219
  # Find the first element exactly matching class and attribute value.
@@ -218,7 +222,7 @@ module Appium
218
222
  # @param attr [String] the attribute to inspect
219
223
  # @param value [String] the expected value of the attribute
220
224
  # @return [Element]
221
- def find_ele_by_attr class_name, attr, value
225
+ def find_ele_by_attr(class_name, attr, value)
222
226
  @driver.find_element :xpath, string_attr_exact(class_name, attr, value)
223
227
  end
224
228
 
@@ -228,13 +232,13 @@ module Appium
228
232
  # @param attr [String] the attribute to compare
229
233
  # @param value [String] the value of the attribute that the element must have
230
234
  # @return [Array<Element>]
231
- def find_eles_by_attr class_name, attr, value
235
+ def find_eles_by_attr(class_name, attr, value)
232
236
  @driver.find_elements :xpath, string_attr_exact(class_name, attr, value)
233
237
  end
234
238
 
235
239
  # @private
236
- def string_attr_include class_name, attr, value
237
- %Q(//#{class_name}[@visible="true" and contains(translate(@#{attr},'#{value.upcase}', '#{value}'), '#{value}')])
240
+ def string_attr_include(class_name, attr, value)
241
+ %(//#{class_name}[@visible="true" and contains(translate(@#{attr},'#{value.upcase}', '#{value}'), '#{value}')])
238
242
  end
239
243
 
240
244
  # Get the first tag by attribute that exactly matches value.
@@ -243,7 +247,7 @@ module Appium
243
247
  # @param attr [String] the attribute to compare
244
248
  # @param value [String] the value of the attribute that the element must include
245
249
  # @return [Element] the element of type tag who's attribute includes value
246
- def find_ele_by_attr_include class_name, attr, value
250
+ def find_ele_by_attr_include(class_name, attr, value)
247
251
  @driver.find_element :xpath, string_attr_include(class_name, attr, value)
248
252
  end
249
253
 
@@ -253,14 +257,14 @@ module Appium
253
257
  # @param attr [String] the attribute to compare
254
258
  # @param value [String] the value of the attribute that the element must include
255
259
  # @return [Array<Element>] the elements of type tag who's attribute includes value
256
- def find_eles_by_attr_include class_name, attr, value
260
+ def find_eles_by_attr_include(class_name, attr, value)
257
261
  @driver.find_elements :xpath, string_attr_include(class_name, attr, value)
258
262
  end
259
263
 
260
264
  # Get the first tag that matches class_name
261
265
  # @param class_name [String] the tag to match
262
266
  # @return [Element]
263
- def first_ele class_name
267
+ def first_ele(class_name)
264
268
  # XPath index starts at 1
265
269
  ele_index class_name, 1
266
270
  end
@@ -268,7 +272,7 @@ module Appium
268
272
  # Get the last tag that matches class_name
269
273
  # @param class_name [String] the tag to match
270
274
  # @return [Element]
271
- def last_ele class_name
275
+ def last_ele(class_name)
272
276
  ele_index class_name, 'last()'
273
277
  end
274
278
 
@@ -276,22 +280,22 @@ module Appium
276
280
  #
277
281
  # @param class_name [String] the class_name to search for
278
282
  # @return [Element]
279
- def tag class_name
280
- ele_by_json({
281
- typeArray: [class_name],
282
- onlyVisible: true,
283
- })
283
+ def tag(class_name)
284
+ ele_by_json(
285
+ typeArray: [class_name],
286
+ onlyVisible: true
287
+ )
284
288
  end
285
289
 
286
290
  # Returns all visible elements matching class_name
287
291
  #
288
292
  # @param class_name [String] the class_name to search for
289
293
  # @return [Element]
290
- def tags class_name
291
- eles_by_json({
292
- typeArray: [class_name],
293
- onlyVisible: true,
294
- })
294
+ def tags(class_name)
295
+ eles_by_json(
296
+ typeArray: [class_name],
297
+ onlyVisible: true
298
+ )
295
299
  end
296
300
 
297
301
  # @private
@@ -302,11 +306,11 @@ module Appium
302
306
  # @param element [String] the class name for the element
303
307
  # @param value [String] the value to search for
304
308
  # @return [String]
305
- def string_visible_contains element, value
309
+ def string_visible_contains(element, value)
306
310
  contains = {
307
311
  target: value,
308
312
  substring: true,
309
- insensitive: true,
313
+ insensitive: true
310
314
  }
311
315
 
312
316
  {
@@ -314,7 +318,7 @@ module Appium
314
318
  onlyVisible: true,
315
319
  name: contains,
316
320
  label: contains,
317
- value: contains,
321
+ value: contains
318
322
  }
319
323
  end
320
324
 
@@ -322,7 +326,7 @@ module Appium
322
326
  # @param element [String] the class name for the element
323
327
  # @param value [String] the value to search for
324
328
  # @return [Element]
325
- def ele_by_json_visible_contains element, value
329
+ def ele_by_json_visible_contains(element, value)
326
330
  ele_by_json string_visible_contains element, value
327
331
  end
328
332
 
@@ -330,7 +334,7 @@ module Appium
330
334
  # @param element [String] the class name for the element
331
335
  # @param value [String] the value to search for
332
336
  # @return [Array<Element>]
333
- def eles_by_json_visible_contains element, value
337
+ def eles_by_json_visible_contains(element, value)
334
338
  eles_by_json string_visible_contains element, value
335
339
  end
336
340
 
@@ -339,11 +343,11 @@ module Appium
339
343
  # @param element [String] the class name for the element
340
344
  # @param value [String] the value to search for
341
345
  # @return [String]
342
- def string_visible_exact element, value
346
+ def string_visible_exact(element, value)
343
347
  exact = {
344
348
  target: value,
345
349
  substring: false,
346
- insensitive: false,
350
+ insensitive: false
347
351
  }
348
352
 
349
353
  {
@@ -351,7 +355,7 @@ module Appium
351
355
  onlyVisible: true,
352
356
  name: exact,
353
357
  label: exact,
354
- value: exact,
358
+ value: exact
355
359
  }
356
360
  end
357
361
 
@@ -359,7 +363,7 @@ module Appium
359
363
  # @param element [String] the class name for the element
360
364
  # @param value [String] the value to search for
361
365
  # @return [Element]
362
- def ele_by_json_visible_exact element, value
366
+ def ele_by_json_visible_exact(element, value)
363
367
  ele_by_json string_visible_exact element, value
364
368
  end
365
369
 
@@ -367,7 +371,7 @@ module Appium
367
371
  # @param element [String] the class name for the element
368
372
  # @param value [String] the value to search for
369
373
  # @return [Element]
370
- def eles_by_json_visible_exact element, value
374
+ def eles_by_json_visible_exact(element, value)
371
375
  eles_by_json string_visible_exact element, value
372
376
  end
373
377
 
@@ -377,22 +381,22 @@ module Appium
377
381
  # If close key is present then tap it.
378
382
  # @param close_key [String] close key to tap. Default value is 'Done'
379
383
  # @return [void]
380
- def hide_ios_keyboard close_key='Done'
381
- =begin
382
- todo: there are many various ways to hide the keyboard that work in different
383
- app specific circumstances. webview keyboard will require a window.tap for example.
384
-
385
- Find the top left corner of the keyboard and move up 10 pixels (origin.y - 10)
386
- now swipe down until the end of the window - 10 pixels.
387
- -10 to ensure we're not going outside the window bounds.
388
-
389
- Swiping inside the keyboard will not dismiss it.
390
-
391
- If the 'Done' key exists then that should be pressed to dismiss the keyboard
392
- because swiping to dismiss works only if such key doesn't exist.
393
-
394
- Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
395
- =end
384
+ def hide_ios_keyboard(close_key = 'Done')
385
+ #
386
+ # TODO: there are many various ways to hide the keyboard that work in different
387
+ # app specific circumstances. webview keyboard will require a window.tap for example.
388
+ #
389
+ # Find the top left corner of the keyboard and move up 10 pixels (origin.y - 10)
390
+ # now swipe down until the end of the window - 10 pixels.
391
+ # -10 to ensure we're not going outside the window bounds.
392
+ #
393
+ # Swiping inside the keyboard will not dismiss it.
394
+ #
395
+ # If the 'Done' key exists then that should be pressed to dismiss the keyboard
396
+ # because swiping to dismiss works only if such key doesn't exist.
397
+ #
398
+ # Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
399
+ #
396
400
  dismiss_keyboard = (<<-JS).strip
397
401
  if (!au.mainApp().keyboard().isNil()) {
398
402
  var key = au.mainApp().keyboard().buttons()['#{close_key}']
@@ -431,11 +435,11 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
431
435
  #
432
436
  # visible - if true, only visible elements are returned. default true
433
437
  #
434
- def _all_pred opts
438
+ def _all_pred(opts)
435
439
  predicate = opts[:predicate]
436
- raise 'predicate must be provided' unless predicate
440
+ fail 'predicate must be provided' unless predicate
437
441
  visible = opts.fetch :visible, true
438
- %Q($.mainApp().getAllWithPredicate("#{predicate}", #{visible});)
442
+ %($.mainApp().getAllWithPredicate("#{predicate}", #{visible});)
439
443
  end
440
444
 
441
445
  # returns element matching predicate contained in the main app
@@ -444,7 +448,7 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
444
448
  #
445
449
  # visible - if true, only visible elements are returned. default true
446
450
  # @return [Element]
447
- def ele_with_pred opts
451
+ def ele_with_pred(opts)
448
452
  # true = return only visible
449
453
  find_element(:uiautomation, _all_pred(opts))
450
454
  end
@@ -455,7 +459,7 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
455
459
  #
456
460
  # visible - if true, only visible elements are returned. default true
457
461
  # @return [Array<Element>]
458
- def eles_with_pred opts
462
+ def eles_with_pred(opts)
459
463
  find_elements(:uiautomation, _all_pred(opts))
460
464
  end
461
465
 
@@ -465,23 +469,23 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
465
469
  _print_source get_source
466
470
  end
467
471
 
468
- def _validate_object *objects
469
- raise 'objects must be an array' unless objects.is_a? Array
472
+ def _validate_object(*objects)
473
+ fail 'objects must be an array' unless objects.is_a? Array
470
474
  objects.each do |obj|
471
475
  next unless obj # obj may be nil. if so, ignore.
472
476
 
473
477
  valid_keys = [:target, :substring, :insensitive]
474
478
  unknown_keys = obj.keys - valid_keys
475
- raise "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
479
+ fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
476
480
 
477
481
  target = obj[:target]
478
- raise 'target must be a string' unless target.is_a? String
482
+ fail 'target must be a string' unless target.is_a? String
479
483
 
480
484
  substring = obj[:substring]
481
- raise 'substring must be a boolean' unless [true, false].include? substring
485
+ fail 'substring must be a boolean' unless [true, false].include? substring
482
486
 
483
487
  insensitive = obj[:insensitive]
484
- raise 'insensitive must be a boolean' unless [true, false].include? insensitive
488
+ fail 'insensitive must be a boolean' unless [true, false].include? insensitive
485
489
  end
486
490
  end
487
491
 
@@ -513,33 +517,42 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
513
517
  # }
514
518
  # }
515
519
  #
516
- def _by_json opts
520
+ def _by_json(opts)
517
521
  valid_keys = [:typeArray, :onlyFirst, :onlyVisible, :name, :label, :value]
518
522
  unknown_keys = opts.keys - valid_keys
519
- raise "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
523
+ fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
520
524
 
521
- typeArray = opts[:typeArray]
522
- raise 'typeArray must be an array' unless typeArray.is_a? Array
525
+ type_array = opts[:typeArray]
526
+ fail 'typeArray must be an array' unless type_array.is_a? Array
523
527
 
524
- onlyFirst = opts[:onlyFirst]
525
- raise 'onlyFirst must be a boolean' unless [true, false].include? onlyFirst
528
+ only_first = opts[:onlyFirst]
529
+ fail 'onlyFirst must be a boolean' unless [true, false].include? only_first
526
530
 
527
- onlyVisible = opts[:onlyVisible]
528
- raise 'onlyVisible must be a boolean' unless [true, false].include? onlyVisible
531
+ only_visible = opts[:onlyVisible]
532
+ fail 'onlyVisible must be a boolean' unless [true, false].include? only_visible
529
533
 
530
534
  # name/label/value are optional. when searching for class only, then none
531
535
  # will be present.
532
536
  _validate_object opts[:name], opts[:label], opts[:value]
533
537
 
538
+ # note that mainWindow is sometimes nil so it's passed as a param
539
+ # $._elementOrElementsByType will validate that the window isn't nil
534
540
  element_or_elements_by_type = <<-JS
535
541
  (function() {
536
- var opts = #{opts.to_json}
542
+ var opts = #{opts.to_json};
543
+ var result = false;
544
+
545
+ try {
546
+ result = $._elementOrElementsByType($.mainWindow(), opts);
547
+ } catch (e) {
548
+ }
537
549
 
538
- return $.mainWindow()._elementOrElementsByType(opts);
550
+ return result;
539
551
  })();
540
552
  JS
541
553
 
542
- execute_script element_or_elements_by_type
554
+ res = execute_script element_or_elements_by_type
555
+ res ? res : fail(Selenium::Client::CommandError, 'mainWindow is nil')
543
556
  end
544
557
 
545
558
  # example usage:
@@ -553,16 +566,16 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
553
566
  # insensitive: false,
554
567
  # },
555
568
  # })
556
- def eles_by_json opts
569
+ def eles_by_json(opts)
557
570
  opts[:onlyFirst] = false
558
- return _by_json opts
571
+ _by_json opts
559
572
  end
560
573
 
561
574
  # see eles_by_json
562
- def ele_by_json opts
575
+ def ele_by_json(opts)
563
576
  opts[:onlyFirst] = true
564
577
  result = _by_json(opts).first
565
- raise _no_such_element if result.nil?
578
+ fail _no_such_element if result.nil?
566
579
  result
567
580
  end
568
581
 
@@ -573,4 +586,4 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
573
586
  @driver.page_source
574
587
  end
575
588
  end # module Ios
576
- end # module Appium
589
+ end # module Appium