appium_lib_core 4.1.0 → 5.0.0.rc6
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/.github/dependabot.yml +8 -0
- data/.github/workflows/unittest.yml +8 -9
- data/.rubocop.yml +89 -1
- data/CHANGELOG.md +64 -277
- data/README.md +7 -6
- data/Rakefile +4 -0
- data/appium_lib_core.gemspec +4 -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 +148 -128
- 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 +11 -4
- data/lib/appium_lib_core/common/base.rb +1 -3
- data/lib/appium_lib_core/common/command.rb +259 -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/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/touch_actions.rb +1 -1
- data/lib/appium_lib_core/common/wait.rb +42 -10
- data/lib/appium_lib_core/device.rb +1 -5
- data/lib/appium_lib_core/driver.rb +27 -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 +92 -0
- data/script/commands.rb +3 -37
- metadata +28 -28
- 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
@@ -19,10 +19,17 @@ module Appium
|
|
19
19
|
# @private
|
20
20
|
# @param [Hash] opts_caps Capabilities for Appium server. All capability keys are converted to lowerCamelCase when
|
21
21
|
# this client sends capabilities to Appium server as JSON format.
|
22
|
-
# @return [::Selenium::WebDriver::Remote::
|
23
|
-
# inherited ::Selenium::WebDriver::Remote::
|
22
|
+
# @return [::Selenium::WebDriver::Remote::Capabilities] Return instance of Appium::Core::Base::Capabilities
|
23
|
+
# inherited ::Selenium::WebDriver::Remote::Capabilities
|
24
24
|
def self.create_capabilities(opts_caps = {})
|
25
|
-
|
25
|
+
# TODO: Move to 'Options' way instead of 'Capabilities'.
|
26
|
+
# Selenium 5 will have Options instead of 'Capabilities'.
|
27
|
+
# https://github.com/SeleniumHQ/selenium/blob/trunk/rb/lib/selenium/webdriver/common/options.rb
|
28
|
+
# Then, Ruby client also shoud move to the Options way.
|
29
|
+
# Appium's capabilities could change by depending on Appium versions. So it does not have
|
30
|
+
# standard options like chrome and firefox etc. So, the implementation should differ from
|
31
|
+
# other browsers. But here should inherit `Options` to follow Selenium.
|
32
|
+
::Selenium::WebDriver::Remote::Capabilities.new(opts_caps)
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
class Base
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
class DeviceIME
|
22
|
+
# @private this class is private
|
23
|
+
def initialize(bridge)
|
24
|
+
@bridge = bridge
|
25
|
+
end
|
26
|
+
|
27
|
+
def activate(ime_name)
|
28
|
+
@bridge.ime_activate(ime_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def available_engines
|
32
|
+
@bridge.ime_available_engines
|
33
|
+
end
|
34
|
+
|
35
|
+
def active_engine
|
36
|
+
@bridge.ime_active_engine
|
37
|
+
end
|
38
|
+
|
39
|
+
def activated?
|
40
|
+
@bridge.ime_activated
|
41
|
+
end
|
42
|
+
|
43
|
+
def deactivate
|
44
|
+
@bridge.ime_deactivate
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -13,8 +13,15 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require 'base64'
|
16
|
+
require_relative 'device_ime'
|
17
|
+
require_relative 'driver_settings'
|
16
18
|
require_relative 'search_context'
|
17
19
|
require_relative 'screenshot'
|
20
|
+
require_relative 'rotable'
|
21
|
+
require_relative 'remote_status'
|
22
|
+
require_relative 'has_location'
|
23
|
+
require_relative 'has_network_connection'
|
24
|
+
require_relative '../wait'
|
18
25
|
|
19
26
|
module Appium
|
20
27
|
module Core
|
@@ -22,42 +29,49 @@ module Appium
|
|
22
29
|
class Driver < ::Selenium::WebDriver::Driver
|
23
30
|
include ::Selenium::WebDriver::DriverExtensions::UploadsFiles
|
24
31
|
include ::Selenium::WebDriver::DriverExtensions::HasSessionId
|
25
|
-
include ::Selenium::WebDriver::DriverExtensions::Rotatable
|
26
32
|
include ::Selenium::WebDriver::DriverExtensions::HasRemoteStatus
|
27
33
|
include ::Selenium::WebDriver::DriverExtensions::HasWebStorage
|
28
34
|
|
35
|
+
include ::Appium::Core::Base::Rotatable
|
29
36
|
include ::Appium::Core::Base::SearchContext
|
30
|
-
include ::Appium::Core::Base::
|
37
|
+
include ::Appium::Core::Base::TakesScreenshot
|
38
|
+
include ::Appium::Core::Base::HasRemoteStatus
|
39
|
+
include ::Appium::Core::Base::HasLocation
|
40
|
+
include ::Appium::Core::Base::HasNetworkConnection
|
41
|
+
|
42
|
+
include ::Appium::Core::Waitable
|
43
|
+
|
44
|
+
private
|
31
45
|
|
32
46
|
# Private API.
|
33
47
|
# Do not use this for general use. Used by flutter driver to get bridge for creating a new element
|
34
48
|
attr_reader :bridge
|
35
49
|
|
36
|
-
def initialize(
|
37
|
-
|
38
|
-
@bridge = ::Appium::Core::Base::Bridge.handshake(**opts)
|
39
|
-
if @bridge.dialect == :oss # MJSONWP
|
40
|
-
extend ::Selenium::WebDriver::DriverExtensions::HasTouchScreen
|
41
|
-
extend ::Selenium::WebDriver::DriverExtensions::HasLocation
|
42
|
-
extend ::Selenium::WebDriver::DriverExtensions::HasNetworkConnection
|
43
|
-
elsif @bridge.dialect == :w3c
|
44
|
-
# TODO: Only for Appium. Ideally, we'd like to remove the below like selenium-webdriver
|
45
|
-
extend ::Selenium::WebDriver::DriverExtensions::HasTouchScreen
|
46
|
-
extend ::Selenium::WebDriver::DriverExtensions::HasLocation
|
47
|
-
extend ::Selenium::WebDriver::DriverExtensions::HasNetworkConnection
|
48
|
-
end
|
49
|
-
super(@bridge, listener: listener)
|
50
|
+
def initialize(bridge: nil, listener: nil, **opts)
|
51
|
+
super
|
50
52
|
end
|
51
53
|
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
54
|
+
# Create a proper bridge instance.
|
55
|
+
#
|
56
|
+
# @return [::Appium::Core::Base::Bridge]
|
57
|
+
#
|
58
|
+
def create_bridge(**opts)
|
59
|
+
capabilities = opts.delete(:capabilities)
|
60
|
+
bridge_opts = { http_client: opts.delete(:http_client), url: opts.delete(:url) }
|
61
|
+
raise ::Appium::Core::Error::ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
|
62
|
+
|
63
|
+
bridge = ::Appium::Core::Base::Bridge.new(**bridge_opts)
|
64
|
+
|
65
|
+
bridge.create_session(capabilities)
|
66
|
+
bridge
|
56
67
|
end
|
57
68
|
|
69
|
+
public
|
70
|
+
|
58
71
|
# Update +server_url+ and HTTP clients following this arguments, protocol, host, port and path.
|
59
72
|
# After this method, +@bridge.http+ will be a new instance following them instead of +server_url+ which is
|
60
73
|
# set before creating session.
|
74
|
+
# If +@bridge.http+ did not have +update_sending_request_to+ method, this method returns immediately.
|
61
75
|
#
|
62
76
|
# @example
|
63
77
|
#
|
@@ -66,10 +80,95 @@ module Appium
|
|
66
80
|
# driver.manage.timeouts.implicit_wait = 10 # @bridge.http is for 'https://example2.com:9000/wd/hub/'
|
67
81
|
#
|
68
82
|
def update_sending_request_to(protocol:, host:, port:, path:)
|
69
|
-
@bridge.http
|
70
|
-
|
71
|
-
|
72
|
-
|
83
|
+
unless @bridge.http&.class&.method_defined? :update_sending_request_to
|
84
|
+
::Appium::Logger.warn "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
|
85
|
+
'It keeps current connection target.'
|
86
|
+
return
|
87
|
+
end
|
88
|
+
|
89
|
+
@bridge.http&.update_sending_request_to(scheme: protocol,
|
90
|
+
host: host,
|
91
|
+
port: port,
|
92
|
+
path: path)
|
93
|
+
end
|
94
|
+
|
95
|
+
AVAILABLE_METHODS = [
|
96
|
+
:get, :head, :post, :put, :delete,
|
97
|
+
:connect, :options, :trace, :patch
|
98
|
+
].freeze
|
99
|
+
# Define a new custom method to the driver so that you can define your own method for
|
100
|
+
# drivers/plugins in Appium 2.0. Appium 2.0 and its custom drivers/plugins allow you
|
101
|
+
# to define custom commands that are not part of W3C spec.
|
102
|
+
#
|
103
|
+
# @param [Symbol] method HTTP request method as https://www.w3.org/TR/webdriver/#endpoints
|
104
|
+
# @param [string] url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints.
|
105
|
+
# +:session_id+ is the placeholder of 'session id'.
|
106
|
+
# Other place holders can be specified with +:+ prefix like +:id+.
|
107
|
+
# Then, the +:id+ will be replaced with a given value as the seconds argument of +execute+
|
108
|
+
# @param [Symbol] name The name of method that is called as the driver instance method.
|
109
|
+
# @param [Proc] block The block to involve as the method.
|
110
|
+
# Please define a method that has the same +name+ with arguments you want.
|
111
|
+
# The method must has +execute+ method. tHe +execute+ is calls the +url+
|
112
|
+
# with the given parameters.
|
113
|
+
# The first argument should be +name+ as symbol.
|
114
|
+
# The second argument should be hash. If keys in the hash matches +:+ prefix
|
115
|
+
# string in the given url, the matched string in the given url will be
|
116
|
+
# values in the hash.
|
117
|
+
# The third argument should be hash. The hash will be the request body.
|
118
|
+
# Please read examples below for more details.
|
119
|
+
# @raise [ArgumentError] If the given +method+ is invalid value.
|
120
|
+
#
|
121
|
+
# @example
|
122
|
+
#
|
123
|
+
# @driver.add_command(
|
124
|
+
# method: :get,
|
125
|
+
# url: 'session/:session_id/path/to/custom/url',
|
126
|
+
# name: :test_command
|
127
|
+
# )
|
128
|
+
# # Send a GET request to 'session/<session id>/path/to/custom/url'
|
129
|
+
# @driver.test_command
|
130
|
+
#
|
131
|
+
#
|
132
|
+
# @driver.add_command(
|
133
|
+
# method: :post,
|
134
|
+
# url: 'session/:session_id/path/to/custom/url',
|
135
|
+
# name: :test_command
|
136
|
+
# ) do
|
137
|
+
# def test_command(argument)
|
138
|
+
# execute(:test_command, {}, { dummy: argument })
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
# # Send a POST request to 'session/<session id>/path/to/custom/url'
|
142
|
+
# # with body "{ dummy: 1 }" as JSON object. "1" is the argument.
|
143
|
+
# # ':session_id' in the given 'url' is replaced with current 'session id'.
|
144
|
+
# @driver.test_command(1)
|
145
|
+
#
|
146
|
+
#
|
147
|
+
# @driver.add_command(
|
148
|
+
# method: :post,
|
149
|
+
# url: 'session/:session_id/element/:id/custom/action',
|
150
|
+
# name: :test_action_command
|
151
|
+
# ) do
|
152
|
+
# def test_action_command(element_id, action)
|
153
|
+
# execute(:test_action_command, {id: element_id}, { dummy_action: action })
|
154
|
+
# end
|
155
|
+
# end
|
156
|
+
# # Send a POST request to 'session/<session id>/element/<element id>/custom/action'
|
157
|
+
# # with body "{ dummy_action: #{action} }" as JSON object. "action" is the seconds argument.
|
158
|
+
# # ':session_id' in the given url is replaced with current 'session id'.
|
159
|
+
# # ':id' in the given url is replaced with the given 'element_id'.
|
160
|
+
# e = @driver.find_element :accessibility_id, 'an element'
|
161
|
+
# @driver.test_action_command(e.id, 'action')
|
162
|
+
#
|
163
|
+
def add_command(method:, url:, name:, &block)
|
164
|
+
unless AVAILABLE_METHODS.include? method
|
165
|
+
raise ::Appium::Core::Error::ArgumentError, "Available method is either #{AVAILABLE_METHODS}"
|
166
|
+
end
|
167
|
+
|
168
|
+
# TODO: Remove this logger before Appium 2.0 release
|
169
|
+
::Appium::Logger.info '[Experimental] this method is experimental for Appium 2.0. This interface may change.'
|
170
|
+
|
171
|
+
@bridge.add_command method: method, url: url, name: name, &block
|
73
172
|
end
|
74
173
|
|
75
174
|
### Methods for Appium
|
@@ -138,38 +237,6 @@ module Appium
|
|
138
237
|
end
|
139
238
|
alias is_keyboard_shown keyboard_shown?
|
140
239
|
|
141
|
-
# [DEPRECATION]
|
142
|
-
# Send keys for a current active element
|
143
|
-
# @param [String] key Input text
|
144
|
-
#
|
145
|
-
# @example
|
146
|
-
#
|
147
|
-
# @driver.send_keys 'happy testing!'
|
148
|
-
#
|
149
|
-
def send_keys(*key)
|
150
|
-
::Appium::Logger.warn(
|
151
|
-
'[DEPRECATION] Driver#send_keys is deprecated in W3C spec. Use driver.action.<command>.perform instead'
|
152
|
-
)
|
153
|
-
@bridge.send_keys_to_active_element(key)
|
154
|
-
end
|
155
|
-
alias type send_keys
|
156
|
-
|
157
|
-
class DriverSettings
|
158
|
-
# @private this class is private
|
159
|
-
def initialize(bridge)
|
160
|
-
@bridge = bridge
|
161
|
-
end
|
162
|
-
|
163
|
-
def get
|
164
|
-
@bridge.get_settings
|
165
|
-
end
|
166
|
-
|
167
|
-
def update(settings)
|
168
|
-
@bridge.update_settings(settings)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
private_constant :DriverSettings
|
172
|
-
|
173
240
|
# Returns an instance of DriverSettings to call get/update.
|
174
241
|
#
|
175
242
|
# @example
|
@@ -178,7 +245,7 @@ module Appium
|
|
178
245
|
# @driver.settings.update('allowInvisibleElements': true)
|
179
246
|
#
|
180
247
|
def settings
|
181
|
-
@
|
248
|
+
@settings ||= DriverSettings.new(@bridge)
|
182
249
|
end
|
183
250
|
|
184
251
|
# Get appium Settings for current test session.
|
@@ -200,8 +267,8 @@ module Appium
|
|
200
267
|
#
|
201
268
|
# @example
|
202
269
|
#
|
203
|
-
# @driver.update_settings('allowInvisibleElements': true)
|
204
|
-
# @driver.settings.update('allowInvisibleElements': true)
|
270
|
+
# @driver.update_settings({ 'allowInvisibleElements': true })
|
271
|
+
# @driver.settings.update({ 'allowInvisibleElements': true })
|
205
272
|
# @driver.settings = { 'allowInvisibleElements': true }
|
206
273
|
#
|
207
274
|
def settings=(value)
|
@@ -209,36 +276,10 @@ module Appium
|
|
209
276
|
end
|
210
277
|
alias update_settings settings=
|
211
278
|
|
212
|
-
class DeviceIME
|
213
|
-
# @private this class is private
|
214
|
-
def initialize(bridge)
|
215
|
-
@bridge = bridge
|
216
|
-
end
|
217
|
-
|
218
|
-
def activate(ime_name)
|
219
|
-
@bridge.ime_activate(ime_name)
|
220
|
-
end
|
221
|
-
|
222
|
-
def available_engines
|
223
|
-
@bridge.ime_available_engines
|
224
|
-
end
|
225
|
-
|
226
|
-
def active_engine
|
227
|
-
@bridge.ime_active_engine
|
228
|
-
end
|
229
|
-
|
230
|
-
def activated?
|
231
|
-
@bridge.ime_activated
|
232
|
-
end
|
233
|
-
|
234
|
-
def deactivate
|
235
|
-
@bridge.ime_deactivate
|
236
|
-
end
|
237
|
-
end
|
238
|
-
private_constant :DeviceIME
|
239
|
-
|
240
279
|
# Returns an instance of DeviceIME
|
241
280
|
#
|
281
|
+
# @return [Appium::Core::Base::Driver::DeviceIME]
|
282
|
+
#
|
242
283
|
# @example
|
243
284
|
#
|
244
285
|
# @driver.ime.activate engine: 'com.android.inputmethod.latin/.LatinIME'
|
@@ -248,7 +289,7 @@ module Appium
|
|
248
289
|
# @driver.ime.deactivate #=> Deactivate current IME engine
|
249
290
|
#
|
250
291
|
def ime
|
251
|
-
@
|
292
|
+
@ime ||= DeviceIME.new(@bridge)
|
252
293
|
end
|
253
294
|
|
254
295
|
# Android only. Make an engine that is available active.
|
@@ -289,6 +330,8 @@ module Appium
|
|
289
330
|
# @!method ime_activated
|
290
331
|
# Android only. Indicates whether IME input is active at the moment (not if it is available).
|
291
332
|
#
|
333
|
+
# @return [Boolean]
|
334
|
+
#
|
292
335
|
# @example
|
293
336
|
#
|
294
337
|
# @driver.ime_activated #=> True if IME is activated
|
@@ -366,30 +409,6 @@ module Appium
|
|
366
409
|
end
|
367
410
|
alias set_context context=
|
368
411
|
|
369
|
-
# Set the value to element directly
|
370
|
-
#
|
371
|
-
# @example
|
372
|
-
#
|
373
|
-
# @driver.set_immediate_value element, 'hello'
|
374
|
-
#
|
375
|
-
def set_immediate_value(element, *value)
|
376
|
-
::Appium::Logger.warn '[DEPRECATION] driver#set_immediate_value(element, *value) is deprecated. ' \
|
377
|
-
'Use Element#immediate_value(*value) instead'
|
378
|
-
@bridge.set_immediate_value(element, *value)
|
379
|
-
end
|
380
|
-
|
381
|
-
# Replace the value to element directly
|
382
|
-
#
|
383
|
-
# @example
|
384
|
-
#
|
385
|
-
# @driver.replace_value element, 'hello'
|
386
|
-
#
|
387
|
-
def replace_value(element, *value)
|
388
|
-
::Appium::Logger.warn '[DEPRECATION] driver#replace_value(element, *value) is deprecated. ' \
|
389
|
-
'Use Element#replace_value(*value) instead'
|
390
|
-
@bridge.replace_value(element, *value)
|
391
|
-
end
|
392
|
-
|
393
412
|
# Place a file in a specific location on the device.
|
394
413
|
# On iOS, the server should have ifuse libraries installed and configured properly for this feature to work on
|
395
414
|
# real devices.
|
@@ -809,7 +828,7 @@ module Appium
|
|
809
828
|
# @driver.perform_actions [f1, f2] #=> 'nil' if the action succeed
|
810
829
|
#
|
811
830
|
def perform_actions(data)
|
812
|
-
raise ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
|
831
|
+
raise ::Appium::Core::Error::ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
|
813
832
|
|
814
833
|
@bridge.send_actions data.map(&:encode).compact
|
815
834
|
data.each(&:clear_actions)
|
@@ -853,7 +872,7 @@ module Appium
|
|
853
872
|
end
|
854
873
|
|
855
874
|
# Get the device window's logs.
|
856
|
-
# @return [
|
875
|
+
# @return [Appium::Core::Logs]
|
857
876
|
#
|
858
877
|
# @example
|
859
878
|
#
|
@@ -879,16 +898,15 @@ module Appium
|
|
879
898
|
# Retrieve the capabilities of the specified session.
|
880
899
|
# It's almost same as +@driver.capabilities+ but you can get more details.
|
881
900
|
#
|
882
|
-
# @return [Selenium::WebDriver::Remote::Capabilities]
|
901
|
+
# @return [Selenium::WebDriver::Remote::Capabilities, Selenium::WebDriver::Remote::Capabilities]
|
883
902
|
#
|
884
903
|
# @example
|
885
904
|
# @driver.session_capabilities
|
886
905
|
#
|
887
906
|
# #=> uiautomator2
|
888
|
-
# # <Selenium::WebDriver::Remote::
|
907
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fa38dae1360
|
889
908
|
# # @capabilities=
|
890
|
-
# # {:
|
891
|
-
# # :browser_name=>nil,
|
909
|
+
# # {:browser_name=>nil,
|
892
910
|
# # :browser_version=>nil,
|
893
911
|
# # :platform_name=>"android",
|
894
912
|
# # :page_load_strategy=>nil,
|
@@ -935,10 +953,9 @@ module Appium
|
|
935
953
|
# # "viewportRect"=>{"left"=>0, "top"=>63, "width"=>1080, "height"=>1731}}>
|
936
954
|
# #
|
937
955
|
# #=> XCUITest
|
938
|
-
# # <Selenium::WebDriver::Remote::
|
956
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fb15dc01370
|
939
957
|
# # @capabilities=
|
940
|
-
# # {:
|
941
|
-
# # :browser_name=>"UICatalog",
|
958
|
+
# # {:browser_name=>"UICatalog",
|
942
959
|
# # :browser_version=>nil,
|
943
960
|
# # :platform_name=>"ios",
|
944
961
|
# # :page_load_strategy=>nil,
|
@@ -992,11 +1009,14 @@ module Appium
|
|
992
1009
|
visualize: visualize)
|
993
1010
|
end
|
994
1011
|
|
995
|
-
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil
|
1012
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
|
1013
|
+
multiple: nil, match_neighbour_threshold: nil)
|
996
1014
|
@bridge.find_image_occurrence(full_image: full_image,
|
997
1015
|
partial_image: partial_image,
|
998
1016
|
visualize: visualize,
|
999
|
-
threshold: threshold
|
1017
|
+
threshold: threshold,
|
1018
|
+
multiple: multiple,
|
1019
|
+
match_neighbour_threshold: match_neighbour_threshold)
|
1000
1020
|
end
|
1001
1021
|
|
1002
1022
|
def get_images_similarity(first_image:, second_image:, visualize: false)
|
@@ -1016,7 +1036,7 @@ module Appium
|
|
1016
1036
|
#
|
1017
1037
|
# @param [String] img_path A path to a partial image you'd like to find
|
1018
1038
|
#
|
1019
|
-
# @return [::
|
1039
|
+
# @return [::Appium::Core::Element]
|
1020
1040
|
#
|
1021
1041
|
# @example
|
1022
1042
|
#
|
@@ -1038,7 +1058,7 @@ module Appium
|
|
1038
1058
|
#
|
1039
1059
|
# @param [String] img_path A path to a partial image you'd like to find
|
1040
1060
|
#
|
1041
|
-
# @return [
|
1061
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
1042
1062
|
#
|
1043
1063
|
# @example
|
1044
1064
|
#
|
@@ -1086,14 +1106,14 @@ module Appium
|
|
1086
1106
|
@bridge.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
|
1087
1107
|
end
|
1088
1108
|
|
1089
|
-
# Convert vanilla element response to ::
|
1109
|
+
# Convert vanilla element response to ::Appium::Core::Element
|
1090
1110
|
#
|
1091
1111
|
# @param [Hash] id The id which can get as a response from server
|
1092
|
-
# @return [::
|
1112
|
+
# @return [::Appium::Core::Element]
|
1093
1113
|
#
|
1094
1114
|
# @example
|
1095
1115
|
# response = {"element-6066-11e4-a52e-4f735466cecf"=>"xxxx", "ELEMENT"=>"xxxx"}
|
1096
|
-
# ele = @driver.convert_to_element(response) #=> ::
|
1116
|
+
# ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
|
1097
1117
|
# ele.rect #=> Can get the rect of the element
|
1098
1118
|
#
|
1099
1119
|
def convert_to_element(id)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
class Base
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
class DriverSettings
|
22
|
+
# @private this class is private
|
23
|
+
def initialize(bridge)
|
24
|
+
@bridge = bridge
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get appium Settings for current test session.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
#
|
31
|
+
# @driver.settings.get
|
32
|
+
#
|
33
|
+
def get
|
34
|
+
@bridge.get_settings
|
35
|
+
end
|
36
|
+
|
37
|
+
# Update Appium Settings for current test session
|
38
|
+
#
|
39
|
+
# @param [Hash] settings Settings to update, keys are settings, values to value to set each setting to
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
#
|
43
|
+
# @driver.settings.update({'allowInvisibleElements': true})
|
44
|
+
#
|
45
|
+
def update(settings)
|
46
|
+
@bridge.update_settings(settings)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
class Base
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
module HasLocation
|
22
|
+
# Get the location of the device.
|
23
|
+
#
|
24
|
+
# @return [::Selenium::WebDriver::Location]
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
#
|
28
|
+
# driver.location #=> ::Selenium::WebDriver::Location.new(10, 10, 10)
|
29
|
+
#
|
30
|
+
def location
|
31
|
+
@bridge.location
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set the location of the device.
|
35
|
+
#
|
36
|
+
# @param [::Selenium::WebDriver::Location] location Set the location.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
#
|
40
|
+
# driver.location = ::Selenium::WebDriver::Location.new(10, 10, 10)
|
41
|
+
#
|
42
|
+
def location=(location)
|
43
|
+
unless location.is_a?(::Selenium::WebDriver::Location)
|
44
|
+
raise TypeError, "expected #{::Selenium::WebDriver::Location}, got #{location.inspect}:#{location.class}"
|
45
|
+
end
|
46
|
+
|
47
|
+
@bridge.set_location location.latitude, location.longitude, location.altitude
|
48
|
+
end
|
49
|
+
|
50
|
+
# Set the location of the device.
|
51
|
+
#
|
52
|
+
# @param [String, Number] latitude Set the latitude.
|
53
|
+
# @param [String, Number] longitude Set the longitude.
|
54
|
+
# @param [String, Number] altitude Set the altitude.
|
55
|
+
# @param [String, Number] speed Set the speed to apply the location on Android real devices
|
56
|
+
# in meters/second @since Appium 1.21.0 and in knots for emulators @since Appium 1.22.0.
|
57
|
+
# @param [String, Number] satellites Sets the count of geo satellites being tracked in range 1..12 @since Appium 1.22.0.
|
58
|
+
# This number is respected on Emulators.
|
59
|
+
# @param [::Selenium::WebDriver::Location]
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
#
|
63
|
+
# driver.location = ::Selenium::WebDriver::Location.new(10, 10, 10)
|
64
|
+
#
|
65
|
+
def set_location(latitude, longitude, altitude, speed: nil, satellites: nil)
|
66
|
+
if speed.nil? && satellites.nil?
|
67
|
+
self.location = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
|
68
|
+
else
|
69
|
+
loc = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
|
70
|
+
|
71
|
+
speed = Float(speed) unless speed.nil?
|
72
|
+
satellites = Integer(satellites) unless satellites.nil?
|
73
|
+
|
74
|
+
@bridge.set_location loc.latitude, loc.longitude, loc.altitude, speed: speed, satellites: satellites
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
class Base
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
module HasNetworkConnection
|
22
|
+
def network_connection_type
|
23
|
+
connection_value = @bridge.network_connection
|
24
|
+
|
25
|
+
connection_type = values_to_type[connection_value]
|
26
|
+
|
27
|
+
# In case the connection type is not recognized return the
|
28
|
+
# connection value.
|
29
|
+
connection_type || connection_value
|
30
|
+
end
|
31
|
+
|
32
|
+
def network_connection_type=(connection_type)
|
33
|
+
raise ::Appium::Core::Error::ArgumentError, 'Invalid connection type' unless valid_type? connection_type
|
34
|
+
|
35
|
+
connection_value = type_to_values[connection_type]
|
36
|
+
|
37
|
+
@bridge.network_connection = connection_value
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def type_to_values
|
43
|
+
{ airplane_mode: 1, wifi: 2, data: 4, all: 6, none: 0 }
|
44
|
+
end
|
45
|
+
|
46
|
+
def values_to_type
|
47
|
+
type_to_values.invert
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid_type?(type)
|
51
|
+
type_to_values.keys.include? type
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|