appium_lib_core 4.1.0 → 6.2.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/CHANGELOG.md +207 -272
- data/README.md +41 -14
- data/Rakefile +4 -0
- data/appium_lib_core.gemspec +5 -8
- data/bin/console +0 -4
- 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 +311 -90
- data/lib/appium_lib_core/common/base/capabilities.rb +8 -9
- data/lib/appium_lib_core/common/base/device_ime.rb +49 -0
- data/lib/appium_lib_core/common/base/driver.rb +222 -187
- 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/{ios/uiautomation/bridge.rb → common/base/remote_status.rb} +9 -8
- 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 +20 -6
- 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/app_management.rb +8 -14
- 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 -8
- data/lib/appium_lib_core/common/error.rb +4 -5
- 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 +177 -102
- data/lib/appium_lib_core/{patch.rb → element.rb} +66 -9
- 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/{ios.rb → mac2.rb} +2 -5
- data/lib/appium_lib_core/version.rb +2 -2
- data/lib/appium_lib_core/windows/device/app_management.rb +38 -0
- data/lib/appium_lib_core/windows/device.rb +2 -0
- data/lib/appium_lib_core.rb +20 -10
- metadata +27 -83
- data/.github/ISSUE_TEMPLATE/issue-report.md +0 -29
- data/.github/contributing.md +0 -26
- data/.github/issue_template.md +0 -20
- data/.github/workflows/unittest.yml +0 -68
- data/.gitignore +0 -18
- data/.rubocop.yml +0 -58
- data/azure-pipelines.yml +0 -15
- data/ci-jobs/functional/android_setup.yml +0 -3
- data/ci-jobs/functional/ios_setup.yml +0 -7
- data/ci-jobs/functional/publish_test_result.yml +0 -18
- data/ci-jobs/functional/run_appium.yml +0 -25
- data/ci-jobs/functional/start-emulator.sh +0 -26
- data/ci-jobs/functional_test.yml +0 -298
- data/docs/mobile_command.md +0 -34
- 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
- data/lib/appium_lib_core/ios/uiautomation/device.rb +0 -44
- data/lib/appium_lib_core/ios/uiautomation/patch.rb +0 -34
- data/release_notes.md +0 -816
- data/script/commands.rb +0 -200
@@ -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,65 @@ 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
|
-
include ::Selenium::WebDriver::DriverExtensions::HasRemoteStatus
|
27
32
|
include ::Selenium::WebDriver::DriverExtensions::HasWebStorage
|
28
33
|
|
34
|
+
include ::Appium::Core::Base::Rotatable
|
29
35
|
include ::Appium::Core::Base::SearchContext
|
30
|
-
include ::Appium::Core::Base::
|
36
|
+
include ::Appium::Core::Base::TakesScreenshot
|
37
|
+
include ::Appium::Core::Base::HasRemoteStatus
|
38
|
+
include ::Appium::Core::Base::HasLocation
|
39
|
+
include ::Appium::Core::Base::HasNetworkConnection
|
40
|
+
|
41
|
+
include ::Appium::Core::Waitable
|
31
42
|
|
32
43
|
# Private API.
|
33
44
|
# Do not use this for general use. Used by flutter driver to get bridge for creating a new element
|
34
45
|
attr_reader :bridge
|
35
46
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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)
|
47
|
+
private
|
48
|
+
|
49
|
+
def initialize(bridge: nil, listener: nil, **opts)
|
50
|
+
# For ::Appium::Core::Waitable
|
51
|
+
@wait_timeout = opts.delete(:wait_timeout)
|
52
|
+
@wait_interval = opts.delete(:wait_interval)
|
53
|
+
|
54
|
+
super
|
50
55
|
end
|
51
56
|
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
57
|
+
# Create a proper bridge instance.
|
58
|
+
#
|
59
|
+
# @return [::Appium::Core::Base::Bridge]
|
60
|
+
#
|
61
|
+
def create_bridge(**opts)
|
62
|
+
# for a new session request
|
63
|
+
capabilities = opts.delete(:capabilities)
|
64
|
+
bridge_opts = { http_client: opts.delete(:http_client), url: opts.delete(:url) }
|
65
|
+
|
66
|
+
# for attaching to an existing session
|
67
|
+
session_id = opts.delete(:existing_session_id)
|
68
|
+
automation_name = opts.delete(:automation_name)
|
69
|
+
platform_name = opts.delete(:platform_name)
|
70
|
+
|
71
|
+
raise ::Appium::Core::Error::ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
|
72
|
+
|
73
|
+
bridge = ::Appium::Core::Base::Bridge.new(**bridge_opts)
|
74
|
+
|
75
|
+
if session_id.nil?
|
76
|
+
bridge.create_session(capabilities)
|
77
|
+
else
|
78
|
+
# attach to the existing session id
|
79
|
+
bridge.attach_to(session_id, platform_name, automation_name)
|
80
|
+
end
|
81
|
+
|
82
|
+
bridge
|
56
83
|
end
|
57
84
|
|
85
|
+
public
|
86
|
+
|
58
87
|
# Update +server_url+ and HTTP clients following this arguments, protocol, host, port and path.
|
59
88
|
# After this method, +@bridge.http+ will be a new instance following them instead of +server_url+ which is
|
60
89
|
# set before creating session.
|
90
|
+
# If +@bridge.http+ did not have +update_sending_request_to+ method, this method returns immediately.
|
61
91
|
#
|
62
92
|
# @example
|
63
93
|
#
|
@@ -66,14 +96,124 @@ module Appium
|
|
66
96
|
# driver.manage.timeouts.implicit_wait = 10 # @bridge.http is for 'https://example2.com:9000/wd/hub/'
|
67
97
|
#
|
68
98
|
def update_sending_request_to(protocol:, host:, port:, path:)
|
69
|
-
@bridge.http
|
70
|
-
|
71
|
-
|
72
|
-
|
99
|
+
unless @bridge.http&.class&.method_defined? :update_sending_request_to
|
100
|
+
::Appium::Logger.warn "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
|
101
|
+
'It keeps current connection target.'
|
102
|
+
return
|
103
|
+
end
|
104
|
+
|
105
|
+
@bridge.http&.update_sending_request_to(scheme: protocol,
|
106
|
+
host: host,
|
107
|
+
port: port,
|
108
|
+
path: path)
|
109
|
+
end
|
110
|
+
|
111
|
+
AVAILABLE_METHODS = [
|
112
|
+
:get, :head, :post, :put, :delete,
|
113
|
+
:connect, :options, :trace, :patch
|
114
|
+
].freeze
|
115
|
+
# Define a new custom method to the driver so that you can define your own method for
|
116
|
+
# drivers/plugins in Appium 2.0. Appium 2.0 and its custom drivers/plugins allow you
|
117
|
+
# to define custom commands that are not part of W3C spec.
|
118
|
+
#
|
119
|
+
# @param [Symbol] method HTTP request method as https://www.w3.org/TR/webdriver/#endpoints
|
120
|
+
# @param [string] url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints.
|
121
|
+
# +:session_id+ is the placeholder of 'session id'.
|
122
|
+
# Other place holders can be specified with +:+ prefix like +:id+.
|
123
|
+
# Then, the +:id+ will be replaced with a given value as the seconds argument of +execute+
|
124
|
+
# @param [Symbol] name The name of method that is called as the driver instance method.
|
125
|
+
# @param [Proc] block The block to involve as the method.
|
126
|
+
# Please define a method that has the same +name+ with arguments you want.
|
127
|
+
# The method must has +execute+ method. tHe +execute+ is calls the +url+
|
128
|
+
# with the given parameters.
|
129
|
+
# The first argument should be +name+ as symbol.
|
130
|
+
# The second argument should be hash. If keys in the hash matches +:+ prefix
|
131
|
+
# string in the given url, the matched string in the given url will be
|
132
|
+
# values in the hash.
|
133
|
+
# The third argument should be hash. The hash will be the request body.
|
134
|
+
# Please read examples below for more details.
|
135
|
+
# @raise [ArgumentError] If the given +method+ is invalid value.
|
136
|
+
#
|
137
|
+
# @example
|
138
|
+
#
|
139
|
+
# @driver.add_command(
|
140
|
+
# method: :get,
|
141
|
+
# url: 'session/:session_id/path/to/custom/url',
|
142
|
+
# name: :test_command
|
143
|
+
# )
|
144
|
+
# # Send a GET request to 'session/<session id>/path/to/custom/url'
|
145
|
+
# @driver.test_command
|
146
|
+
#
|
147
|
+
#
|
148
|
+
# @driver.add_command(
|
149
|
+
# method: :post,
|
150
|
+
# url: 'session/:session_id/path/to/custom/url',
|
151
|
+
# name: :test_command
|
152
|
+
# ) do
|
153
|
+
# def test_command(argument)
|
154
|
+
# execute(:test_command, {}, { dummy: argument })
|
155
|
+
# end
|
156
|
+
# end
|
157
|
+
# # Send a POST request to 'session/<session id>/path/to/custom/url'
|
158
|
+
# # with body "{ dummy: 1 }" as JSON object. "1" is the argument.
|
159
|
+
# # ':session_id' in the given 'url' is replaced with current 'session id'.
|
160
|
+
# @driver.test_command(1)
|
161
|
+
#
|
162
|
+
#
|
163
|
+
# @driver.add_command(
|
164
|
+
# method: :post,
|
165
|
+
# url: 'session/:session_id/element/:id/custom/action',
|
166
|
+
# name: :test_action_command
|
167
|
+
# ) do
|
168
|
+
# def test_action_command(element_id, action)
|
169
|
+
# execute(:test_action_command, {id: element_id}, { dummy_action: action })
|
170
|
+
# end
|
171
|
+
# end
|
172
|
+
# # Send a POST request to 'session/<session id>/element/<element id>/custom/action'
|
173
|
+
# # with body "{ dummy_action: #{action} }" as JSON object. "action" is the seconds argument.
|
174
|
+
# # ':session_id' in the given url is replaced with current 'session id'.
|
175
|
+
# # ':id' in the given url is replaced with the given 'element_id'.
|
176
|
+
# e = @driver.find_element :accessibility_id, 'an element'
|
177
|
+
# @driver.test_action_command(e.id, 'action')
|
178
|
+
#
|
179
|
+
def add_command(method:, url:, name:, &block)
|
180
|
+
unless AVAILABLE_METHODS.include? method
|
181
|
+
raise ::Appium::Core::Error::ArgumentError, "Available method is either #{AVAILABLE_METHODS}"
|
182
|
+
end
|
183
|
+
|
184
|
+
# TODO: Remove this logger before Appium 2.0 release
|
185
|
+
::Appium::Logger.info '[Experimental] this method is experimental for Appium 2.0. This interface may change.'
|
186
|
+
|
187
|
+
@bridge.add_command method: method, url: url, name: name, &block
|
73
188
|
end
|
74
189
|
|
75
190
|
### Methods for Appium
|
76
191
|
|
192
|
+
# Perform 'key' actions for W3C module.
|
193
|
+
# Generate +key+ pointer action here and users can use this via +driver.key_action+
|
194
|
+
# - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/W3CActionBuilder.html
|
195
|
+
# - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/KeyActions.html
|
196
|
+
#
|
197
|
+
# The pointer type is 'key' by default in the Appium Ruby client.
|
198
|
+
# +driver.action+ in Appium Ruby client has 'pointer' action by default.
|
199
|
+
# This method is a shortcut to set 'key' type.
|
200
|
+
# Hense this method is equal to +driver.action(devices: [::Selenium::WebDriver::Interactions.key('keyboard')])+
|
201
|
+
# as below example.
|
202
|
+
#
|
203
|
+
# @example
|
204
|
+
#
|
205
|
+
# element = @driver.find_element(:id, "some id")
|
206
|
+
# @driver.key_action.send_key('hiあ').perform # The 'send_key' is a part of 'KeyActions'
|
207
|
+
# # is equal to:
|
208
|
+
# # @driver.action(devices: [::Selenium::WebDriver::Interactions.key('keyboard')]).send_keys('hiあ').perform
|
209
|
+
#
|
210
|
+
def key_action(async: false)
|
211
|
+
@bridge.action(
|
212
|
+
async: async,
|
213
|
+
devices: [::Selenium::WebDriver::Interactions.key('keyboard')]
|
214
|
+
)
|
215
|
+
end
|
216
|
+
|
77
217
|
# Lock the device
|
78
218
|
# @return [String]
|
79
219
|
#
|
@@ -138,38 +278,6 @@ module Appium
|
|
138
278
|
end
|
139
279
|
alias is_keyboard_shown keyboard_shown?
|
140
280
|
|
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
281
|
# Returns an instance of DriverSettings to call get/update.
|
174
282
|
#
|
175
283
|
# @example
|
@@ -178,7 +286,7 @@ module Appium
|
|
178
286
|
# @driver.settings.update('allowInvisibleElements': true)
|
179
287
|
#
|
180
288
|
def settings
|
181
|
-
@
|
289
|
+
@settings ||= DriverSettings.new(@bridge)
|
182
290
|
end
|
183
291
|
|
184
292
|
# Get appium Settings for current test session.
|
@@ -200,8 +308,8 @@ module Appium
|
|
200
308
|
#
|
201
309
|
# @example
|
202
310
|
#
|
203
|
-
# @driver.update_settings('allowInvisibleElements': true)
|
204
|
-
# @driver.settings.update('allowInvisibleElements': true)
|
311
|
+
# @driver.update_settings({ 'allowInvisibleElements': true })
|
312
|
+
# @driver.settings.update({ 'allowInvisibleElements': true })
|
205
313
|
# @driver.settings = { 'allowInvisibleElements': true }
|
206
314
|
#
|
207
315
|
def settings=(value)
|
@@ -209,36 +317,10 @@ module Appium
|
|
209
317
|
end
|
210
318
|
alias update_settings settings=
|
211
319
|
|
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
320
|
# Returns an instance of DeviceIME
|
241
321
|
#
|
322
|
+
# @return [Appium::Core::Base::Driver::DeviceIME]
|
323
|
+
#
|
242
324
|
# @example
|
243
325
|
#
|
244
326
|
# @driver.ime.activate engine: 'com.android.inputmethod.latin/.LatinIME'
|
@@ -248,7 +330,7 @@ module Appium
|
|
248
330
|
# @driver.ime.deactivate #=> Deactivate current IME engine
|
249
331
|
#
|
250
332
|
def ime
|
251
|
-
@
|
333
|
+
@ime ||= DeviceIME.new(@bridge)
|
252
334
|
end
|
253
335
|
|
254
336
|
# Android only. Make an engine that is available active.
|
@@ -289,6 +371,8 @@ module Appium
|
|
289
371
|
# @!method ime_activated
|
290
372
|
# Android only. Indicates whether IME input is active at the moment (not if it is available).
|
291
373
|
#
|
374
|
+
# @return [Boolean]
|
375
|
+
#
|
292
376
|
# @example
|
293
377
|
#
|
294
378
|
# @driver.ime_activated #=> True if IME is activated
|
@@ -366,42 +450,10 @@ module Appium
|
|
366
450
|
end
|
367
451
|
alias set_context context=
|
368
452
|
|
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
453
|
# Place a file in a specific location on the device.
|
394
|
-
# On iOS, the server should have ifuse libraries installed and configured properly for this feature to work on
|
395
|
-
# real devices.
|
396
454
|
# On Android, the application under test should be built with debuggable flag enabled in order to get access to
|
397
455
|
# its container on the internal file system.
|
398
456
|
#
|
399
|
-
# {https://github.com/libimobiledevice/ifuse iFuse GitHub page6}
|
400
|
-
#
|
401
|
-
# {https://github.com/osxfuse/osxfuse/wiki/FAQ osxFuse FAQ}
|
402
|
-
#
|
403
|
-
# {https://developer.android.com/studio/debug 'Debug Your App' developer article}
|
404
|
-
#
|
405
457
|
# @param [String] path Either an absolute path OR, for iOS devices, a path relative to the app, as described.
|
406
458
|
# If the path starts with application id prefix, then the file will be pushed to the root of
|
407
459
|
# the corresponding application container.
|
@@ -418,18 +470,10 @@ module Appium
|
|
418
470
|
@bridge.push_file(path, filedata)
|
419
471
|
end
|
420
472
|
|
421
|
-
# Pull a file from the
|
422
|
-
# On iOS the server should have ifuse
|
423
|
-
# libraries installed and configured properly for this feature to work on real devices.
|
473
|
+
# Pull a file from the remote device.
|
424
474
|
# On Android the application under test should be built with debuggable flag enabled in order to get access
|
425
475
|
# to its container on the internal file system.
|
426
476
|
#
|
427
|
-
# {https://github.com/libimobiledevice/ifuse iFuse GitHub page6}
|
428
|
-
#
|
429
|
-
# {https://github.com/osxfuse/osxfuse/wiki/FAQ osxFuse FAQ}
|
430
|
-
#
|
431
|
-
# {https://developer.android.com/studio/debug 'Debug Your App' developer article}
|
432
|
-
#
|
433
477
|
# @param [String] path Either an absolute path OR, for iOS devices, a path relative to the app, as described.
|
434
478
|
# If the path starts with application id prefix, then the file will be pulled from the root
|
435
479
|
# of the corresponding application container.
|
@@ -438,7 +482,6 @@ module Appium
|
|
438
482
|
# Only pulling files from application containers is supported for iOS Simulator.
|
439
483
|
# Provide the remote path in format
|
440
484
|
# <code>@bundle.identifier:container_type/relative_path_in_container</code>
|
441
|
-
# (Make sure this in ifuse doc)
|
442
485
|
#
|
443
486
|
# @return [Base64-decoded] Base64 decoded data
|
444
487
|
#
|
@@ -455,18 +498,10 @@ module Appium
|
|
455
498
|
@bridge.pull_file(path)
|
456
499
|
end
|
457
500
|
|
458
|
-
# Pull a folder content from the
|
459
|
-
# On iOS the server should have ifuse libraries installed and configured properly for this feature to work
|
460
|
-
# on real devices.
|
501
|
+
# Pull a folder content from the remote device.
|
461
502
|
# On Android the application under test should be built with debuggable flag enabled in order to get access to
|
462
503
|
# its container on the internal file system.
|
463
504
|
#
|
464
|
-
# {https://github.com/libimobiledevice/ifuse iFuse GitHub page6}
|
465
|
-
#
|
466
|
-
# {https://github.com/osxfuse/osxfuse/wiki/FAQ osxFuse FAQ}
|
467
|
-
#
|
468
|
-
# {https://developer.android.com/studio/debug 'Debug Your App' developer article}
|
469
|
-
#
|
470
505
|
# @param [String] path Absolute path to the folder.
|
471
506
|
# If the path starts with <em>@applicationId/</em> prefix, then the folder will be pulled
|
472
507
|
# from the root of the corresponding application container.
|
@@ -475,7 +510,6 @@ module Appium
|
|
475
510
|
# Only pulling files from application containers is supported for iOS Simulator.
|
476
511
|
# Provide the remote path in format
|
477
512
|
# <code>@bundle.identifier:container_type/relative_path_in_container</code>
|
478
|
-
# (Make sure this in ifuse doc)
|
479
513
|
#
|
480
514
|
# @return [Base64-decoded] Base64 decoded data which is zip archived
|
481
515
|
#
|
@@ -489,19 +523,6 @@ module Appium
|
|
489
523
|
@bridge.pull_folder(path)
|
490
524
|
end
|
491
525
|
|
492
|
-
# Send keyevent on the device.(Only for Selendroid)
|
493
|
-
# http://developer.android.com/reference/android/view/KeyEvent.html
|
494
|
-
# @param [integer] key The key to press.
|
495
|
-
# @param [String] metastate The state the metakeys should be in when pressing the key.
|
496
|
-
#
|
497
|
-
# @example
|
498
|
-
#
|
499
|
-
# @driver.keyevent 82
|
500
|
-
#
|
501
|
-
def keyevent(key, metastate = nil)
|
502
|
-
@bridge.keyevent(key, metastate)
|
503
|
-
end
|
504
|
-
|
505
526
|
# Press keycode on the device.
|
506
527
|
# http://developer.android.com/reference/android/view/KeyEvent.html
|
507
528
|
# @param [Integer] key The key to press. The values which have +KEYCODE_+ prefix in http://developer.android.com/reference/android/view/KeyEvent.html
|
@@ -546,6 +567,7 @@ module Appium
|
|
546
567
|
@bridge.long_press_keycode(key, metastate: metastate, flags: flags)
|
547
568
|
end
|
548
569
|
|
570
|
+
# @deprecated Except for Windows
|
549
571
|
# Start the simulator and application configured with desired capabilities
|
550
572
|
#
|
551
573
|
# @example
|
@@ -556,6 +578,7 @@ module Appium
|
|
556
578
|
@bridge.launch_app
|
557
579
|
end
|
558
580
|
|
581
|
+
# @deprecated Except for Windows
|
559
582
|
# Close an app on device
|
560
583
|
#
|
561
584
|
# @example
|
@@ -566,6 +589,7 @@ module Appium
|
|
566
589
|
@bridge.close_app
|
567
590
|
end
|
568
591
|
|
592
|
+
# @deprecated
|
569
593
|
# Reset the device, relaunching the application.
|
570
594
|
#
|
571
595
|
# @example
|
@@ -573,6 +597,10 @@ module Appium
|
|
573
597
|
# @driver.reset
|
574
598
|
#
|
575
599
|
def reset
|
600
|
+
::Appium::Logger.warn(
|
601
|
+
'[DEPRECATION] reset is deprecated. Please use terminate_app and activate_app, ' \
|
602
|
+
'or quit and create a new session instead.'
|
603
|
+
)
|
576
604
|
@bridge.reset
|
577
605
|
end
|
578
606
|
|
@@ -602,7 +630,9 @@ module Appium
|
|
602
630
|
@bridge.background_app(duration)
|
603
631
|
end
|
604
632
|
|
605
|
-
# Install the given app onto the device
|
633
|
+
# Install the given app onto the device.
|
634
|
+
# Each options can be snake-case or camel-case. Snake-cases will be converted to camel-case
|
635
|
+
# as options value.
|
606
636
|
#
|
607
637
|
# @param [String] path The absolute local path or remote http URL to an .ipa or .apk file,
|
608
638
|
# or a .zip containing one of these.
|
@@ -616,26 +646,26 @@ module Appium
|
|
616
646
|
# @param [Boolean] grant_permissions Only for Android. whether to automatically grant application permissions
|
617
647
|
# on Android 6+ after the installation completes. +false+ by default
|
618
648
|
#
|
649
|
+
# Other parameters such as https://github.com/appium/appium-xcuitest-driver#mobile-installapp also can be set.
|
650
|
+
# Then, arguments in snake case will be camel case as its request parameters.
|
651
|
+
#
|
619
652
|
# @example
|
620
653
|
#
|
621
654
|
# @driver.install_app("/path/to/test.apk")
|
622
655
|
# @driver.install_app("/path/to/test.apk", replace: true, timeout: 20000, allow_test_packages: true,
|
623
656
|
# use_sdcard: false, grant_permissions: false)
|
657
|
+
# @driver.install_app("/path/to/test.ipa", timeoutMs: 20000)
|
624
658
|
#
|
625
|
-
def install_app(path,
|
626
|
-
|
627
|
-
|
628
|
-
allow_test_packages: nil,
|
629
|
-
use_sdcard: nil,
|
630
|
-
grant_permissions: nil)
|
631
|
-
@bridge.install_app(path,
|
632
|
-
replace: replace,
|
633
|
-
timeout: timeout,
|
634
|
-
allow_test_packages: allow_test_packages,
|
635
|
-
use_sdcard: use_sdcard,
|
636
|
-
grant_permissions: grant_permissions)
|
659
|
+
def install_app(path, **options)
|
660
|
+
options = options.transform_keys { |key| key.to_s.gsub(/_./) { |v| v[1].upcase } } unless options.nil?
|
661
|
+
@bridge.install_app(path, options)
|
637
662
|
end
|
638
663
|
|
664
|
+
# def capitalize(s)
|
665
|
+
# chars =
|
666
|
+
# chars[1:].map(&:capitalize).join
|
667
|
+
# end
|
668
|
+
|
639
669
|
# @param [Strong] app_id BundleId for iOS or package name for Android
|
640
670
|
# @param [Boolean] keep_data Only for Android. Whether to keep application data and caches after it is uninstalled.
|
641
671
|
# +false+ by default
|
@@ -790,7 +820,7 @@ module Appium
|
|
790
820
|
#
|
791
821
|
# @example: Zoom
|
792
822
|
#
|
793
|
-
# f1 =
|
823
|
+
# f1 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger1')
|
794
824
|
# f1.create_pointer_move(duration: 1, x: 200, y: 500,
|
795
825
|
# origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
796
826
|
# f1.create_pointer_down(:left)
|
@@ -798,7 +828,7 @@ module Appium
|
|
798
828
|
# origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
799
829
|
# f1.create_pointer_up(:left)
|
800
830
|
#
|
801
|
-
# f2 =
|
831
|
+
# f2 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger2')
|
802
832
|
# f2.create_pointer_move(duration: 1, x: 200, y: 500,
|
803
833
|
# origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
804
834
|
# f2.create_pointer_down(:left)
|
@@ -809,7 +839,11 @@ module Appium
|
|
809
839
|
# @driver.perform_actions [f1, f2] #=> 'nil' if the action succeed
|
810
840
|
#
|
811
841
|
def perform_actions(data)
|
812
|
-
raise ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
|
842
|
+
raise ::Appium::Core::Error::ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
|
843
|
+
|
844
|
+
# NOTE: 'add_input' in Selenium Ruby implementation has additional 'pause'.
|
845
|
+
# This implementation is to avoid the additional pause.
|
846
|
+
# https://github.com/SeleniumHQ/selenium/blob/64447d4b03f6986337d1ca8d8b6476653570bcc1/rb/lib/selenium/webdriver/common/action_builder.rb#L207
|
813
847
|
|
814
848
|
@bridge.send_actions data.map(&:encode).compact
|
815
849
|
data.each(&:clear_actions)
|
@@ -853,7 +887,7 @@ module Appium
|
|
853
887
|
end
|
854
888
|
|
855
889
|
# Get the device window's logs.
|
856
|
-
# @return [
|
890
|
+
# @return [Appium::Core::Logs]
|
857
891
|
#
|
858
892
|
# @example
|
859
893
|
#
|
@@ -879,16 +913,15 @@ module Appium
|
|
879
913
|
# Retrieve the capabilities of the specified session.
|
880
914
|
# It's almost same as +@driver.capabilities+ but you can get more details.
|
881
915
|
#
|
882
|
-
# @return [Selenium::WebDriver::Remote::Capabilities]
|
916
|
+
# @return [Selenium::WebDriver::Remote::Capabilities, Selenium::WebDriver::Remote::Capabilities]
|
883
917
|
#
|
884
918
|
# @example
|
885
919
|
# @driver.session_capabilities
|
886
920
|
#
|
887
921
|
# #=> uiautomator2
|
888
|
-
# # <Selenium::WebDriver::Remote::
|
922
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fa38dae1360
|
889
923
|
# # @capabilities=
|
890
|
-
# # {:
|
891
|
-
# # :browser_name=>nil,
|
924
|
+
# # {:browser_name=>nil,
|
892
925
|
# # :browser_version=>nil,
|
893
926
|
# # :platform_name=>"android",
|
894
927
|
# # :page_load_strategy=>nil,
|
@@ -935,10 +968,9 @@ module Appium
|
|
935
968
|
# # "viewportRect"=>{"left"=>0, "top"=>63, "width"=>1080, "height"=>1731}}>
|
936
969
|
# #
|
937
970
|
# #=> XCUITest
|
938
|
-
# # <Selenium::WebDriver::Remote::
|
971
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fb15dc01370
|
939
972
|
# # @capabilities=
|
940
|
-
# # {:
|
941
|
-
# # :browser_name=>"UICatalog",
|
973
|
+
# # {:browser_name=>"UICatalog",
|
942
974
|
# # :browser_version=>nil,
|
943
975
|
# # :platform_name=>"ios",
|
944
976
|
# # :page_load_strategy=>nil,
|
@@ -992,11 +1024,14 @@ module Appium
|
|
992
1024
|
visualize: visualize)
|
993
1025
|
end
|
994
1026
|
|
995
|
-
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil
|
1027
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
|
1028
|
+
multiple: nil, match_neighbour_threshold: nil)
|
996
1029
|
@bridge.find_image_occurrence(full_image: full_image,
|
997
1030
|
partial_image: partial_image,
|
998
1031
|
visualize: visualize,
|
999
|
-
threshold: threshold
|
1032
|
+
threshold: threshold,
|
1033
|
+
multiple: multiple,
|
1034
|
+
match_neighbour_threshold: match_neighbour_threshold)
|
1000
1035
|
end
|
1001
1036
|
|
1002
1037
|
def get_images_similarity(first_image:, second_image:, visualize: false)
|
@@ -1009,14 +1044,14 @@ module Appium
|
|
1009
1044
|
|
1010
1045
|
# @since Appium 1.8.2
|
1011
1046
|
# Return an element if current view has a partial image. The logic depends on template matching by OpenCV.
|
1012
|
-
# {https://github.com/appium/appium/blob/
|
1047
|
+
# {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison}
|
1013
1048
|
#
|
1014
1049
|
# You can handle settings for the comparision following below.
|
1015
1050
|
# {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 device-settings}
|
1016
1051
|
#
|
1017
1052
|
# @param [String] img_path A path to a partial image you'd like to find
|
1018
1053
|
#
|
1019
|
-
# @return [::
|
1054
|
+
# @return [::Appium::Core::Element]
|
1020
1055
|
#
|
1021
1056
|
# @example
|
1022
1057
|
#
|
@@ -1031,14 +1066,14 @@ module Appium
|
|
1031
1066
|
|
1032
1067
|
# @since Appium 1.8.2
|
1033
1068
|
# Return elements if current view has a partial image. The logic depends on template matching by OpenCV.
|
1034
|
-
# {https://github.com/appium/appium/blob/
|
1069
|
+
# {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison}
|
1035
1070
|
#
|
1036
1071
|
# You can handle settings for the comparision following below.
|
1037
1072
|
# {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 device-settings}
|
1038
1073
|
#
|
1039
1074
|
# @param [String] img_path A path to a partial image you'd like to find
|
1040
1075
|
#
|
1041
|
-
# @return [
|
1076
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
1042
1077
|
#
|
1043
1078
|
# @example
|
1044
1079
|
#
|
@@ -1086,14 +1121,14 @@ module Appium
|
|
1086
1121
|
@bridge.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
|
1087
1122
|
end
|
1088
1123
|
|
1089
|
-
# Convert vanilla element response to ::
|
1124
|
+
# Convert vanilla element response to ::Appium::Core::Element
|
1090
1125
|
#
|
1091
1126
|
# @param [Hash] id The id which can get as a response from server
|
1092
|
-
# @return [::
|
1127
|
+
# @return [::Appium::Core::Element]
|
1093
1128
|
#
|
1094
1129
|
# @example
|
1095
1130
|
# response = {"element-6066-11e4-a52e-4f735466cecf"=>"xxxx", "ELEMENT"=>"xxxx"}
|
1096
|
-
# ele = @driver.convert_to_element(response) #=> ::
|
1131
|
+
# ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
|
1097
1132
|
# ele.rect #=> Can get the rect of the element
|
1098
1133
|
#
|
1099
1134
|
def convert_to_element(id)
|