appium_lib 6.0.0 → 7.0.0

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