appium_lib 11.0.0 → 12.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.azure-pipelines.yml +18 -0
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/rubocop.yml +1 -1
- data/.rubocop.yml +106 -2
- data/CHANGELOG.md +9 -6
- data/appium_lib.gemspec +5 -5
- data/docs/android_docs.md +209 -209
- data/docs/ios_docs.md +247 -247
- data/lib/appium_lib/android/common/helper.rb +4 -4
- data/lib/appium_lib/android/element/button.rb +2 -2
- data/lib/appium_lib/android/element/generic.rb +8 -12
- data/lib/appium_lib/android/espresso/element/generic.rb +20 -24
- data/lib/appium_lib/android/uiautomator2/element/button.rb +2 -2
- data/lib/appium_lib/appium.rb +32 -32
- data/lib/appium_lib/common/helper.rb +7 -5
- data/lib/appium_lib/common/wait.rb +3 -4
- data/lib/appium_lib/driver.rb +9 -46
- data/lib/appium_lib/ios/common/helper.rb +2 -1
- data/lib/appium_lib/ios/xcuitest/command/gestures.rb +14 -14
- data/lib/appium_lib/ios/xcuitest/command/multi_app_handler.rb +6 -12
- data/lib/appium_lib/ios/xcuitest/helper.rb +1 -1
- data/lib/appium_lib/ios/xcuitest.rb +0 -1
- data/lib/appium_lib/version.rb +2 -2
- data/readme.md +4 -9
- data/release_notes.md +18 -0
- metadata +29 -21
@@ -27,7 +27,7 @@ module Appium
|
|
27
27
|
@filter = value.to_s.downcase
|
28
28
|
end
|
29
29
|
|
30
|
-
def initialize
|
30
|
+
def initialize # rubocop:disable Lint/MissingSuper
|
31
31
|
reset
|
32
32
|
@filter = false
|
33
33
|
end
|
@@ -217,7 +217,7 @@ module Appium
|
|
217
217
|
# [^\/]+ - type is made up of at least one non-/ characters
|
218
218
|
# \\/ - / ends the type and starts the name
|
219
219
|
# [\S]+$ - the name contains at least one non-space character and then the line is ended
|
220
|
-
resource_id = /^[a-zA-Z_][a-zA-Z0-9
|
220
|
+
resource_id = /^[a-zA-Z_][a-zA-Z0-9._]*:[^\/]+\/\S+$/
|
221
221
|
string.match(resource_id) ? on_match : ''
|
222
222
|
end
|
223
223
|
|
@@ -234,11 +234,11 @@ module Appium
|
|
234
234
|
|
235
235
|
if class_name == '*'
|
236
236
|
return "//*[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}')" \
|
237
|
-
|
237
|
+
" or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
|
238
238
|
end
|
239
239
|
|
240
240
|
"//#{class_name}[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}')" \
|
241
|
-
|
241
|
+
" or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
|
242
242
|
end
|
243
243
|
|
244
244
|
# Returns a string that matches the first element that contains value
|
@@ -98,10 +98,10 @@ module Appium
|
|
98
98
|
|
99
99
|
if button_index && image_button_index
|
100
100
|
"new UiSelector().className(#{BUTTON}).instance(#{button_index});" \
|
101
|
-
|
101
|
+
"new UiSelector().className(#{IMAGE_BUTTON}).instance(#{image_button_index});"
|
102
102
|
else
|
103
103
|
"new UiSelector().className(#{BUTTON});" \
|
104
|
-
|
104
|
+
"new UiSelector().className(#{IMAGE_BUTTON});"
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
@@ -56,12 +56,10 @@ module Appium
|
|
56
56
|
rid = resource_id(text, "new UiSelector().resourceId(#{text})")
|
57
57
|
args = rid.empty? ? ["new UiSelector().textContains(#{text})", "new UiSelector().descriptionContains(#{text})"] : [rid]
|
58
58
|
args.each_with_index do |arg, index|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
raise e if index == args.size - 1
|
64
|
-
end
|
59
|
+
elem = find_element :uiautomator, scroll_uiselector(arg, scrollable_index)
|
60
|
+
return elem
|
61
|
+
rescue StandardError => e
|
62
|
+
raise e if index == args.size - 1
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
@@ -74,12 +72,10 @@ module Appium
|
|
74
72
|
rid = resource_id(text, "new UiSelector().resourceId(#{text})")
|
75
73
|
args = rid.empty? ? ["new UiSelector().text(#{text})", "new UiSelector().description(#{text})"] : [rid]
|
76
74
|
args.each_with_index do |arg, index|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
raise e if index == args.size - 1
|
82
|
-
end
|
75
|
+
elem = find_element :uiautomator, scroll_uiselector(arg, scrollable_index)
|
76
|
+
return elem
|
77
|
+
rescue StandardError => e
|
78
|
+
raise e if index == args.size - 1
|
83
79
|
end
|
84
80
|
end
|
85
81
|
end # module Android
|
@@ -25,19 +25,17 @@ module Appium
|
|
25
25
|
w_s = window_rect
|
26
26
|
|
27
27
|
(1..30).each do |_count|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
sleep 1 # we must wait finish scrolling
|
28
|
+
action
|
29
|
+
.move_to_location(w_s.width / 2, (w_s.height * 2) / 5) # pointer based magic number
|
30
|
+
.pointer_down(:left)
|
31
|
+
.move_to_location(0, w_s.height / 5)
|
32
|
+
.release
|
33
|
+
.perform
|
34
|
+
sleep 1 # we must wait finish scrolling
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
36
|
+
return text(text)
|
37
|
+
rescue StandardError => e
|
38
|
+
err = e
|
41
39
|
end
|
42
40
|
|
43
41
|
raise err
|
@@ -52,19 +50,17 @@ module Appium
|
|
52
50
|
w_s = window_rect
|
53
51
|
|
54
52
|
(1..30).each do |_count|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
sleep 1 # we must wait finish scrolling
|
53
|
+
action
|
54
|
+
.move_to_location(w_s.width / 2, (w_s.height * 2) / 5) # pointer based magic number
|
55
|
+
.pointer_down(:left)
|
56
|
+
.move_to_location(0, w_s.height / 5)
|
57
|
+
.release
|
58
|
+
.perform
|
59
|
+
sleep 1 # we must wait finish scrolling
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
61
|
+
return text_exact(text)
|
62
|
+
rescue StandardError => e
|
63
|
+
err = e
|
68
64
|
end
|
69
65
|
|
70
66
|
raise err
|
@@ -101,10 +101,10 @@ module Appium
|
|
101
101
|
|
102
102
|
if button_index && image_button_index
|
103
103
|
"new UiSelector().className(#{::Appium::Android::Button}).instance(#{button_index});" \
|
104
|
-
|
104
|
+
"new UiSelector().className(#{::Appium::Android::ImageButton}).instance(#{image_button_index});"
|
105
105
|
else
|
106
106
|
"new UiSelector().className(#{::Appium::Android::Button});" \
|
107
|
-
|
107
|
+
"new UiSelector().className(#{::Appium::Android::ImageButton});"
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
data/lib/appium_lib/appium.rb
CHANGED
@@ -77,9 +77,8 @@ module Appium
|
|
77
77
|
Appium::Logger.info "Loading #{toml}" if verbose
|
78
78
|
|
79
79
|
data = Tomlrb.load_file(toml, symbolize_keys: true)
|
80
|
-
|
81
|
-
|
82
|
-
end
|
80
|
+
|
81
|
+
Appium::Logger.info data if verbose && !data.empty?
|
83
82
|
|
84
83
|
if data && data[:caps] && data[:caps][:app] && !data[:caps][:app].empty?
|
85
84
|
data[:caps][:app] = Appium::Driver.absolute_app_path data
|
@@ -157,18 +156,16 @@ module Appium
|
|
157
156
|
|
158
157
|
target_modules.each do |const|
|
159
158
|
# noinspection RubyResolve
|
160
|
-
# rubocop:disable Style/MultilineIfModifier
|
161
159
|
driver.public_methods(false).each do |m|
|
160
|
+
# override unless there's an existing method with matching arity
|
161
|
+
next if const.respond_to?(m) && const.method(m).arity == driver.method(m).arity
|
162
|
+
|
162
163
|
const.send(:define_singleton_method, m) do |*args, &block|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
end
|
168
|
-
# override unless there's an existing method with matching arity
|
169
|
-
end unless const.respond_to?(m) && const.method(m).arity == driver.method(m).arity
|
164
|
+
super(*args, &block) # promote.rb
|
165
|
+
rescue NoMethodError, ArgumentError
|
166
|
+
driver.send m, *args, &block if driver.respond_to?(m)
|
167
|
+
end
|
170
168
|
end
|
171
|
-
# rubocop:enable Style/MultilineIfModifier
|
172
169
|
end
|
173
170
|
end
|
174
171
|
|
@@ -200,29 +197,32 @@ module Appium
|
|
200
197
|
raise 'Driver is nil' if driver.nil?
|
201
198
|
|
202
199
|
# Wrap single class into an array
|
203
|
-
class_array = [class_array] unless class_array.
|
200
|
+
class_array = [class_array] unless class_array.instance_of? Array
|
204
201
|
# Promote Appium driver methods to class instance methods.
|
205
202
|
class_array.each do |klass|
|
206
|
-
driver.public_methods(false).each do |
|
203
|
+
driver.public_methods(false).each do |method|
|
207
204
|
klass.class_eval do
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
205
|
+
if method_defined? method
|
206
|
+
::Appium::Logger.warn "'#{method}' is already defined. Skipping to override it."
|
207
|
+
next
|
208
|
+
end
|
209
|
+
|
210
|
+
define_method method do |*args, &block|
|
211
|
+
# Prefer existing method.
|
212
|
+
# super will invoke method missing on driver
|
213
|
+
super(*args, &block)
|
214
|
+
|
215
|
+
# minitest also defines a name method,
|
216
|
+
# so rescue argument error
|
217
|
+
# and call the name method on $driver
|
218
|
+
rescue NoMethodError, ArgumentError
|
219
|
+
if args.size == 1 && args.first.is_a?(Hash)
|
220
|
+
# To prevent warnings by keyword arguments (for Ruby 2.7 and 3)
|
221
|
+
driver.send method, **args.first, &block if driver.respond_to?(method)
|
222
|
+
else
|
223
|
+
::Appium::Logger.warn "Should fix this '#{args}' for Ruby 2.7 (and 3)" if args.first.is_a?(Hash)
|
224
|
+
|
225
|
+
driver.send method, *args, &block if driver.respond_to?(method)
|
226
226
|
end
|
227
227
|
end
|
228
228
|
end
|
@@ -29,7 +29,8 @@ module Appium
|
|
29
29
|
# Return yield and ignore any exceptions.
|
30
30
|
def ignore
|
31
31
|
yield
|
32
|
-
rescue Exception # rubocop:disable Lint/
|
32
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
33
|
+
# Ignored
|
33
34
|
end
|
34
35
|
|
35
36
|
# Navigate back.
|
@@ -73,7 +74,7 @@ module Appium
|
|
73
74
|
class CountElements < Nokogiri::XML::SAX::Document
|
74
75
|
attr_reader :result
|
75
76
|
|
76
|
-
def initialize(platform)
|
77
|
+
def initialize(platform) # rubocop:disable Lint/MissingSuper
|
77
78
|
reset
|
78
79
|
@platform = platform
|
79
80
|
end
|
@@ -213,7 +214,7 @@ module Appium
|
|
213
214
|
@filter = value.to_s.downcase
|
214
215
|
end
|
215
216
|
|
216
|
-
def initialize
|
217
|
+
def initialize # rubocop:disable Lint/MissingSuper
|
217
218
|
reset
|
218
219
|
@filter = false
|
219
220
|
end
|
@@ -232,8 +233,9 @@ module Appium
|
|
232
233
|
"#{string} #{attr[0]}: #{attr1}\n"
|
233
234
|
end
|
234
235
|
|
235
|
-
r
|
236
|
-
|
236
|
+
return r if attr_string.nil? || attr_string.empty?
|
237
|
+
|
238
|
+
"#{r}\n#{name}\n#{attr_string}"
|
237
239
|
end
|
238
240
|
end
|
239
241
|
|
@@ -42,10 +42,10 @@ module Appium
|
|
42
42
|
# wait_true(20) { button_exact('Back') }.click
|
43
43
|
#
|
44
44
|
def wait_true(opts = {})
|
45
|
-
opts =
|
45
|
+
opts = { timeout: opts } if opts.is_a? Numeric
|
46
46
|
|
47
47
|
if opts.is_a? Hash
|
48
|
-
opts.empty? ? @core.wait_true { yield } : @core.wait_true(opts) { yield }
|
48
|
+
opts.empty? ? @core.wait_true { yield } : @core.wait_true(**opts) { yield }
|
49
49
|
else
|
50
50
|
::Appium::Logger.warn('Arguments should be Hash like {timeout: 100}')
|
51
51
|
end
|
@@ -71,8 +71,7 @@ module Appium
|
|
71
71
|
# wait(20) { button_exact('Back') }.click
|
72
72
|
#
|
73
73
|
def wait(opts = {})
|
74
|
-
opts =
|
75
|
-
|
74
|
+
opts = { timeout: opts } if opts.is_a? Numeric
|
76
75
|
if opts.is_a? Hash
|
77
76
|
opts.empty? ? @core.wait { yield } : @core.wait(**opts) { yield }
|
78
77
|
else
|
data/lib/appium_lib/driver.rb
CHANGED
@@ -151,18 +151,10 @@ module Appium
|
|
151
151
|
# @param opts [Object] A hash containing various options.
|
152
152
|
# @param global_driver [Bool] A bool require global driver before initialize.
|
153
153
|
# @return [Driver]
|
154
|
-
def initialize(opts = {}, global_driver =
|
155
|
-
# TODO: set `global_driver = false` by default in the future.
|
154
|
+
def initialize(opts = {}, global_driver = false)
|
156
155
|
# Capybara can't put `global_driver` as the 2nd argument.
|
157
156
|
global_driver = opts.delete :global_driver if global_driver.nil?
|
158
157
|
|
159
|
-
if global_driver.nil?
|
160
|
-
warn '[DEPRECATION] Appium::Driver.new(opts) will not generate global driver by default.' \
|
161
|
-
'If you would like to generate the global driver dy default, ' \
|
162
|
-
'please initialise driver with Appium::Driver.new(opts, true)'
|
163
|
-
global_driver = true # if global_driver is nil, then global_driver must be default value.
|
164
|
-
end
|
165
|
-
|
166
158
|
$driver&.driver_quit if global_driver
|
167
159
|
|
168
160
|
raise 'opts must be a hash' unless opts.is_a? Hash
|
@@ -276,7 +268,6 @@ module Appium
|
|
276
268
|
|
277
269
|
# Returns a hash of the driver attributes
|
278
270
|
def driver_attributes
|
279
|
-
# rubocop:disable Layout/AlignHash
|
280
271
|
{
|
281
272
|
caps: @core.caps,
|
282
273
|
automation_name: @core.automation_name,
|
@@ -294,7 +285,6 @@ module Appium
|
|
294
285
|
wait_timeout: @core.wait_timeout,
|
295
286
|
wait_interval: @core.wait_interval
|
296
287
|
}
|
297
|
-
# rubocop:enable Layout/AlignHash
|
298
288
|
end
|
299
289
|
|
300
290
|
def device_is_android?
|
@@ -327,27 +317,7 @@ module Appium
|
|
327
317
|
!@core.automation_name.nil? && @core.automation_name == :xcuitest
|
328
318
|
end
|
329
319
|
|
330
|
-
#
|
331
|
-
#
|
332
|
-
# @return [:oss | :w3c]
|
333
|
-
#
|
334
|
-
# @example
|
335
|
-
#
|
336
|
-
# if dialect == :w3c
|
337
|
-
# driver.action
|
338
|
-
# .move_to_location(500, 500).pointer_down(:left)
|
339
|
-
# .move_to_location(0, 700)
|
340
|
-
# .release.perform
|
341
|
-
# else
|
342
|
-
# action = TouchAction.new(driver).press(x: 500, y: 500).move_to(500, 700).release
|
343
|
-
# action.perform
|
344
|
-
# end
|
345
|
-
#
|
346
|
-
def dialect
|
347
|
-
@driver.dialect
|
348
|
-
end
|
349
|
-
|
350
|
-
# An entry point to chain W3C actions. Returns `TouchAction.new` if it works as MJSONWP instead of W3C action.
|
320
|
+
# An entry point to chain W3C actions
|
351
321
|
# Read https://www.rubydoc.info/github/appium/ruby_lib_core/Appium/Core/Base/Bridge/W3C#action-instance_method
|
352
322
|
#
|
353
323
|
# @return [TouchAction|Selenium::WebDriver::PointerActions]
|
@@ -358,12 +328,7 @@ module Appium
|
|
358
328
|
# action.click(element).perform # The `click` is a part of `PointerActions`
|
359
329
|
#
|
360
330
|
def action
|
361
|
-
|
362
|
-
::Appium::Logger.info('Calls TouchAction instead of W3C actions for MJSONWP module')
|
363
|
-
TouchAction.new($driver || @driver)
|
364
|
-
else
|
365
|
-
@driver.action
|
366
|
-
end
|
331
|
+
@driver.action
|
367
332
|
end
|
368
333
|
|
369
334
|
# Returns the server's version info
|
@@ -425,14 +390,12 @@ module Appium
|
|
425
390
|
return app_path if app_path =~ URI::DEFAULT_PARSER.make_regexp # public URL for Sauce
|
426
391
|
|
427
392
|
absolute_app_path = File.expand_path app_path
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
app_path
|
393
|
+
if File.exist? absolute_app_path
|
394
|
+
absolute_app_path
|
395
|
+
else
|
396
|
+
::Appium::Logger.info("Use #{app_path}")
|
397
|
+
app_path
|
398
|
+
end
|
436
399
|
end
|
437
400
|
|
438
401
|
# Get the server url
|
@@ -49,6 +49,7 @@ module Appium
|
|
49
49
|
puts " visible: #{visible}" if visible
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
52
53
|
# iOS only. On Android uiautomator always returns an empty string for EditText password.
|
53
54
|
#
|
54
55
|
# Password character returned from value of UIASecureTextField
|
@@ -470,7 +471,7 @@ module Appium
|
|
470
471
|
# will be present.
|
471
472
|
_validate_object opts[:name], opts[:label], opts[:value]
|
472
473
|
|
473
|
-
#
|
474
|
+
# NOTE: that mainWindow is sometimes nil so it's passed as a param
|
474
475
|
# $._elementOrElementsByType will validate that the window isn't nil
|
475
476
|
element_or_elements_by_type = <<-JS
|
476
477
|
(function() {
|
@@ -24,7 +24,7 @@ module Appium
|
|
24
24
|
# ```
|
25
25
|
def swipe(direction:, element: nil)
|
26
26
|
args = { direction: direction }
|
27
|
-
args[:element] = element.
|
27
|
+
args[:element] = element.id if element
|
28
28
|
|
29
29
|
@driver.execute_script 'mobile: swipe', args
|
30
30
|
end
|
@@ -47,7 +47,7 @@ module Appium
|
|
47
47
|
return 'Set "up", "down", "left" or "right" for :direction' unless %w(up down left right).include?(direction)
|
48
48
|
|
49
49
|
args = { direction: direction }
|
50
|
-
args[:element] = element.
|
50
|
+
args[:element] = element.id if element
|
51
51
|
args[:distance] = distance if distance
|
52
52
|
args[:name] = name if name
|
53
53
|
args[:toVisible] = to_visible if to_visible
|
@@ -66,7 +66,7 @@ module Appium
|
|
66
66
|
# ```
|
67
67
|
def pinch(scale:, velocity: 1.0, element: nil)
|
68
68
|
args = { scale: scale, velocity: velocity }
|
69
|
-
args[:element] = element.
|
69
|
+
args[:element] = element.id if element
|
70
70
|
|
71
71
|
@driver.execute_script 'mobile: pinch', args
|
72
72
|
end
|
@@ -79,10 +79,10 @@ module Appium
|
|
79
79
|
# double_tap x: 100, y: 100
|
80
80
|
# double_tap element: find_element(:accessibility_id, "some item")
|
81
81
|
# ```
|
82
|
-
def double_tap(x: nil, y: nil, element: nil)
|
82
|
+
def double_tap(x: nil, y: nil, element: nil)
|
83
83
|
return 'Set x, y or element' if (x.nil? || y.nil?) && element.nil?
|
84
84
|
|
85
|
-
args = element.nil? ? { x: x, y: y } : { element: element.
|
85
|
+
args = element.nil? ? { x: x, y: y } : { element: element.id }
|
86
86
|
@driver.execute_script 'mobile: doubleTap', args
|
87
87
|
end
|
88
88
|
|
@@ -96,10 +96,10 @@ module Appium
|
|
96
96
|
# touch_and_hold x: 100, y: 100, duration: 2.0
|
97
97
|
# touch_and_hold element: find_element(:accessibility_id, "some item")
|
98
98
|
# ```
|
99
|
-
def touch_and_hold(x: nil, y: nil, element: nil, duration: 1.0)
|
99
|
+
def touch_and_hold(x: nil, y: nil, element: nil, duration: 1.0)
|
100
100
|
return 'Set x, y or element' if (x.nil? || y.nil?) && element.nil?
|
101
101
|
|
102
|
-
args = element.nil? ? { x: x, y: y } : { element: element.
|
102
|
+
args = element.nil? ? { x: x, y: y } : { element: element.id }
|
103
103
|
args[:duration] = duration
|
104
104
|
@driver.execute_script 'mobile: touchAndHold', args
|
105
105
|
end
|
@@ -110,7 +110,7 @@ module Appium
|
|
110
110
|
# two_finger_tap element: find_element(:accessibility_id, "some item")
|
111
111
|
# ```
|
112
112
|
def two_finger_tap(element:)
|
113
|
-
args = { element: element.
|
113
|
+
args = { element: element.id }
|
114
114
|
@driver.execute_script 'mobile: twoFingerTap', args
|
115
115
|
end
|
116
116
|
|
@@ -121,12 +121,12 @@ module Appium
|
|
121
121
|
# Otherwise they should be calculated relatively to screen borders.
|
122
122
|
#
|
123
123
|
# ```ruby
|
124
|
-
#
|
125
|
-
#
|
124
|
+
# one_finger_tap x: 100, y: 100
|
125
|
+
# one_finger_tap x: 100, y: 100, element: find_element(:accessibility_id, "some item")
|
126
126
|
# ```
|
127
|
-
def
|
127
|
+
def one_finger_tap(x:, y:, element: nil)
|
128
128
|
args = { x: x, y: y }
|
129
|
-
args[:element] = element.
|
129
|
+
args[:element] = element.id if element
|
130
130
|
@driver.execute_script 'mobile: tap', args
|
131
131
|
end
|
132
132
|
|
@@ -146,7 +146,7 @@ module Appium
|
|
146
146
|
# ```
|
147
147
|
def drag_from_to_for_duration(from_x:, from_y:, to_x:, to_y:, duration: 1.0, element: nil)
|
148
148
|
args = { fromX: from_x, fromY: from_y, toX: to_x, toY: to_y, duration: duration }
|
149
|
-
args[:element] = element.
|
149
|
+
args[:element] = element.id if element
|
150
150
|
@driver.execute_script 'mobile: dragFromToForDuration', args
|
151
151
|
end
|
152
152
|
# rubocop:enable Metrics/ParameterLists
|
@@ -164,7 +164,7 @@ module Appium
|
|
164
164
|
def select_picker_wheel(element:, order:, offset: nil)
|
165
165
|
return 'Set "next" or "previous" for :order' unless %w(next previous).include?(order)
|
166
166
|
|
167
|
-
args = { element: element.
|
167
|
+
args = { element: element.id, order: order }
|
168
168
|
args[:offset] = offset if offset
|
169
169
|
@driver.execute_script 'mobile: selectPickerWheelValue', args
|
170
170
|
end
|
@@ -33,8 +33,7 @@ module Appium
|
|
33
33
|
# xcuitest_install_app(app: "path/to/app.app")
|
34
34
|
#
|
35
35
|
def xcuitest_install_app(app:)
|
36
|
-
|
37
|
-
@driver.execute_script 'mobile: installApp', args
|
36
|
+
@driver.install_app app
|
38
37
|
end
|
39
38
|
|
40
39
|
# Verifies whether the application with given bundle identifier is installed on the device.
|
@@ -47,8 +46,7 @@ module Appium
|
|
47
46
|
# xcuitest_app_installed?(bundle_id: "io.appium.bundle") #=> true or false
|
48
47
|
#
|
49
48
|
def xcuitest_app_installed?(bundle_id:)
|
50
|
-
|
51
|
-
@driver.execute_script 'mobile: isAppInstalled', args
|
49
|
+
@driver.app_installed? bundle_id
|
52
50
|
end
|
53
51
|
|
54
52
|
# Uninstalls an existing application from the device under test. This endpoint does not verify
|
@@ -62,8 +60,7 @@ module Appium
|
|
62
60
|
# xcuitest_remove_app(bundle_id: "io.appium.bundle") #=> 1
|
63
61
|
#
|
64
62
|
def xcuitest_remove_app(bundle_id:)
|
65
|
-
|
66
|
-
@driver.execute_script 'mobile: removeApp', args
|
63
|
+
@driver.remove_app bundle_id
|
67
64
|
end
|
68
65
|
|
69
66
|
# Executes an existing application on the device. If the application is already running then
|
@@ -92,8 +89,7 @@ module Appium
|
|
92
89
|
# xcuitest_terminate_app(bundle_id: "io.appium.bundle") #=> 1
|
93
90
|
#
|
94
91
|
def xcuitest_terminate_app(bundle_id:)
|
95
|
-
|
96
|
-
@driver.execute_script 'mobile: terminateApp', args
|
92
|
+
@driver.terminate_app bundle_id
|
97
93
|
end
|
98
94
|
|
99
95
|
# Get the status of an existing application on the device.
|
@@ -114,8 +110,7 @@ module Appium
|
|
114
110
|
# xcuitest_query_app_status(bundle_id: "io.appium.bundle") #=> 1
|
115
111
|
#
|
116
112
|
def xcuitest_query_app_status(bundle_id:)
|
117
|
-
|
118
|
-
@driver.execute_script 'mobile: queryAppState', args
|
113
|
+
@driver.app_state bundle_id
|
119
114
|
end
|
120
115
|
|
121
116
|
# Activates an existing application on the device under test and moves it to the foreground.
|
@@ -130,8 +125,7 @@ module Appium
|
|
130
125
|
# xcuitest_activate_app(bundle_id: "io.appium.bundle") #=> 1
|
131
126
|
#
|
132
127
|
def xcuitest_activate_app(bundle_id:)
|
133
|
-
|
134
|
-
@driver.execute_script 'mobile: activateApp', args
|
128
|
+
@driver.activate_app bundle_id
|
135
129
|
end
|
136
130
|
end
|
137
131
|
end # module Xcuitest
|
@@ -74,7 +74,7 @@ module Appium
|
|
74
74
|
c_names = class_names.map { |class_name| %(type == "#{class_name}") }.join(' || ')
|
75
75
|
|
76
76
|
predicate = if value
|
77
|
-
%((#{c_names}) && (name contains[c] "#{value}" || label contains[c] "#{value}" || value contains[c] "#{value}")) # rubocop:disable
|
77
|
+
%((#{c_names}) && (name contains[c] "#{value}" || label contains[c] "#{value}" || value contains[c] "#{value}")) # rubocop:disable Layout/LineLength
|
78
78
|
else
|
79
79
|
c_names
|
80
80
|
end
|
data/lib/appium_lib/version.rb
CHANGED
@@ -14,6 +14,6 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
# Version and Date are defined on the 'Appium' module, not 'Appium::Common'
|
17
|
-
VERSION = '
|
18
|
-
DATE = '
|
17
|
+
VERSION = '12.0.0.rc2' unless defined? ::Appium::VERSION
|
18
|
+
DATE = '2021-10-25' unless defined? ::Appium::DATE
|
19
19
|
end
|
data/readme.md
CHANGED
@@ -21,9 +21,11 @@ We can avoid the class driver with current `ruby_lib`, but if you'd like to impl
|
|
21
21
|
# Setup
|
22
22
|
## Requirement
|
23
23
|
- [Appium](https://github.com/appium/appium#requirements)
|
24
|
-
- Ruby: 2.
|
24
|
+
- Ruby: 2.6+
|
25
25
|
|
26
26
|
### Ruby Lib and Appium
|
27
|
+
|
28
|
+
- Ruby library version over `12.0.0` is based on Selenium v4
|
27
29
|
- Ruby library version over `9.8.0` requires Appium over `1.8`
|
28
30
|
- Ruby library version under `9.7.5` can work with Appium under `1.7`
|
29
31
|
|
@@ -35,16 +37,9 @@ $ appium
|
|
35
37
|
```
|
36
38
|
|
37
39
|
## Install / Upgrade
|
38
|
-
- Update rubygems and bundler
|
39
|
-
```bash
|
40
|
-
$ gem update --system
|
41
|
-
$ gem update bundler
|
42
|
-
```
|
43
40
|
|
44
|
-
- Install the latest gem release
|
45
41
|
```bash
|
46
|
-
gem
|
47
|
-
gem install --no-rdoc --no-ri appium_lib
|
42
|
+
gem install appium_lib
|
48
43
|
```
|
49
44
|
|
50
45
|
## [Sauce Labs env vars](https://github.com/appium/ruby_lib/blob/master/lib/appium_lib/sauce_labs.rb)
|