appium_lib_core 4.1.0 → 5.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.github/workflows/unittest.yml +8 -9
- data/.rubocop.yml +95 -1
- data/CHANGELOG.md +94 -276
- data/README.md +11 -6
- data/Rakefile +4 -0
- data/appium_lib_core.gemspec +4 -7
- data/bin/console +0 -4
- data/ci-jobs/functional/run_appium.yml +3 -3
- data/ci-jobs/functional_test.yml +3 -3
- data/docs/mobile_command.md +2 -2
- data/lib/appium_lib_core/android/device/auth_finger_print.rb +2 -1
- data/lib/appium_lib_core/android/device.rb +4 -4
- data/lib/appium_lib_core/common/base/bridge.rb +297 -90
- data/lib/appium_lib_core/common/base/capabilities.rb +10 -3
- data/lib/appium_lib_core/common/base/device_ime.rb +49 -0
- data/lib/appium_lib_core/common/base/driver.rb +183 -171
- data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
- data/lib/appium_lib_core/common/base/has_location.rb +80 -0
- data/lib/appium_lib_core/common/base/has_network_connection.rb +56 -0
- data/lib/appium_lib_core/common/base/http_default.rb +1 -3
- data/lib/appium_lib_core/common/base/remote_status.rb +31 -0
- data/lib/appium_lib_core/common/base/rotable.rb +54 -0
- data/lib/appium_lib_core/common/base/screenshot.rb +6 -6
- data/lib/appium_lib_core/common/base/search_context.rb +19 -4
- data/lib/appium_lib_core/common/base.rb +1 -3
- data/lib/appium_lib_core/common/command.rb +257 -4
- data/lib/appium_lib_core/common/device/image_comparison.rb +12 -4
- data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
- data/lib/appium_lib_core/common/{command/mjsonwp.rb → device/orientation.rb} +14 -11
- data/lib/appium_lib_core/common/device/touch_actions.rb +2 -0
- data/lib/appium_lib_core/common/device/value.rb +6 -6
- data/lib/appium_lib_core/common/error.rb +4 -1
- data/lib/appium_lib_core/common/log.rb +4 -1
- data/lib/appium_lib_core/common/touch_action/multi_touch.rb +19 -0
- data/lib/appium_lib_core/common/touch_action/touch_actions.rb +16 -2
- data/lib/appium_lib_core/common/wait.rb +38 -6
- data/lib/appium_lib_core/device.rb +1 -5
- data/lib/appium_lib_core/driver.rb +30 -46
- data/lib/appium_lib_core/{patch.rb → element.rb} +66 -9
- data/lib/appium_lib_core/ios/uiautomation/patch.rb +1 -1
- data/lib/appium_lib_core/{common/base/command.rb → mac2/bridge.rb} +9 -8
- data/lib/appium_lib_core/mac2/device/screen.rb +48 -0
- data/lib/appium_lib_core/mac2/device.rb +92 -0
- data/lib/appium_lib_core/mac2.rb +17 -0
- data/lib/appium_lib_core/version.rb +2 -2
- data/lib/appium_lib_core.rb +2 -5
- data/release_notes.md +132 -0
- data/script/commands.rb +3 -37
- metadata +27 -68
- data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -81
- data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -252
- data/lib/appium_lib_core/common/command/common.rb +0 -110
- data/lib/appium_lib_core/common/command/w3c.rb +0 -56
@@ -47,7 +47,7 @@ module Appium
|
|
47
47
|
# not available in the default OpenCV installation and have to be enabled manually
|
48
48
|
# before library compilation. The default detector name is 'ORB'.
|
49
49
|
# @param [String] match_func The name of the matching function. The default one is 'BruteForce'.
|
50
|
-
# @param [String] good_matches_factor The maximum count of "good" matches (e. g. with minimal distances).
|
50
|
+
# @param [String, nil] good_matches_factor The maximum count of "good" matches (e. g. with minimal distances).
|
51
51
|
# The default one is nil.
|
52
52
|
# @param [Bool] visualize Makes the endpoint to return an image, which contains the visualized result of
|
53
53
|
# the corresponding picture matching operation. This option is disabled by default.
|
@@ -94,7 +94,12 @@ module Appium
|
|
94
94
|
# are supported.
|
95
95
|
# @param [Bool] visualize Makes the endpoint to return an image, which contains the visualized result of
|
96
96
|
# the corresponding picture matching operation. This option is disabled by default.
|
97
|
-
# @param [Float] threshold [0.5] At what normalized threshold to reject
|
97
|
+
# @param [Float, nil] threshold [0.5] At what normalized threshold to reject
|
98
|
+
# @param [bool, nil] multiple Whether to enable the support of multiple image occurrences @since Appium 1.21.0.
|
99
|
+
# @param [integer, nil] match_neighbour_threshold The pixel distance between matches we consider to be part of
|
100
|
+
# the same template match @since Appium 1.21.0.
|
101
|
+
# This option is only considered if multiple matches mode is enabled.
|
102
|
+
# 10 pixels by default.
|
98
103
|
#
|
99
104
|
# @example
|
100
105
|
# @driver.find_image_occurrence full_image: "image data 1", partial_image: "image data 2"
|
@@ -102,12 +107,15 @@ module Appium
|
|
102
107
|
# visual = @@driver.find_image_occurrence full_image: image1, partial_image: image2, visualize: true
|
103
108
|
# File.write 'find_result_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
|
104
109
|
#
|
105
|
-
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil
|
110
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
|
111
|
+
multiple: nil, match_neighbour_threshold: nil)
|
106
112
|
raise "visualize should be #{MATCH_TEMPLATE[:visualize]}" unless MATCH_TEMPLATE[:visualize].member?(visualize)
|
107
113
|
|
108
114
|
options = {}
|
109
115
|
options[:visualize] = visualize
|
110
116
|
options[:threshold] = threshold unless threshold.nil?
|
117
|
+
options[:multiple] = multiple unless multiple.nil?
|
118
|
+
options[:matchNeighbourThreshold] = match_neighbour_threshold unless match_neighbour_threshold.nil?
|
111
119
|
|
112
120
|
compare_images(mode: :matchTemplate, first_image: full_image, second_image: partial_image, options: options)
|
113
121
|
end
|
@@ -144,7 +152,7 @@ module Appium
|
|
144
152
|
# +:matchFeatures is by default.
|
145
153
|
# @param [String] first_image An image data. All image formats, that OpenCV library itself accepts, are supported.
|
146
154
|
# @param [String] second_image An image data. All image formats, that OpenCV library itself accepts, are supported.
|
147
|
-
# @param [Hash] options The content of this dictionary depends on the actual +mode+ value.
|
155
|
+
# @param [Hash, nil] options The content of this dictionary depends on the actual +mode+ value.
|
148
156
|
# See the documentation on +appium-support+ module for more details.
|
149
157
|
# @return [Hash] The content of the resulting dictionary depends on the actual +mode+ and +options+ values.
|
150
158
|
# See the documentation on +appium-support+ module for more details.
|
@@ -25,8 +25,8 @@ module Appium
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def press_keycode(key, metastate: [], flags: [])
|
28
|
-
raise ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
29
|
-
raise ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
28
|
+
raise ::Appium::Core::Error::ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
29
|
+
raise ::Appium::Core::Error::ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
30
30
|
|
31
31
|
args = { keycode: key }
|
32
32
|
args[:metastate] = metastate.reduce(0) { |acc, meta| acc | meta } unless metastate.empty?
|
@@ -36,8 +36,8 @@ module Appium
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def long_press_keycode(key, metastate: [], flags: [])
|
39
|
-
raise ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
40
|
-
raise ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
39
|
+
raise ::Appium::Core::Error::ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
40
|
+
raise ::Appium::Core::Error::ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
41
41
|
|
42
42
|
args = { keycode: key }
|
43
43
|
args[:metastate] = metastate.reduce(0) { |acc, meta| acc | meta } unless metastate.empty?
|
@@ -14,15 +14,18 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
-
|
18
|
-
module
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
class Base
|
18
|
+
module Device
|
19
|
+
module Orientation
|
20
|
+
def screen_orientation=(orientation)
|
21
|
+
execute :set_screen_orientation, {}, { orientation: orientation }
|
22
|
+
end
|
23
|
+
|
24
|
+
def screen_orientation
|
25
|
+
execute :get_screen_orientation
|
26
|
+
end
|
27
|
+
end # module Orientation
|
28
|
+
end # module Device
|
29
|
+
end # class Base
|
27
30
|
end # module Core
|
28
|
-
end # Appium
|
31
|
+
end # module Appium
|
@@ -20,11 +20,13 @@ module Appium
|
|
20
20
|
class Base
|
21
21
|
module Device
|
22
22
|
module TouchActions
|
23
|
+
# @deprecated Use W3C actions instead
|
23
24
|
def touch_actions(actions)
|
24
25
|
actions = { actions: [actions].flatten }
|
25
26
|
execute :touch_actions, {}, actions
|
26
27
|
end
|
27
28
|
|
29
|
+
# @deprecated Use W3C actions instead
|
28
30
|
def multi_touch(actions)
|
29
31
|
execute :multi_touch, {}, actions: actions
|
30
32
|
end
|
@@ -17,12 +17,12 @@ module Appium
|
|
17
17
|
class Base
|
18
18
|
module Device
|
19
19
|
module Value
|
20
|
-
def set_immediate_value(
|
21
|
-
execute :set_immediate_value, { id:
|
20
|
+
def set_immediate_value(element_id, *value)
|
21
|
+
execute :set_immediate_value, { id: element_id }, generate_value_and_text(value)
|
22
22
|
end
|
23
23
|
|
24
|
-
def replace_value(
|
25
|
-
execute :replace_value, { id:
|
24
|
+
def replace_value(element_id, *value)
|
25
|
+
execute :replace_value, { id: element_id }, generate_value_and_text(value)
|
26
26
|
end
|
27
27
|
|
28
28
|
private
|
@@ -39,11 +39,11 @@ module Appium
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# Keep .split(//) for backward compatibility for now
|
42
|
-
text = keys.join
|
42
|
+
text = keys.join
|
43
43
|
|
44
44
|
# FIXME: further work for W3C. Over appium 1.15.0 or later
|
45
45
|
# { value: text.split(//), text: text }
|
46
|
-
{ value: text.
|
46
|
+
{ value: text.chars }
|
47
47
|
end
|
48
48
|
end # module Value
|
49
49
|
end # module Device
|
@@ -27,8 +27,11 @@ module Appium
|
|
27
27
|
|
28
28
|
class UnsupportedOperationError < CoreError; end
|
29
29
|
|
30
|
-
# Server side
|
30
|
+
# Server side errors
|
31
31
|
class ServerError < CoreError; end
|
32
|
+
|
33
|
+
# ruby_lib_core library specific errors
|
34
|
+
class ArgumentError < CoreError; end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
@@ -65,7 +65,10 @@ module Appium
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def event=(log_event)
|
68
|
-
|
68
|
+
unless log_event.is_a?(Hash)
|
69
|
+
raise ::Appium::Core::Error::ArgumentError,
|
70
|
+
'log_event should be Hash like { vendor: "appium", event: "funEvent"}'
|
71
|
+
end
|
69
72
|
|
70
73
|
event vendor: log_event[:vendor], event: log_event[:event]
|
71
74
|
end
|
@@ -14,6 +14,9 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
+
#
|
18
|
+
# @deprecated Use W3C actions instead
|
19
|
+
#
|
17
20
|
# MultiTouch actions allow for multiple touches to happen at the same time,
|
18
21
|
# for instance, to simulate multiple finger swipes.
|
19
22
|
#
|
@@ -21,6 +24,18 @@ module Appium
|
|
21
24
|
# add to a new MultiTouch action. When ready, call +prepare()+ and all
|
22
25
|
# actions will be executed simultaneously.
|
23
26
|
#
|
27
|
+
# Consider to use W3C spec touch action like the followings.
|
28
|
+
# https://www.selenium.dev/selenium/docs/api/rb/Selenium/WebDriver/PointerActions.html
|
29
|
+
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/android/webdriver/w3c_actions_test.rb
|
30
|
+
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/ios/webdriver/w3c_actions_test.rb
|
31
|
+
#
|
32
|
+
# About W3C actions
|
33
|
+
# https://www.youtube.com/watch?v=oAJ7jwMNFVU
|
34
|
+
# https://appiumpro.com/editions/30-ios-specific-touch-action-methods
|
35
|
+
# https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api
|
36
|
+
#
|
37
|
+
# Functional test code in ruby_lib_core repository also helps.
|
38
|
+
#
|
24
39
|
# @example
|
25
40
|
#
|
26
41
|
# @driver = Appium::Core.for(opts).start_driver
|
@@ -36,6 +51,10 @@ module Appium
|
|
36
51
|
attr_reader :driver
|
37
52
|
|
38
53
|
def initialize(driver)
|
54
|
+
::Appium::Logger.warn(
|
55
|
+
'[DEPRECATION] Appium::Core::MultiTouch is deprecated in W3C spec. Use W3C actions instead'
|
56
|
+
)
|
57
|
+
|
39
58
|
@actions = []
|
40
59
|
@driver = driver
|
41
60
|
end
|
@@ -14,16 +14,26 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
+
#
|
18
|
+
# @deprecated Use W3C actions instead
|
19
|
+
#
|
17
20
|
# Perform a series of gestures, one after another. Gestures are chained
|
18
21
|
# together and only performed when +perform()+ is called. Default is conducted by global driver.
|
19
22
|
#
|
20
23
|
# Each method returns the object itself, so calls can be chained.
|
21
24
|
#
|
22
25
|
# Consider to use W3C spec touch action like the followings.
|
23
|
-
# https://
|
26
|
+
# https://www.selenium.dev/selenium/docs/api/rb/Selenium/WebDriver/PointerActions.html
|
24
27
|
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/android/webdriver/w3c_actions_test.rb
|
25
28
|
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/ios/webdriver/w3c_actions_test.rb
|
26
29
|
#
|
30
|
+
# About W3C actions
|
31
|
+
# https://www.youtube.com/watch?v=oAJ7jwMNFVU
|
32
|
+
# https://appiumpro.com/editions/30-ios-specific-touch-action-methods
|
33
|
+
# https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api
|
34
|
+
#
|
35
|
+
# Functional test code in ruby_lib_core repository also helps.
|
36
|
+
#
|
27
37
|
# @example
|
28
38
|
#
|
29
39
|
# @driver = Appium::Core.for(opts).start_driver
|
@@ -39,6 +49,10 @@ module Appium
|
|
39
49
|
attr_reader :actions, :driver
|
40
50
|
|
41
51
|
def initialize(driver)
|
52
|
+
::Appium::Logger.warn(
|
53
|
+
'[DEPRECATION] Appium::Core::TouchAction is deprecated in W3C spec. Use W3C actions instead'
|
54
|
+
)
|
55
|
+
|
42
56
|
@actions = []
|
43
57
|
@driver = driver
|
44
58
|
end
|
@@ -195,7 +209,7 @@ module Appium
|
|
195
209
|
end
|
196
210
|
|
197
211
|
def args_with_ele_ref(args)
|
198
|
-
args[:element] = args[:element].
|
212
|
+
args[:element] = args[:element].id if args.key? :element
|
199
213
|
args
|
200
214
|
end
|
201
215
|
end # class TouchAction
|
@@ -38,6 +38,8 @@ module Appium
|
|
38
38
|
#
|
39
39
|
# result = Appium::Core::Wait.until { @driver.find_element(:id, 'something') }
|
40
40
|
#
|
41
|
+
# result = Appium::Core::Wait.until(timeout: 30, message: 'timeout') { @driver.find_element(:id, 'something') }
|
42
|
+
#
|
41
43
|
# result = Appium::Core::Wait.until(object: 'some object') { |object|
|
42
44
|
# @driver.find_element(:id, object)
|
43
45
|
# }
|
@@ -82,6 +84,8 @@ module Appium
|
|
82
84
|
#
|
83
85
|
# Appium::Core::Wait.until_true { @driver.find_element(:id, 'something') }
|
84
86
|
#
|
87
|
+
# Appium::Core::Wait.until_true(timeout: 30) { @driver.find_element(:id, 'something') }
|
88
|
+
#
|
85
89
|
# Appium::Core::Wait.until_true(object: 'some object') { |object|
|
86
90
|
# @driver.find_element(:id, object)
|
87
91
|
# }
|
@@ -133,17 +137,31 @@ module Appium
|
|
133
137
|
# @param [String] message Exception message if timed out.
|
134
138
|
# @param [Array, Exception] ignored Exceptions to ignore while polling (default: Exception)
|
135
139
|
#
|
136
|
-
# @example
|
140
|
+
# @example With core instance
|
137
141
|
#
|
138
142
|
# @core.wait_true { @driver.find_element :accessibility_id, 'something' }
|
143
|
+
# @core.wait_true(timeout: 30, interval: 2) { @driver.find_element :accessibility_id, 'something' }
|
144
|
+
#
|
145
|
+
# @core.wait_until_true { @driver.find_element :accessibility_id, 'something' }
|
146
|
+
# @core.wait_until_true(timeout: 30, interval: 2) { @driver.find_element :accessibility_id, 'something' }
|
147
|
+
#
|
148
|
+
# @example With driver instance
|
149
|
+
#
|
150
|
+
# @driver.wait_true { |d| d.find_element :accessibility_id, 'something' }
|
151
|
+
# @driver.wait_true(timeout: 30, interval: 2) { |d| driver.find_element :accessibility_id, 'something' }
|
139
152
|
#
|
140
|
-
|
153
|
+
# @driver.wait_until_true { |d| d.find_element :accessibility_id, 'something' }
|
154
|
+
# @driver.wait_until_true(timeout: 30, interval: 2) { |d| driver.find_element :accessibility_id, 'something' }
|
155
|
+
#
|
156
|
+
def wait_until_true(timeout: nil, interval: nil, message: nil, ignored: nil, &block)
|
141
157
|
Wait.until_true(timeout: timeout || @wait_timeout,
|
142
158
|
interval: interval || @wait_interval,
|
143
159
|
message: message,
|
144
160
|
ignored: ignored,
|
145
|
-
object: self
|
161
|
+
object: self,
|
162
|
+
&block)
|
146
163
|
end
|
164
|
+
alias wait_true wait_until_true
|
147
165
|
|
148
166
|
# Check every interval seconds to see if yield doesn't raise an exception.
|
149
167
|
# Give up after timeout seconds.
|
@@ -155,17 +173,31 @@ module Appium
|
|
155
173
|
# @param [String] message Exception message if timed out.
|
156
174
|
# @param [Array, Exception] ignored Exceptions to ignore while polling (default: Exception)
|
157
175
|
#
|
158
|
-
# @example
|
176
|
+
# @example With core instance
|
159
177
|
#
|
160
178
|
# @core.wait { @driver.find_element :accessibility_id, 'something' }
|
179
|
+
# @core.wait(timeout: 30, interval: 2) { @driver.find_element :accessibility_id, 'something' }
|
180
|
+
#
|
181
|
+
# @core.wait_until { @driver.find_element :accessibility_id, 'something' }
|
182
|
+
# @core.wait_until(timeout: 30, interval: 2) { @driver.find_element :accessibility_id, 'something' }
|
183
|
+
#
|
184
|
+
# @example With driver instance
|
185
|
+
#
|
186
|
+
# @driver.wait { @driver.find_element :accessibility_id, 'something' }
|
187
|
+
# @driver.wait(timeout: 30, interval: 2) { @driver.find_element :accessibility_id, 'something' }
|
188
|
+
#
|
189
|
+
# @driver.wait_until { |d| d.find_element :accessibility_id, 'something' }
|
190
|
+
# @driver.wait_until(timeout: 30, interval: 2) { |d| d.find_element :accessibility_id, 'something' }
|
161
191
|
#
|
162
|
-
def
|
192
|
+
def wait_until(timeout: nil, interval: nil, message: nil, ignored: nil, &block)
|
163
193
|
Wait.until(timeout: timeout || @wait_timeout,
|
164
194
|
interval: interval || @wait_interval,
|
165
195
|
message: message,
|
166
196
|
ignored: ignored,
|
167
|
-
object: self
|
197
|
+
object: self,
|
198
|
+
&block)
|
168
199
|
end
|
200
|
+
alias wait wait_until
|
169
201
|
end
|
170
202
|
end # module Core
|
171
203
|
end # module Appium
|
@@ -79,11 +79,7 @@ module Appium
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def create_bridge_command(method, &block)
|
82
|
-
::Appium::Core::Base::Bridge
|
83
|
-
undef_method method if method_defined? method
|
84
|
-
block_given? ? class_eval(&block) : define_method(method) { execute method }
|
85
|
-
end
|
86
|
-
::Appium::Core::Base::Bridge::W3C.class_eval do
|
82
|
+
::Appium::Core::Base::Bridge.class_eval do
|
87
83
|
undef_method method if method_defined? method
|
88
84
|
block_given? ? class_eval(&block) : define_method(method) { execute method }
|
89
85
|
end
|
@@ -27,6 +27,8 @@ module Appium
|
|
27
27
|
autoload :Xcuitest, 'appium_lib_core/ios_xcuitest'
|
28
28
|
end
|
29
29
|
|
30
|
+
autoload :Mac2, 'appium_lib_core/mac2'
|
31
|
+
|
30
32
|
autoload :Windows, 'appium_lib_core/windows'
|
31
33
|
|
32
34
|
# This options affects only client side as <code>:appium_lib</code> key.<br>
|
@@ -38,18 +40,18 @@ module Appium
|
|
38
40
|
|
39
41
|
def initialize(appium_lib_opts)
|
40
42
|
@custom_url = appium_lib_opts.fetch :server_url, nil
|
41
|
-
@default_wait = appium_lib_opts.fetch :wait,
|
43
|
+
@default_wait = appium_lib_opts.fetch :wait, nil
|
42
44
|
@enable_idempotency_header = appium_lib_opts.fetch :enable_idempotency_header, true
|
43
45
|
|
44
46
|
# bump current session id into a particular file
|
45
47
|
@export_session = appium_lib_opts.fetch :export_session, false
|
46
48
|
@export_session_path = appium_lib_opts.fetch :export_session_path, default_tmp_appium_lib_session
|
47
49
|
|
48
|
-
@direct_connect = appium_lib_opts.fetch :direct_connect,
|
50
|
+
@direct_connect = appium_lib_opts.fetch :direct_connect, true
|
49
51
|
|
50
52
|
@port = appium_lib_opts.fetch :port, Driver::DEFAULT_APPIUM_PORT
|
51
53
|
|
52
|
-
# timeout and interval used in ::Appium::
|
54
|
+
# timeout and interval used in ::Appium::Commn.wait/wait_true
|
53
55
|
@wait_timeout = appium_lib_opts.fetch :wait_timeout, ::Appium::Core::Wait::DEFAULT_TIMEOUT
|
54
56
|
@wait_interval = appium_lib_opts.fetch :wait_interval, ::Appium::Core::Wait::DEFAULT_INTERVAL
|
55
57
|
|
@@ -133,11 +135,9 @@ module Appium
|
|
133
135
|
attr_reader :export_session_path
|
134
136
|
|
135
137
|
# Default wait time for elements to appear in Appium server side.
|
136
|
-
# Defaults to {::Appium::Core::Driver::DEFAULT_IMPLICIT_WAIT}.<br>
|
137
138
|
# Provide <code>{ appium_lib: { wait: 30 } }</code> to {::Appium::Core.for}
|
138
139
|
# @return [Integer]
|
139
140
|
attr_reader :default_wait
|
140
|
-
DEFAULT_IMPLICIT_WAIT = 0
|
141
141
|
|
142
142
|
# Appium's server port. 4723 is by default. Defaults to {::Appium::Core::Driver::DEFAULT_APPIUM_PORT}.<br>
|
143
143
|
# Provide <code>{ appium_lib: { port: 8080 } }</code> to {::Appium::Core.for}.
|
@@ -175,7 +175,7 @@ module Appium
|
|
175
175
|
# - <code>directConnectPort</code>
|
176
176
|
# - <code>directConnectPath</code>
|
177
177
|
#
|
178
|
-
# Ignore them if this parameter is <code>false</code>. Defaults to
|
178
|
+
# Ignore them if this parameter is <code>false</code>. Defaults to true.
|
179
179
|
#
|
180
180
|
# @return [Bool]
|
181
181
|
attr_reader :direct_connect
|
@@ -185,8 +185,6 @@ module Appium
|
|
185
185
|
# @option opts [Hash] :caps Appium capabilities.
|
186
186
|
# @option opts [Hash] :capabilities The same as :caps.
|
187
187
|
# This param is for compatibility with Selenium WebDriver format
|
188
|
-
# @option opts [Hash] :desired_capabilities The same as :caps.
|
189
|
-
# This param is for compatibility with Selenium WebDriver format
|
190
188
|
# @option opts [Appium::Core::Options] :appium_lib Capabilities affect only ruby client
|
191
189
|
# @option opts [String] :url The same as :custom_url in :appium_lib.
|
192
190
|
# This param is for compatibility with Selenium WebDriver format
|
@@ -197,10 +195,8 @@ module Appium
|
|
197
195
|
#
|
198
196
|
# # format 1
|
199
197
|
# @core = Appium::Core.for caps: {...}, appium_lib: {...}
|
200
|
-
# # format 2. 'capabilities:'
|
198
|
+
# # format 2. 'capabilities:' is also available instead of 'caps:'.
|
201
199
|
# @core = Appium::Core.for url: "http://127.0.0.1:8080/wd/hub", capabilities: {...}, appium_lib: {...}
|
202
|
-
# # format 3. 'appium_lib: {...}' can be blank
|
203
|
-
# @core = Appium::Core.for url: "http://127.0.0.1:8080/wd/hub", desired_capabilities: {...}
|
204
200
|
#
|
205
201
|
#
|
206
202
|
# require 'rubygems'
|
@@ -228,7 +224,7 @@ module Appium
|
|
228
224
|
# @core.start_driver # Connect to 'http://127.0.0.1:8080/wd/hub' because of 'port: 8080'
|
229
225
|
#
|
230
226
|
# # Start iOS driver with .zip file over HTTP
|
231
|
-
# #
|
227
|
+
# # 'capabilities:' is also available instead of 'caps:'. Either is fine.
|
232
228
|
# opts = {
|
233
229
|
# capabilities: {
|
234
230
|
# platformName: :ios,
|
@@ -252,7 +248,7 @@ module Appium
|
|
252
248
|
# # Start iOS driver as another format. 'url' is available like below
|
253
249
|
# opts = {
|
254
250
|
# url: "http://custom-host:8080/wd/hub.com",
|
255
|
-
#
|
251
|
+
# capabilities: {
|
256
252
|
# platformName: :ios,
|
257
253
|
# platformVersion: '11.0',
|
258
254
|
# deviceName: 'iPhone Simulator',
|
@@ -324,7 +320,7 @@ module Appium
|
|
324
320
|
#
|
325
321
|
# # Start iOS driver
|
326
322
|
# opts = {
|
327
|
-
#
|
323
|
+
# capabilities: {
|
328
324
|
# platformName: :ios,
|
329
325
|
# platformVersion: '11.0',
|
330
326
|
# deviceName: 'iPhone Simulator',
|
@@ -365,11 +361,13 @@ module Appium
|
|
365
361
|
end
|
366
362
|
|
367
363
|
begin
|
368
|
-
|
369
|
-
|
370
|
-
|
364
|
+
@driver = ::Appium::Core::Base::Driver.new(listener: @listener,
|
365
|
+
http_client: @http_client,
|
366
|
+
capabilities: @caps, # ::Selenium::WebDriver::Remote::Capabilities
|
371
367
|
url: @custom_url,
|
372
|
-
|
368
|
+
wait_timeout: @wait_timeout,
|
369
|
+
wait_interval: @wait_interval,
|
370
|
+
automation_name: @automation_name)
|
373
371
|
|
374
372
|
if @direct_connect
|
375
373
|
d_c = DirectConnections.new(@driver.capabilities)
|
@@ -410,6 +408,8 @@ module Appium
|
|
410
408
|
|
411
409
|
# Ignore setting default wait if the target driver has no implementation
|
412
410
|
def set_implicit_wait_by_default(wait)
|
411
|
+
return if @default_wait.nil?
|
412
|
+
|
413
413
|
@driver.manage.timeouts.implicit_wait = wait
|
414
414
|
rescue ::Selenium::WebDriver::Error::UnknownError => e
|
415
415
|
unless e.message.include?('The operation requested is not yet implemented')
|
@@ -435,7 +435,8 @@ module Appium
|
|
435
435
|
nil
|
436
436
|
end
|
437
437
|
|
438
|
-
# Returns the server's version info
|
438
|
+
# Returns the server's version info. This method calls +driver.remote_status+ internally
|
439
|
+
#
|
439
440
|
# @return [Hash]
|
440
441
|
#
|
441
442
|
# @example
|
@@ -449,18 +450,20 @@ module Appium
|
|
449
450
|
# }
|
450
451
|
# }
|
451
452
|
#
|
452
|
-
# Returns blank hash
|
453
|
+
# Returns blank hash in a case +driver.remote_status+ got an error
|
454
|
+
# such as Selenium Grid. It returns 500 error against 'remote_status'.
|
453
455
|
#
|
454
456
|
# @example
|
455
457
|
#
|
456
458
|
# @core.appium_server_version #=> {}
|
457
459
|
#
|
458
460
|
def appium_server_version
|
459
|
-
@driver.
|
460
|
-
rescue Selenium::WebDriver::Error::ServerError => e
|
461
|
-
raise ::Appium::Core::Error::ServerError unless e.message.include?('status code 500')
|
461
|
+
return {} if @driver.nil?
|
462
462
|
|
463
|
-
|
463
|
+
@driver.remote_status
|
464
|
+
rescue StandardError
|
465
|
+
# Ignore error case in a case the target appium server
|
466
|
+
# does not support `/status` API.
|
464
467
|
{}
|
465
468
|
end
|
466
469
|
|
@@ -476,21 +479,6 @@ module Appium
|
|
476
479
|
p_version.split('.').map(&:to_i)
|
477
480
|
end
|
478
481
|
|
479
|
-
# Takes a png screenshot and saves to the target path.
|
480
|
-
#
|
481
|
-
# @param png_save_path [String] the full path to save the png
|
482
|
-
# @return [File]
|
483
|
-
#
|
484
|
-
# @example
|
485
|
-
#
|
486
|
-
# @core.screenshot '/tmp/hi.png' #=> nil
|
487
|
-
# # same as '@driver.save_screenshot png_save_path'
|
488
|
-
#
|
489
|
-
def screenshot(png_save_path)
|
490
|
-
::Appium::Logger.warn '[DEPRECATION] screenshot will be removed. Please use driver.save_screenshot instead.'
|
491
|
-
@driver.save_screenshot png_save_path
|
492
|
-
end
|
493
|
-
|
494
482
|
private
|
495
483
|
|
496
484
|
# @private
|
@@ -526,7 +514,7 @@ module Appium
|
|
526
514
|
when :gecko
|
527
515
|
::Appium::Logger.debug('Gecko Driver for macOS')
|
528
516
|
when :mac2
|
529
|
-
::Appium::
|
517
|
+
::Appium::Core::Mac2::Bridge.for self
|
530
518
|
else
|
531
519
|
# no Mac specific extentions
|
532
520
|
::Appium::Logger.debug('macOS Native')
|
@@ -563,10 +551,7 @@ module Appium
|
|
563
551
|
def validate_keys(opts)
|
564
552
|
flatten_ops = flatten_hash_keys(opts)
|
565
553
|
|
566
|
-
|
567
|
-
unless opts.member?(:caps) || opts.member?(:capabilities) || opts.member?(:desired_capabilities)
|
568
|
-
raise Error::NoCapabilityError
|
569
|
-
end
|
554
|
+
raise Error::NoCapabilityError unless opts.member?(:caps) || opts.member?(:capabilities)
|
570
555
|
|
571
556
|
if !opts.member?(:appium_lib) && flatten_ops.member?(:appium_lib)
|
572
557
|
raise Error::CapabilityStructureError, 'Please check the value of appium_lib in the capability'
|
@@ -587,8 +572,7 @@ module Appium
|
|
587
572
|
|
588
573
|
# @private
|
589
574
|
def get_caps(opts)
|
590
|
-
|
591
|
-
Core::Base::Capabilities.create_capabilities(opts[:caps] || opts[:capabilities] || opts[:desired_capabilities] || {})
|
575
|
+
Core::Base::Capabilities.create_capabilities(opts[:caps] || opts[:capabilities] || {})
|
592
576
|
end
|
593
577
|
|
594
578
|
# @private
|