appium_lib 4.0.0 → 4.1.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.
- checksums.yaml +4 -4
- data/android_tests/lib/android/specs/common/helper.rb +26 -13
- data/android_tests/lib/android/specs/driver.rb +4 -4
- data/docs/android_docs.md +249 -203
- data/docs/docs.md +2 -12
- data/docs/ios_docs.md +210 -196
- data/ios_tests/lib/ios/specs/common/helper.rb +19 -13
- data/lib/appium_lib/android/client_xpath.rb +47 -0
- data/lib/appium_lib/common/helper.rb +0 -58
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/common/wait.rb +99 -0
- data/lib/appium_lib/device/touch_actions.rb +3 -0
- data/lib/appium_lib/driver.rb +38 -10
- data/release_notes.md +13 -0
- metadata +4 -2
@@ -8,7 +8,7 @@ describe 'common/helper.rb' do
|
|
8
8
|
before_first
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
wait_opts = { timeout: 0.2, interval: 0.2 } # max_wait, interval
|
12
12
|
|
13
13
|
=begin
|
14
14
|
There's no `must_not_raise` as the opposite of must_raise
|
@@ -21,17 +21,20 @@ must_not_raise is a no-op.
|
|
21
21
|
# max_wait=0 is infinity to use 0.1
|
22
22
|
t 'wait' do
|
23
23
|
# successful wait should not raise error
|
24
|
-
wait(
|
25
|
-
wait(
|
26
|
-
wait(
|
24
|
+
wait(wait_opts) { true }
|
25
|
+
wait(wait_opts) { false }
|
26
|
+
wait(wait_opts) { nil }
|
27
27
|
|
28
28
|
# failed wait should error
|
29
|
-
proc { wait(
|
29
|
+
proc { wait(wait_opts) { raise } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
30
30
|
|
31
31
|
# regular rescue will not handle exceptions outside of StandardError hierarchy
|
32
32
|
# must rescue Exception explicitly to rescue everything
|
33
|
-
proc { wait(
|
34
|
-
proc { wait(0.2, 0.0) { raise NoMemoryError } }.must_raise
|
33
|
+
proc { wait(wait_opts) { raise NoMemoryError } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
34
|
+
proc { wait(timeout: 0.2, interval: 0.0) { raise NoMemoryError } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
35
|
+
|
36
|
+
# invalid keys are rejected
|
37
|
+
proc { wait(invalidkey: 2) { true } }.must_raise RuntimeError
|
35
38
|
end
|
36
39
|
|
37
40
|
t 'ignore' do
|
@@ -46,19 +49,22 @@ must_not_raise is a no-op.
|
|
46
49
|
# wait_true is a success unless the value is not true
|
47
50
|
t 'wait_true' do
|
48
51
|
# successful wait should not error
|
49
|
-
wait_true(
|
52
|
+
wait_true(wait_opts) { true }
|
50
53
|
|
51
54
|
# failed wait should error
|
52
|
-
proc { wait_true(
|
53
|
-
proc { wait_true(
|
55
|
+
proc { wait_true(wait_opts) { false } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
56
|
+
proc { wait_true(wait_opts) { nil } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
54
57
|
|
55
58
|
# raise should error
|
56
|
-
proc { wait_true(
|
59
|
+
proc { wait_true(wait_opts) { raise } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
57
60
|
|
58
61
|
# regular rescue will not handle exceptions outside of StandardError hierarchy
|
59
62
|
# must rescue Exception explicitly to rescue everything
|
60
|
-
proc { wait_true(
|
61
|
-
proc { wait_true(0.2, 0.0) { raise NoMemoryError } }.must_raise
|
63
|
+
proc { wait_true(wait_opts) { raise NoMemoryError } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
64
|
+
proc { wait_true(timeout: 0.2, interval: 0.0) { raise NoMemoryError } }.must_raise Selenium::WebDriver::Error::TimeOutError
|
65
|
+
|
66
|
+
# invalid keys are rejected
|
67
|
+
proc { wait_true(invalidkey: 2) { true } }.must_raise RuntimeError
|
62
68
|
end
|
63
69
|
|
64
70
|
# t 'id' # id is for Selendroid
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Appium
|
4
|
+
module Android
|
5
|
+
def _nodeset_to_uiselector opts={}
|
6
|
+
results = ''
|
7
|
+
|
8
|
+
nodes = opts[:nodes]
|
9
|
+
first = opts[:first]
|
10
|
+
|
11
|
+
nodes = [nodes[0]] if first
|
12
|
+
|
13
|
+
nodes.each do |node|
|
14
|
+
results += %Q(new UiSelector().className("#{node.name}").instance(#{node.attr('instance')});)
|
15
|
+
end
|
16
|
+
|
17
|
+
results.strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def _client_xpath opts={}
|
21
|
+
root_node = Nokogiri::XML(get_source).children.first
|
22
|
+
|
23
|
+
instance = Hash.new -1
|
24
|
+
|
25
|
+
root_node.traverse do |node|
|
26
|
+
number = instance[node.name] += 1
|
27
|
+
node.set_attribute 'instance', number
|
28
|
+
end
|
29
|
+
|
30
|
+
nodes = root_node.xpath(opts[:xpath])
|
31
|
+
first = opts[:first]
|
32
|
+
|
33
|
+
_nodeset_to_uiselector nodes: nodes, first: first
|
34
|
+
end
|
35
|
+
|
36
|
+
def client_xpath xpath
|
37
|
+
find_element :uiautomator, _client_xpath(xpath: xpath, first: true)
|
38
|
+
end
|
39
|
+
|
40
|
+
def client_xpaths xpath
|
41
|
+
find_elements :uiautomator, _client_xpath(xpath: xpath, first: false)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# http://stackoverflow.com/questions/9199415/getting-first-node-in-xpath-result-set
|
47
|
+
# '(//android.widget.TextView)[1]' not '//android.widget.TextView[1]'
|
@@ -18,38 +18,6 @@ module Appium
|
|
18
18
|
#
|
19
19
|
# find_element :text doesn't work so use XPath to find by text.
|
20
20
|
|
21
|
-
# Check every 0.5 seconds to see if block.call doesn't raise an exception.
|
22
|
-
# if .call raises an exception then it will be tried again.
|
23
|
-
# if .call doesn't raise an exception then it will stop waiting.
|
24
|
-
#
|
25
|
-
# Example: wait { name('back').click }
|
26
|
-
#
|
27
|
-
# Give up after 30 seconds.
|
28
|
-
# @param max_wait [Integer] the maximum time in seconds to wait for.
|
29
|
-
# Note that max wait 0 means infinity.
|
30
|
-
# @param interval [Float] the time in seconds to wait after calling the block
|
31
|
-
# @param block [Block] the block to call
|
32
|
-
# @return [Object] the result of block.call
|
33
|
-
def wait max_wait=30, interval=0.5, &block
|
34
|
-
max_wait = 1 if max_wait <= 0
|
35
|
-
result = nil
|
36
|
-
timeout max_wait do
|
37
|
-
until (
|
38
|
-
begin
|
39
|
-
result = block.call || true
|
40
|
-
rescue Errno::ECONNREFUSED => e
|
41
|
-
raise e
|
42
|
-
rescue Exception
|
43
|
-
sleep interval
|
44
|
-
# sleep returns truthy value which breaks out of until
|
45
|
-
# must return false value
|
46
|
-
false
|
47
|
-
end)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
result
|
51
|
-
end
|
52
|
-
|
53
21
|
# Return block.call and ignore any exceptions.
|
54
22
|
def ignore &block
|
55
23
|
begin
|
@@ -58,32 +26,6 @@ module Appium
|
|
58
26
|
end
|
59
27
|
end
|
60
28
|
|
61
|
-
# Check every 0.5 seconds to see if block.call returns a truthy value.
|
62
|
-
# Note this isn't a strict boolean true, any truthy value is accepted.
|
63
|
-
# false and nil are considered failures.
|
64
|
-
# Give up after 30 seconds.
|
65
|
-
# @param max_wait [Integer] the maximum time in seconds to wait for
|
66
|
-
# @param interval [Float] the time in seconds to wait after calling the block
|
67
|
-
# @param block [Block] the block to call
|
68
|
-
# @return [Object] the result of block.call
|
69
|
-
def wait_true max_wait=30, interval=0.5, &block
|
70
|
-
max_wait = 1 if max_wait <= 0
|
71
|
-
result = nil
|
72
|
-
timeout max_wait do
|
73
|
-
until (
|
74
|
-
begin
|
75
|
-
result = block.call
|
76
|
-
rescue Errno::ECONNREFUSED => e
|
77
|
-
raise e
|
78
|
-
rescue Exception
|
79
|
-
ensure
|
80
|
-
sleep interval unless result
|
81
|
-
end)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
result
|
85
|
-
end
|
86
|
-
|
87
29
|
# Navigate back.
|
88
30
|
# @return [void]
|
89
31
|
def back
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Appium
|
2
2
|
# Version and Date are defined on the 'Appium' module, not 'Appium::Common'
|
3
|
-
VERSION = '4.
|
4
|
-
DATE = '2014-07-
|
3
|
+
VERSION = '4.1.0' unless defined? ::Appium::VERSION
|
4
|
+
DATE = '2014-07-21' unless defined? ::Appium::DATE
|
5
5
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Appium
|
2
|
+
module Common
|
3
|
+
|
4
|
+
# http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html
|
5
|
+
# Note that the Ruby timeout module is avoided. timeout has problems.
|
6
|
+
# https://coderwall.com/p/1novga
|
7
|
+
|
8
|
+
# Wait code from the selenium Ruby gem
|
9
|
+
# https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
|
10
|
+
def _generic_wait opts={}, &block
|
11
|
+
valid_keys = [:timeout, :interval, :message, :ignore, :return_if_true]
|
12
|
+
invalid_keys = []
|
13
|
+
opts.keys.each { |key| invalid_keys << key unless valid_keys.include?(key) }
|
14
|
+
# [:one, :two] => :one, :two
|
15
|
+
raise "Invalid keys #{invalid_keys.to_s[1..-2]}. Valid keys are #{valid_keys.to_s[1..-2]}" unless invalid_keys.empty?
|
16
|
+
|
17
|
+
timeout = opts.fetch(:timeout, 30)
|
18
|
+
interval = opts.fetch(:interval, 0.5)
|
19
|
+
message = opts[:message]
|
20
|
+
ignored = Array(opts[:ignore] || ::Exception)
|
21
|
+
return_if_true = opts[:return_if_true]
|
22
|
+
|
23
|
+
end_time = Time.now + timeout
|
24
|
+
last_error = nil
|
25
|
+
|
26
|
+
until Time.now > end_time
|
27
|
+
begin
|
28
|
+
if return_if_true
|
29
|
+
result = block.call
|
30
|
+
return result if result
|
31
|
+
else
|
32
|
+
return block.call
|
33
|
+
end
|
34
|
+
rescue ::Errno::ECONNREFUSED => e
|
35
|
+
raise e
|
36
|
+
rescue *ignored => last_error
|
37
|
+
# swallowed
|
38
|
+
end
|
39
|
+
|
40
|
+
sleep interval
|
41
|
+
end
|
42
|
+
|
43
|
+
if message
|
44
|
+
msg = message.dup
|
45
|
+
else
|
46
|
+
msg = "timed out after #{timeout} seconds"
|
47
|
+
end
|
48
|
+
|
49
|
+
msg << " (#{last_error.message})" if last_error
|
50
|
+
|
51
|
+
raise Selenium::WebDriver::Error::TimeOutError, msg
|
52
|
+
end
|
53
|
+
|
54
|
+
# process opts before calling _generic_wait
|
55
|
+
def _process_wait_opts opts
|
56
|
+
opts = { timeout: opts } if opts.is_a?(Numeric)
|
57
|
+
raise 'opts must be a hash' unless opts.is_a? Hash
|
58
|
+
opts
|
59
|
+
end
|
60
|
+
|
61
|
+
# Check every interval seconds to see if block.call returns a truthy value.
|
62
|
+
# Note this isn't a strict boolean true, any truthy value is accepted.
|
63
|
+
# false and nil are considered failures.
|
64
|
+
# Give up after timeout seconds.
|
65
|
+
#
|
66
|
+
# Wait code from the selenium Ruby gem
|
67
|
+
# https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
|
68
|
+
#
|
69
|
+
# If only a number is provided then it's treated as the timeout value.
|
70
|
+
#
|
71
|
+
# @param [Hash] opts Options
|
72
|
+
# @option opts [Numeric] :timeout (30) Seconds to wait before timing out.
|
73
|
+
# @option opts [Numeric] :interval (0.5) Seconds to sleep between polls.
|
74
|
+
# @option opts [String] :message Exception message if timed out.
|
75
|
+
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
|
76
|
+
def wait_true opts={}, &block
|
77
|
+
opts = _process_wait_opts(opts).merge(return_if_true: true)
|
78
|
+
_generic_wait opts, &block
|
79
|
+
end
|
80
|
+
|
81
|
+
# Check every interval seconds to see if block.call doesn't raise an exception.
|
82
|
+
# Give up after timeout seconds.
|
83
|
+
#
|
84
|
+
# Wait code from the selenium Ruby gem
|
85
|
+
# https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
|
86
|
+
#
|
87
|
+
# If only a number is provided then it's treated as the timeout value.
|
88
|
+
#
|
89
|
+
# @param [Hash] opts Options
|
90
|
+
# @option opts [Numeric] :timeout (30) Seconds to wait before timing out.
|
91
|
+
# @option opts [Numeric] :interval (0.5) Seconds to sleep between polls.
|
92
|
+
# @option opts [String] :message Exception message if timed out.
|
93
|
+
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
|
94
|
+
def wait opts={}, &block
|
95
|
+
opts = _process_wait_opts(opts).merge(return_if_true: false)
|
96
|
+
_generic_wait opts, &block
|
97
|
+
end
|
98
|
+
end # module Common
|
99
|
+
end # module Appium
|
@@ -93,6 +93,9 @@ module Appium
|
|
93
93
|
end
|
94
94
|
|
95
95
|
# Convenience method to peform a swipe.
|
96
|
+
#
|
97
|
+
# Note that iOS 7 simulators have broken swipe.
|
98
|
+
#
|
96
99
|
# @option opts [int] :start_x Where to start swiping, on the x axis. Default 0.
|
97
100
|
# @option opts [int] :start_y Where to start swiping, on the y axis. Default 0.
|
98
101
|
# @option opts [int] :end_x Where to end swiping, on the x axis. Default 0.
|
data/lib/appium_lib/driver.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative 'awesome_print/ostruct'
|
|
8
8
|
|
9
9
|
# common
|
10
10
|
require_relative 'common/helper'
|
11
|
+
require_relative 'common/wait'
|
11
12
|
require_relative 'common/patch'
|
12
13
|
require_relative 'common/version'
|
13
14
|
require_relative 'common/element/window'
|
@@ -26,6 +27,7 @@ require_relative 'ios/mobile_methods'
|
|
26
27
|
# android
|
27
28
|
require_relative 'android/helper'
|
28
29
|
require_relative 'android/patch'
|
30
|
+
require_relative 'android/client_xpath'
|
29
31
|
require_relative 'android/element/alert'
|
30
32
|
require_relative 'android/element/button'
|
31
33
|
require_relative 'android/element/generic'
|
@@ -92,8 +94,8 @@ module Appium
|
|
92
94
|
data = Appium::symbolize_keys data
|
93
95
|
ap data unless data.empty? if verbose
|
94
96
|
|
95
|
-
if data && data[:caps] && data[:caps][:app]
|
96
|
-
data[:caps][:app] = Appium::Driver.absolute_app_path data
|
97
|
+
if data && data[:caps] && data[:caps][:app] && !data[:caps][:app].empty?
|
98
|
+
data[:caps][:app] = Appium::Driver.absolute_app_path data
|
97
99
|
end
|
98
100
|
|
99
101
|
# return list of require files as an array
|
@@ -147,12 +149,26 @@ module Appium
|
|
147
149
|
result
|
148
150
|
end
|
149
151
|
|
150
|
-
|
152
|
+
# if modules is a module instead of an array, then the constants of
|
153
|
+
# that module are promoted on.
|
154
|
+
# otherwise, the array of modules will be used as the promotion target.
|
155
|
+
def self.promote_singleton_appium_methods modules
|
151
156
|
raise 'Driver is nil' if $driver.nil?
|
152
|
-
|
157
|
+
|
158
|
+
target_modules = []
|
159
|
+
|
160
|
+
if modules.is_a? Module
|
161
|
+
modules.constants.each do |sub_module|
|
162
|
+
target_modules << modules.const_get(sub_module)
|
163
|
+
end
|
164
|
+
else
|
165
|
+
raise 'modules must be a module or an array' unless modules.is_a? Array
|
166
|
+
target_modules = modules
|
167
|
+
end
|
168
|
+
|
169
|
+
target_modules.each do |const|
|
153
170
|
#noinspection RubyResolve
|
154
171
|
$driver.public_methods(false).each do |m|
|
155
|
-
const = main_module.const_get(sub_module)
|
156
172
|
const.send(:define_singleton_method, m) do |*args, &block|
|
157
173
|
begin
|
158
174
|
super(*args, &block) # promote.rb
|
@@ -264,8 +280,8 @@ module Appium
|
|
264
280
|
|
265
281
|
# Path to the .apk, .app or .app.zip.
|
266
282
|
# The path can be local or remote for Sauce.
|
267
|
-
|
268
|
-
@caps[:app] = self.class.absolute_app_path
|
283
|
+
if @caps && @caps[:app] && ! @caps[:app].empty?
|
284
|
+
@caps[:app] = self.class.absolute_app_path opts
|
269
285
|
end
|
270
286
|
|
271
287
|
# https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile
|
@@ -356,12 +372,24 @@ module Appium
|
|
356
372
|
end
|
357
373
|
|
358
374
|
# Converts app_path to an absolute path.
|
375
|
+
#
|
376
|
+
# opts is the full options hash (caps and appium_lib). If server_url is set
|
377
|
+
# then the app path is used as is.
|
378
|
+
#
|
379
|
+
# if app isn't set then an error is raised.
|
380
|
+
#
|
359
381
|
# @return [String] APP_PATH as an absolute path
|
360
|
-
def self.absolute_app_path
|
361
|
-
raise '
|
382
|
+
def self.absolute_app_path opts
|
383
|
+
raise 'opts must be a hash' unless opts.is_a? Hash
|
384
|
+
caps = opts[:caps] || {}
|
385
|
+
appium_lib_opts = opts[:appium_lib] || {}
|
386
|
+
server_url = appium_lib_opts.fetch :server_url, false
|
387
|
+
|
388
|
+
app_path = caps[:app]
|
389
|
+
raise 'absolute_app_path invoked and app is not set!' if app_path.nil? || app_path.empty?
|
362
390
|
# may be absolute path to file on remote server.
|
363
391
|
# if the file is on the remote server then we can't check if it exists
|
364
|
-
return app_path if
|
392
|
+
return app_path if server_url
|
365
393
|
# Sauce storage API. http://saucelabs.com/docs/rest#storage
|
366
394
|
return app_path if app_path.start_with? 'sauce-storage:'
|
367
395
|
return app_path if app_path.match(/^http/) # public URL for Sauce
|
data/release_notes.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
#### v4.1.0 2014-07-21
|
2
|
+
|
3
|
+
- [a13158f](https://github.com/appium/ruby_lib/commit/a13158fb926212d84f26120c3bc5355c8cd34baf) Release 4.1.0
|
4
|
+
- [be1c710](https://github.com/appium/ruby_lib/commit/be1c710134ee9a001b8e71c0ce5cbb5786bebf1e) Update android specs
|
5
|
+
- [4edd949](https://github.com/appium/ruby_lib/commit/4edd94989519ec14acf9c694d9ed3ae6a5939b10) Update self.promote_singleton_appium_methods
|
6
|
+
- [82a236a](https://github.com/appium/ruby_lib/commit/82a236a84742f1eb6d55acab00d8f222d721bd9a) Update docs.md
|
7
|
+
- [a724d5d](https://github.com/appium/ruby_lib/commit/a724d5d3711cdfa3ea420663949c06017189bf02) Fix #224
|
8
|
+
- [d05bfe8](https://github.com/appium/ruby_lib/commit/d05bfe85d6c356a8ea6a0f151aaf21dfef979736) Fix docs
|
9
|
+
- [c04d6f0](https://github.com/appium/ruby_lib/commit/c04d6f048ee4e24c66bef662e31a0d957360e7a7) Fix wait / wait_true by using selenium wait method
|
10
|
+
- [da19c8c](https://github.com/appium/ruby_lib/commit/da19c8cca5753f06576b82bbbb6e77e7e36bcb9c) Add iOS 7 note to swipe
|
11
|
+
- [4f4d800](https://github.com/appium/ruby_lib/commit/4f4d80094eac5a4fbc2c11b8050155b2f767839c) Add client side xpath support
|
12
|
+
|
13
|
+
|
1
14
|
#### v4.0.0 2014-07-05
|
2
15
|
|
3
16
|
- [8cc004a](https://github.com/appium/ruby_lib/commit/8cc004ad04ec087a8a11c06ca0749a5e2c6586a7) Release 4.0.0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appium_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- code@bootstraponline.com
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: selenium-webdriver
|
@@ -322,6 +322,7 @@ files:
|
|
322
322
|
- ios_tests/upload/sauce_storage.rb
|
323
323
|
- ios_tests/upload/upload.rb
|
324
324
|
- lib/appium_lib.rb
|
325
|
+
- lib/appium_lib/android/client_xpath.rb
|
325
326
|
- lib/appium_lib/android/element/alert.rb
|
326
327
|
- lib/appium_lib/android/element/button.rb
|
327
328
|
- lib/appium_lib/android/element/generic.rb
|
@@ -335,6 +336,7 @@ files:
|
|
335
336
|
- lib/appium_lib/common/helper.rb
|
336
337
|
- lib/appium_lib/common/patch.rb
|
337
338
|
- lib/appium_lib/common/version.rb
|
339
|
+
- lib/appium_lib/common/wait.rb
|
338
340
|
- lib/appium_lib/device/device.rb
|
339
341
|
- lib/appium_lib/device/multi_touch.rb
|
340
342
|
- lib/appium_lib/device/touch_actions.rb
|