appium_lib 9.0.0 → 9.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +21 -0
  3. data/android_tests/lib/android/specs/android/helper.rb +3 -5
  4. data/android_tests/lib/android/specs/common/command.rb +47 -0
  5. data/android_tests/lib/android/specs/common/helper.rb +8 -8
  6. data/android_tests/lib/android/specs/common/web_context.rb +1 -1
  7. data/android_tests/lib/android/specs/driver.rb +19 -11
  8. data/android_tests/lib/format.rb +3 -3
  9. data/android_tests/lib/run.rb +7 -5
  10. data/android_tests/readme.md +1 -1
  11. data/appium_lib.gemspec +6 -7
  12. data/contributing.md +10 -0
  13. data/docs/android_docs.md +252 -217
  14. data/docs/ios_docs.md +257 -222
  15. data/docs/ios_xcuitest.md +32 -4
  16. data/ios_tests/lib/common.rb +11 -55
  17. data/ios_tests/lib/ios/specs/common/command.rb +44 -0
  18. data/ios_tests/lib/ios/specs/common/helper.rb +8 -8
  19. data/ios_tests/lib/ios/specs/device/device.rb +5 -5
  20. data/ios_tests/lib/ios/specs/driver.rb +34 -15
  21. data/ios_tests/lib/ios/specs/ios/element/textfield.rb +1 -1
  22. data/ios_tests/readme.md +1 -1
  23. data/ios_tests/upload/sauce_storage.rb +10 -8
  24. data/lib/appium_lib/android/element/button.rb +3 -3
  25. data/lib/appium_lib/android/element/text.rb +1 -1
  26. data/lib/appium_lib/android/element/textfield.rb +1 -1
  27. data/lib/appium_lib/android/helper.rb +12 -12
  28. data/lib/appium_lib/android/mobile_methods.rb +1 -3
  29. data/lib/appium_lib/common/command.rb +55 -0
  30. data/lib/appium_lib/common/helper.rb +7 -7
  31. data/lib/appium_lib/common/patch.rb +21 -8
  32. data/lib/appium_lib/common/search_context.rb +10 -0
  33. data/lib/appium_lib/common/version.rb +2 -2
  34. data/lib/appium_lib/common/wait.rb +8 -14
  35. data/lib/appium_lib/device/device.rb +65 -83
  36. data/lib/appium_lib/device/multi_touch.rb +2 -2
  37. data/lib/appium_lib/device/touch_actions.rb +4 -7
  38. data/lib/appium_lib/driver.rb +66 -38
  39. data/lib/appium_lib/ios/element/alert.rb +4 -4
  40. data/lib/appium_lib/ios/element/textfield.rb +3 -3
  41. data/lib/appium_lib/ios/errors.rb +6 -0
  42. data/lib/appium_lib/ios/helper.rb +25 -25
  43. data/lib/appium_lib/ios/mobile_methods.rb +2 -4
  44. data/readme.md +3 -1
  45. data/release_notes.md +13 -0
  46. metadata +23 -12
@@ -26,7 +26,7 @@ module Appium
26
26
  # action.perform #=> to 25% of its size.
27
27
  # ```
28
28
  def pinch(percentage = 25, auto_perform = true)
29
- fail ArgumentError("Can't pinch to greater than screen size.") if percentage > 100
29
+ raise ArgumentError("Can't pinch to greater than screen size.") if percentage > 100
30
30
 
31
31
  p = Float(percentage) / 100
32
32
 
@@ -62,7 +62,7 @@ module Appium
62
62
  # action.perform
63
63
  # ```
64
64
  def zoom(percentage = 200, auto_perform = true)
65
- fail ArgumentError("Can't zoom to smaller then screen size.") if percentage < 100
65
+ raise ArgumentError("Can't zoom to smaller then screen size.") if percentage < 100
66
66
 
67
67
  p = 100 / Float(percentage)
68
68
  i = 1 - p
@@ -8,8 +8,8 @@ module Appium
8
8
  # action = TouchAction.new.press(x: 45, y: 100).wait(5).release
9
9
  # action.perform
10
10
  class TouchAction
11
- ACTIONS = [:move_to, :long_press, :double_tap, :two_finger_tap, :press, :release, :tap, :wait, :perform]
12
- COMPLEX_ACTIONS = [:swipe]
11
+ ACTIONS = [:move_to, :long_press, :double_tap, :two_finger_tap, :press, :release, :tap, :wait, :perform].freeze
12
+ COMPLEX_ACTIONS = [:swipe].freeze
13
13
 
14
14
  class << self
15
15
  COMPLEX_ACTIONS.each do |action|
@@ -174,11 +174,8 @@ module Appium
174
174
  private
175
175
 
176
176
  def chain_method(method, args = nil)
177
- if args
178
- @actions << { action: method, options: args }
179
- else
180
- @actions << { action: method }
181
- end
177
+ action = args ? { action: method, options: args } : { action: method }
178
+ @actions << action
182
179
  self
183
180
  end
184
181
 
@@ -1,7 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'ap'
3
3
  require 'selenium-webdriver'
4
- require 'selenium/client/errors' # used in helper.rb for CommandError
5
4
  require 'nokogiri'
6
5
 
7
6
  # common
@@ -10,11 +9,14 @@ require_relative 'common/wait'
10
9
  require_relative 'common/patch'
11
10
  require_relative 'common/version'
12
11
  require_relative 'common/error'
12
+ require_relative 'common/search_context'
13
+ require_relative 'common/command'
13
14
  require_relative 'common/element/window'
14
15
 
15
16
  # ios
16
17
  require_relative 'ios/helper'
17
18
  require_relative 'ios/patch'
19
+ require_relative 'ios/errors'
18
20
 
19
21
  require_relative 'ios/element/alert'
20
22
  require_relative 'ios/element/button'
@@ -70,11 +72,11 @@ module Appium
70
72
  # @param opts [Hash] file: '/path/to/appium.txt', verbose: true
71
73
  # @return [hash] the symbolized hash with updated :app and :require keys
72
74
  def self.load_settings(opts = {})
73
- fail 'opts must be a hash' unless opts.is_a? Hash
74
- fail 'opts must not be empty' if opts.empty?
75
+ raise 'opts must be a hash' unless opts.is_a? Hash
76
+ raise 'opts must not be empty' if opts.empty?
75
77
 
76
78
  toml = opts[:file]
77
- fail 'Must pass file' unless toml
79
+ raise 'Must pass file' unless toml
78
80
  verbose = opts.fetch :verbose, false
79
81
 
80
82
  Appium::Logger.info "appium settings path: #{toml}" if verbose
@@ -82,12 +84,14 @@ module Appium
82
84
  toml_exists = File.exist? toml
83
85
  Appium::Logger.info "Exists? #{toml_exists}" if verbose
84
86
 
85
- fail "toml doesn't exist #{toml}" unless toml_exists
87
+ raise "toml doesn't exist #{toml}" unless toml_exists
86
88
  require 'tomlrb'
87
89
  Appium::Logger.info "Loading #{toml}" if verbose
88
90
 
89
91
  data = Tomlrb.load_file(toml, symbolize_keys: true)
90
- Appium::Logger.ap_info data unless data.empty? if verbose
92
+ if verbose
93
+ Appium::Logger.ap_info data unless data.empty?
94
+ end
91
95
 
92
96
  if data && data[:caps] && data[:caps][:app] && !data[:caps][:app].empty?
93
97
  data[:caps][:app] = Appium::Driver.absolute_app_path data
@@ -102,6 +106,7 @@ module Appium
102
106
  end
103
107
 
104
108
  class << self
109
+ # rubocop:disable Style/Alias
105
110
  alias_method :load_appium_txt, :load_settings
106
111
  end
107
112
 
@@ -141,7 +146,7 @@ module Appium
141
146
  # based on deep_symbolize_keys & deep_transform_keys from rails
142
147
  # https://github.com/rails/docrails/blob/a3b1105ada3da64acfa3843b164b14b734456a50/activesupport/lib/active_support/core_ext/hash/keys.rb#L84
143
148
  def self.symbolize_keys(hash)
144
- fail 'symbolize_keys requires a hash' unless hash.is_a? Hash
149
+ raise 'symbolize_keys requires a hash' unless hash.is_a? Hash
145
150
  result = {}
146
151
  hash.each do |key, value|
147
152
  key = key.to_sym rescue key # rubocop:disable Style/RescueModifier
@@ -162,7 +167,7 @@ module Appium
162
167
  # that module are promoted on.
163
168
  # otherwise, the array of modules will be used as the promotion target.
164
169
  def self.promote_singleton_appium_methods(modules)
165
- fail 'Driver is nil' if $driver.nil?
170
+ raise 'Driver is nil' if $driver.nil?
166
171
 
167
172
  target_modules = []
168
173
 
@@ -171,12 +176,13 @@ module Appium
171
176
  target_modules << modules.const_get(sub_module)
172
177
  end
173
178
  else
174
- fail 'modules must be a module or an array' unless modules.is_a? Array
179
+ raise 'modules must be a module or an array' unless modules.is_a? Array
175
180
  target_modules = modules
176
181
  end
177
182
 
178
183
  target_modules.each do |const|
179
184
  # noinspection RubyResolve
185
+ # rubocop:disable Style/MultilineIfModifier
180
186
  $driver.public_methods(false).each do |m|
181
187
  const.send(:define_singleton_method, m) do |*args, &block|
182
188
  begin
@@ -187,6 +193,7 @@ module Appium
187
193
  # override unless there's an existing method with matching arity
188
194
  end unless const.respond_to?(m) && const.method(m).arity == $driver.method(m).arity
189
195
  end
196
+ # rubocop:enable Style/MultilineIfModifier
190
197
  end
191
198
  end
192
199
 
@@ -213,7 +220,7 @@ module Appium
213
220
  # Appium.promote_appium_methods Minitest::Spec
214
221
  # ```
215
222
  def self.promote_appium_methods(class_array)
216
- fail 'Driver is nil' if $driver.nil?
223
+ raise 'Driver is nil' if $driver.nil?
217
224
  # Wrap single class into an array
218
225
  class_array = [class_array] unless class_array.class == Array
219
226
  # Promote Appium driver methods to class instance methods.
@@ -239,6 +246,22 @@ module Appium
239
246
  nil # return nil
240
247
  end
241
248
 
249
+ class Driver
250
+ module Capabilities
251
+ # except for browser_name, default capability is equal to ::Selenium::WebDriver::Remote::Capabilities.firefox
252
+ # Because Selenium::WebDriver::Remote::Bridge uses Capabilities.firefox by default
253
+ # https://github.com/SeleniumHQ/selenium/blob/selenium-3.0.1/rb/lib/selenium/webdriver/remote/bridge.rb#L67
254
+ def self.init_caps_for_appium(opts_caps = {})
255
+ default_caps_opts_firefox = {
256
+ javascript_enabled: true,
257
+ takes_screenshot: true,
258
+ css_selectors_enabled: true
259
+ }.merge(opts_caps)
260
+ ::Selenium::WebDriver::Remote::Capabilities.new(default_caps_opts_firefox)
261
+ end
262
+ end
263
+ end
264
+
242
265
  class Driver
243
266
  # attr readers are promoted to global scope. To avoid clobbering, they're
244
267
  # made available via the driver_attributes method
@@ -302,12 +325,12 @@ module Appium
302
325
  def initialize(opts = {})
303
326
  # quit last driver
304
327
  $driver.driver_quit if $driver
305
- fail 'opts must be a hash' unless opts.is_a? Hash
328
+ raise 'opts must be a hash' unless opts.is_a? Hash
306
329
 
307
330
  opts = Appium.symbolize_keys opts
308
331
 
309
- # default to {} to prevent nil.fetch and other nil errors
310
- @caps = opts[:caps] || {}
332
+ @caps = Capabilities.init_caps_for_appium(opts[:caps] || {})
333
+
311
334
  appium_lib_opts = opts[:appium_lib] || {}
312
335
 
313
336
  # appium_lib specific values
@@ -327,7 +350,7 @@ module Appium
327
350
 
328
351
  # Path to the .apk, .app or .app.zip.
329
352
  # The path can be local or remote for Sauce.
330
- if @caps && @caps[:app] && ! @caps[:app].empty?
353
+ if @caps && @caps[:app] && !@caps[:app].empty?
331
354
  @caps[:app] = self.class.absolute_app_path opts
332
355
  end
333
356
 
@@ -351,6 +374,9 @@ module Appium
351
374
  # apply os specific patches
352
375
  patch_webdriver_element
353
376
 
377
+ # for command
378
+ patch_remote_driver_commands
379
+
354
380
  # enable debug patch
355
381
  # !!'constant' == true
356
382
  @appium_debug = appium_lib_opts.fetch :debug, !!defined?(Pry)
@@ -370,17 +396,18 @@ module Appium
370
396
 
371
397
  # Returns a hash of the driver attributes
372
398
  def driver_attributes
373
- attributes = { caps: @caps,
374
- custom_url: @custom_url,
375
- export_session: @export_session,
376
- default_wait: @default_wait,
377
- last_waits: @last_waits,
378
- sauce_username: @sauce_username,
379
- sauce_access_key: @sauce_access_key,
380
- port: @appium_port,
381
- device: @appium_device,
382
- debug: @appium_debug,
383
- listener: @listener
399
+ attributes = {
400
+ caps: @caps,
401
+ custom_url: @custom_url,
402
+ export_session: @export_session,
403
+ default_wait: @default_wait,
404
+ last_waits: @last_waits,
405
+ sauce_username: @sauce_username,
406
+ sauce_access_key: @sauce_access_key,
407
+ port: @appium_port,
408
+ device: @appium_device,
409
+ debug: @appium_debug,
410
+ listener: @listener
384
411
  }
385
412
 
386
413
  # Return duplicates so attributes are immutable
@@ -397,7 +424,7 @@ module Appium
397
424
  # Return true if automationName is 'XCUITest'
398
425
  # @return [Boolean]
399
426
  def automation_name_is_xcuitest?
400
- !@automation_name.nil? && @automation_name.downcase == 'xcuitest'
427
+ !@automation_name.nil? && 'xcuitest'.casecmp(@automation_name).zero?
401
428
  end
402
429
 
403
430
  # Return true if the target Appium server is over REQUIRED_VERSION_XCUITEST.
@@ -405,7 +432,7 @@ module Appium
405
432
  # @return [Boolean]
406
433
  def check_server_version_xcuitest
407
434
  if automation_name_is_xcuitest? && (@appium_server_version['build']['version'] <= REQUIRED_VERSION_XCUITEST)
408
- fail Appium::Error::NotSupportedAppiumServer, "XCUITest requires over Appium #{REQUIRED_VERSION_XCUITEST}"
435
+ raise Appium::Error::NotSupportedAppiumServer, "XCUITest requires over Appium #{REQUIRED_VERSION_XCUITEST}"
409
436
  end
410
437
  true
411
438
  end
@@ -435,33 +462,33 @@ module Appium
435
462
  #
436
463
  # @return [String] APP_PATH as an absolute path
437
464
  def self.absolute_app_path(opts)
438
- fail 'opts must be a hash' unless opts.is_a? Hash
465
+ raise 'opts must be a hash' unless opts.is_a? Hash
439
466
  caps = opts[:caps] || {}
440
467
  appium_lib_opts = opts[:appium_lib] || {}
441
468
  server_url = appium_lib_opts.fetch :server_url, false
442
469
 
443
470
  app_path = caps[:app]
444
- fail 'absolute_app_path invoked and app is not set!' if app_path.nil? || app_path.empty?
471
+ raise 'absolute_app_path invoked and app is not set!' if app_path.nil? || app_path.empty?
445
472
  # may be absolute path to file on remote server.
446
473
  # if the file is on the remote server then we can't check if it exists
447
474
  return app_path if server_url
448
475
  # Sauce storage API. http://saucelabs.com/docs/rest#storage
449
476
  return app_path if app_path.start_with? 'sauce-storage:'
450
- return app_path if app_path.match(/^http/) # public URL for Sauce
451
- if app_path.match(/^(\/|[a-zA-Z]:)/) # absolute file path
477
+ return app_path if app_path =~ /^http/ # public URL for Sauce
478
+ if app_path =~ /^(\/|[a-zA-Z]:)/ # absolute file path
452
479
  app_path = File.expand_path app_path unless File.exist? app_path
453
- fail "App doesn't exist. #{app_path}" unless File.exist? app_path
480
+ raise "App doesn't exist. #{app_path}" unless File.exist? app_path
454
481
  return app_path
455
482
  end
456
483
 
457
484
  # if it doesn't contain a slash then it's a bundle id
458
- return app_path unless app_path.match(/[\/\\]/)
485
+ return app_path unless app_path =~ /[\/\\]/
459
486
 
460
487
  # relative path that must be expanded.
461
488
  # absolute_app_path is called from load_settings
462
489
  # and the txt file path is the base of the app path in that case.
463
490
  app_path = File.expand_path app_path
464
- fail "App doesn't exist #{app_path}" unless File.exist? app_path
491
+ raise "App doesn't exist #{app_path}" unless File.exist? app_path
465
492
  app_path
466
493
  end
467
494
 
@@ -498,8 +525,9 @@ module Appium
498
525
  # @return [void]
499
526
  def driver_quit
500
527
  # rescue NoSuchDriverError or nil driver
501
- # rubocop:disable Style/RescueModifier
502
- @driver.quit rescue nil
528
+ @driver.quit
529
+ rescue
530
+ nil
503
531
  end
504
532
 
505
533
  # Creates a new global driver and quits the old one if it exists.
@@ -621,7 +649,7 @@ module Appium
621
649
  # @param args [*args] the args to use
622
650
  # @return [Array<Element>] Array is empty when no elements are found.
623
651
  def find_elements(*args)
624
- @driver.find_elements(*args)
652
+ @driver.find_elements_with_appium(*args)
625
653
  end
626
654
 
627
655
  # Calls @driver.find_elements
@@ -629,7 +657,7 @@ module Appium
629
657
  # @param args [*args] the args to use
630
658
  # @return [Element]
631
659
  def find_element(*args)
632
- @driver.find_element(*args)
660
+ @driver.find_element_with_appium(*args)
633
661
  end
634
662
 
635
663
  # Calls @driver.set_location
@@ -4,16 +4,16 @@ module Appium
4
4
  # @return [void]
5
5
  def alert_accept
6
6
  # @driver.switch_to.alert.accept
7
- # ".switch_to.alert" calls getAlertText so use bridge directly
8
- driver.send(:bridge).acceptAlert
7
+ # ".switch_to.alert" calls alert_text so use bridge directly
8
+ driver.send(:bridge).accept_alert
9
9
  end
10
10
 
11
11
  # Dismiss the alert.
12
12
  # @return [void]
13
13
  def alert_dismiss
14
14
  # @driver.switch_to.alert.dismiss
15
- # ".switch_to.alert" calls getAlertText so use bridge directly
16
- driver.send(:bridge).dismissAlert
15
+ # ".switch_to.alert" calls alert_text so use bridge directly
16
+ driver.send(:bridge).dismiss_alert
17
17
  end
18
18
  end # module Ios
19
19
  end # module Appium
@@ -65,14 +65,14 @@ module Appium
65
65
  def textfield(value)
66
66
  if value.is_a? Numeric
67
67
  index = value
68
- fail "#{index} is not a valid index. Must be >= 1" if index <= 0
68
+ raise "#{index} is not a valid index. Must be >= 1" if index <= 0
69
69
  index -= 1 # eles_by_json and _textfields_with_xpath is 0 indexed.
70
70
  result = if automation_name_is_xcuitest?
71
71
  _textfields_with_xpath[index]
72
72
  else
73
73
  eles_by_json(_textfield_visible)[index]
74
74
  end
75
- fail _no_such_element if result.nil?
75
+ raise _no_such_element if result.nil?
76
76
  return result
77
77
 
78
78
  end
@@ -116,7 +116,7 @@ module Appium
116
116
  else
117
117
  eles_by_json(_textfield_visible).last
118
118
  end
119
- fail _no_such_element if result.nil?
119
+ raise _no_such_element if result.nil?
120
120
  result
121
121
  end
122
122
 
@@ -0,0 +1,6 @@
1
+ module Appium
2
+ module Ios
3
+ class CommandError < RuntimeError
4
+ end
5
+ end
6
+ end
@@ -14,21 +14,21 @@ module Appium
14
14
 
15
15
  def _print_attr(type, name, label, value, hint)
16
16
  if name == label && name == value
17
- puts "#{type}" if name || label || value || hint
17
+ puts type.to_s if name || label || value || hint
18
18
  puts " name, label, value: #{name}" if name
19
19
  puts " hint: #{hint}" if hint
20
20
  elsif name == label
21
- puts "#{type}" if name || label || value || hint
21
+ puts type.to_s if name || label || value || hint
22
22
  puts " name, label: #{name}" if name
23
23
  puts " value: #{value}" if value
24
24
  puts " hint: #{hint}" if hint
25
25
  elsif name == value
26
- puts "#{type}" if name || label || value || hint
26
+ puts type.to_s if name || label || value || hint
27
27
  puts " name, value: #{name}" if name
28
28
  puts " label: #{label}" if label
29
29
  puts " hint: #{hint}" if hint
30
30
  else
31
- puts "#{type}" if name || label || value || hint
31
+ puts type.to_s if name || label || value || hint
32
32
  puts " name: #{name}" if name
33
33
  puts " label: #{label}" if label
34
34
  puts " value: #{value}" if value
@@ -91,24 +91,24 @@ module Appium
91
91
  # rubocop:disable Metrics/BlockNesting
92
92
 
93
93
  # if class_name is set, mark non-matches as invisible
94
- visible = (type.downcase.include?(class_name)).to_s if class_name
94
+ visible = (type.downcase.include? class_namet).to_s if class_name
95
95
  if visible && visible == 'true'
96
96
  if name == label && name == value
97
- puts "#{type}" if name || label || value || hint
97
+ puts type.to_s if name || label || value || hint
98
98
  puts " name, label, value: #{name}" if name
99
99
  puts " hint: #{hint}" if hint
100
100
  elsif name == label
101
- puts "#{type}" if name || label || value || hint
101
+ puts type.to_s if name || label || value || hint
102
102
  puts " name, label: #{name}" if name
103
103
  puts " value: #{value}" if value
104
104
  puts " hint: #{hint}" if hint
105
105
  elsif name == value
106
- puts "#{type}" if name || label || value || hint
106
+ puts type.to_s if name || label || value || hint
107
107
  puts " name, value: #{name}" if name
108
108
  puts " label: #{label}" if label
109
109
  puts " hint: #{hint}" if hint
110
110
  else
111
- puts "#{type}" if name || label || value || hint
111
+ puts type.to_s if name || label || value || hint
112
112
  puts " name: #{name}" if name
113
113
  puts " label: #{label}" if label
114
114
  puts " value: #{value}" if value
@@ -236,7 +236,7 @@ module Appium
236
236
  # @param index [Integer] the index
237
237
  # @return [Element]
238
238
  def ele_index(class_name, index)
239
- fail 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
239
+ raise 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
240
240
  elements = tags(class_name)
241
241
 
242
242
  if index == 'last()'
@@ -247,7 +247,7 @@ module Appium
247
247
  result = elements[index]
248
248
  end
249
249
 
250
- fail _no_such_element if result.nil?
250
+ raise _no_such_element if result.nil?
251
251
  result
252
252
  end
253
253
 
@@ -334,7 +334,7 @@ module Appium
334
334
  def last_ele(class_name)
335
335
  if automation_name_is_xcuitest?
336
336
  result = @driver.find_elements :xpath, "(//#{class_name})"
337
- fail _no_such_element if result.empty?
337
+ raise _no_such_element if result.empty?
338
338
  result.last
339
339
  else
340
340
  ele_index class_name, 'last()'
@@ -469,7 +469,7 @@ module Appium
469
469
  #
470
470
  # Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
471
471
  #
472
- dismiss_keyboard = (<<-JS).strip
472
+ dismiss_keyboard = <<-JS.strip
473
473
  if (!au.mainApp().keyboard().isNil()) {
474
474
  var key = au.mainApp().keyboard().buttons()['#{close_key}']
475
475
  if (key.isNil()) {
@@ -509,7 +509,7 @@ module Appium
509
509
  #
510
510
  def _all_pred(opts)
511
511
  predicate = opts[:predicate]
512
- fail 'predicate must be provided' unless predicate
512
+ raise 'predicate must be provided' unless predicate
513
513
  visible = opts.fetch :visible, true
514
514
  %($.mainApp().getAllWithPredicate("#{predicate}", #{visible});)
515
515
  end
@@ -542,22 +542,22 @@ module Appium
542
542
  end
543
543
 
544
544
  def _validate_object(*objects)
545
- fail 'objects must be an array' unless objects.is_a? Array
545
+ raise 'objects must be an array' unless objects.is_a? Array
546
546
  objects.each do |obj|
547
547
  next unless obj # obj may be nil. if so, ignore.
548
548
 
549
549
  valid_keys = [:target, :substring, :insensitive]
550
550
  unknown_keys = obj.keys - valid_keys
551
- fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
551
+ raise "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
552
552
 
553
553
  target = obj[:target]
554
- fail 'target must be a string' unless target.is_a? String
554
+ raise 'target must be a string' unless target.is_a? String
555
555
 
556
556
  substring = obj[:substring]
557
- fail 'substring must be a boolean' unless [true, false].include? substring
557
+ raise 'substring must be a boolean' unless [true, false].include? substring
558
558
 
559
559
  insensitive = obj[:insensitive]
560
- fail 'insensitive must be a boolean' unless [true, false].include? insensitive
560
+ raise 'insensitive must be a boolean' unless [true, false].include? insensitive
561
561
  end
562
562
  end
563
563
 
@@ -593,16 +593,16 @@ module Appium
593
593
  def _by_json(opts)
594
594
  valid_keys = [:typeArray, :onlyFirst, :onlyVisible, :name, :label, :value]
595
595
  unknown_keys = opts.keys - valid_keys
596
- fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
596
+ raise "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
597
597
 
598
598
  type_array = opts[:typeArray]
599
- fail 'typeArray must be an array' unless type_array.is_a? Array
599
+ raise 'typeArray must be an array' unless type_array.is_a? Array
600
600
 
601
601
  only_first = opts[:onlyFirst]
602
- fail 'onlyFirst must be a boolean' unless [true, false].include? only_first
602
+ raise 'onlyFirst must be a boolean' unless [true, false].include? only_first
603
603
 
604
604
  only_visible = opts[:onlyVisible]
605
- fail 'onlyVisible must be a boolean' unless [true, false].include? only_visible
605
+ raise 'onlyVisible must be a boolean' unless [true, false].include? only_visible
606
606
 
607
607
  # name/label/value are optional. when searching for class only, then none
608
608
  # will be present.
@@ -625,7 +625,7 @@ module Appium
625
625
  JS
626
626
 
627
627
  res = execute_script element_or_elements_by_type
628
- res ? res : fail(Selenium::Client::CommandError, 'mainWindow is nil')
628
+ res ? res : raise(Appium::Ios::CommandError, 'mainWindow is nil')
629
629
  end
630
630
 
631
631
  # For Appium(automation name), not XCUITest
@@ -649,7 +649,7 @@ module Appium
649
649
  def ele_by_json(opts)
650
650
  opts[:onlyFirst] = true
651
651
  result = _by_json(opts).first
652
- fail _no_such_element if result.nil?
652
+ raise _no_such_element if result.nil?
653
653
  result
654
654
  end
655
655