appium_lib_core 4.1.0 → 7.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/CHANGELOG.md +250 -271
- data/README.md +65 -15
- 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 +45 -4
- data/lib/appium_lib_core/common/base/bridge.rb +320 -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 +232 -191
- 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 +15 -38
- 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 +62 -0
- data/lib/appium_lib_core/common/base/screenshot.rb +8 -8
- 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 +194 -108
- 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/support/event_firing_bridge.rb +57 -0
- 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 +21 -10
- metadata +31 -86
- 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,75 @@ 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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
# override
|
48
|
+
def initialize(bridge: nil, listener: nil, **opts) # rubocop:disable Lint/MissingSuper
|
49
|
+
original_opts = opts.dup
|
50
|
+
|
51
|
+
# For ::Appium::Core::Waitable
|
52
|
+
@wait_timeout = opts.delete(:wait_timeout)
|
53
|
+
@wait_interval = opts.delete(:wait_interval)
|
54
|
+
|
55
|
+
# Selenium WebDriver attributes
|
56
|
+
@devtools = nil
|
57
|
+
@bidi = nil
|
58
|
+
|
59
|
+
# in the selenium webdriver as well
|
60
|
+
bridge ||= create_bridge(**opts)
|
61
|
+
add_extensions(bridge.browser)
|
62
|
+
@bridge = listener ? ::Appium::Support::EventFiringBridge.new(bridge, listener, **original_opts) : bridge
|
50
63
|
end
|
51
64
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
65
|
+
private
|
66
|
+
|
67
|
+
# Create a proper bridge instance.
|
68
|
+
#
|
69
|
+
# @return [::Appium::Core::Base::Bridge]
|
70
|
+
#
|
71
|
+
def create_bridge(**opts)
|
72
|
+
# for a new session request
|
73
|
+
capabilities = opts.delete(:capabilities)
|
74
|
+
bridge_opts = { http_client: opts.delete(:http_client), url: opts.delete(:url) }
|
75
|
+
|
76
|
+
# for attaching to an existing session
|
77
|
+
session_id = opts.delete(:existing_session_id)
|
78
|
+
automation_name = opts.delete(:automation_name)
|
79
|
+
platform_name = opts.delete(:platform_name)
|
80
|
+
|
81
|
+
raise ::Appium::Core::Error::ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
|
82
|
+
|
83
|
+
bridge = ::Appium::Core::Base::Bridge.new(**bridge_opts)
|
84
|
+
|
85
|
+
if session_id.nil?
|
86
|
+
bridge.create_session(capabilities)
|
87
|
+
else
|
88
|
+
# attach to the existing session id
|
89
|
+
bridge.attach_to(session_id, platform_name, automation_name)
|
90
|
+
end
|
91
|
+
|
92
|
+
bridge
|
56
93
|
end
|
57
94
|
|
95
|
+
public
|
96
|
+
|
58
97
|
# Update +server_url+ and HTTP clients following this arguments, protocol, host, port and path.
|
59
98
|
# After this method, +@bridge.http+ will be a new instance following them instead of +server_url+ which is
|
60
99
|
# set before creating session.
|
100
|
+
# If +@bridge.http+ did not have +update_sending_request_to+ method, this method returns immediately.
|
61
101
|
#
|
62
102
|
# @example
|
63
103
|
#
|
@@ -66,14 +106,124 @@ module Appium
|
|
66
106
|
# driver.manage.timeouts.implicit_wait = 10 # @bridge.http is for 'https://example2.com:9000/wd/hub/'
|
67
107
|
#
|
68
108
|
def update_sending_request_to(protocol:, host:, port:, path:)
|
69
|
-
@bridge.http
|
70
|
-
|
71
|
-
|
72
|
-
|
109
|
+
unless @bridge.http&.class&.method_defined? :update_sending_request_to
|
110
|
+
::Appium::Logger.warn "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
|
111
|
+
'It keeps current connection target.'
|
112
|
+
return
|
113
|
+
end
|
114
|
+
|
115
|
+
@bridge.http&.update_sending_request_to(scheme: protocol,
|
116
|
+
host: host,
|
117
|
+
port: port,
|
118
|
+
path: path)
|
119
|
+
end
|
120
|
+
|
121
|
+
AVAILABLE_METHODS = [
|
122
|
+
:get, :head, :post, :put, :delete,
|
123
|
+
:connect, :options, :trace, :patch
|
124
|
+
].freeze
|
125
|
+
# Define a new custom method to the driver so that you can define your own method for
|
126
|
+
# drivers/plugins in Appium 2.0. Appium 2.0 and its custom drivers/plugins allow you
|
127
|
+
# to define custom commands that are not part of W3C spec.
|
128
|
+
#
|
129
|
+
# @param [Symbol] method HTTP request method as https://www.w3.org/TR/webdriver/#endpoints
|
130
|
+
# @param [string] url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints.
|
131
|
+
# +:session_id+ is the placeholder of 'session id'.
|
132
|
+
# Other place holders can be specified with +:+ prefix like +:id+.
|
133
|
+
# Then, the +:id+ will be replaced with a given value as the seconds argument of +execute+
|
134
|
+
# @param [Symbol] name The name of method that is called as the driver instance method.
|
135
|
+
# @param [Proc] block The block to involve as the method.
|
136
|
+
# Please define a method that has the same +name+ with arguments you want.
|
137
|
+
# The method must has +execute+ method. tHe +execute+ is calls the +url+
|
138
|
+
# with the given parameters.
|
139
|
+
# The first argument should be +name+ as symbol.
|
140
|
+
# The second argument should be hash. If keys in the hash matches +:+ prefix
|
141
|
+
# string in the given url, the matched string in the given url will be
|
142
|
+
# values in the hash.
|
143
|
+
# The third argument should be hash. The hash will be the request body.
|
144
|
+
# Please read examples below for more details.
|
145
|
+
# @raise [ArgumentError] If the given +method+ is invalid value.
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
#
|
149
|
+
# @driver.add_command(
|
150
|
+
# method: :get,
|
151
|
+
# url: 'session/:session_id/path/to/custom/url',
|
152
|
+
# name: :test_command
|
153
|
+
# )
|
154
|
+
# # Send a GET request to 'session/<session id>/path/to/custom/url'
|
155
|
+
# @driver.test_command
|
156
|
+
#
|
157
|
+
#
|
158
|
+
# @driver.add_command(
|
159
|
+
# method: :post,
|
160
|
+
# url: 'session/:session_id/path/to/custom/url',
|
161
|
+
# name: :test_command
|
162
|
+
# ) do
|
163
|
+
# def test_command(argument)
|
164
|
+
# execute(:test_command, {}, { dummy: argument })
|
165
|
+
# end
|
166
|
+
# end
|
167
|
+
# # Send a POST request to 'session/<session id>/path/to/custom/url'
|
168
|
+
# # with body "{ dummy: 1 }" as JSON object. "1" is the argument.
|
169
|
+
# # ':session_id' in the given 'url' is replaced with current 'session id'.
|
170
|
+
# @driver.test_command(1)
|
171
|
+
#
|
172
|
+
#
|
173
|
+
# @driver.add_command(
|
174
|
+
# method: :post,
|
175
|
+
# url: 'session/:session_id/element/:id/custom/action',
|
176
|
+
# name: :test_action_command
|
177
|
+
# ) do
|
178
|
+
# def test_action_command(element_id, action)
|
179
|
+
# execute(:test_action_command, {id: element_id}, { dummy_action: action })
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
# # Send a POST request to 'session/<session id>/element/<element id>/custom/action'
|
183
|
+
# # with body "{ dummy_action: #{action} }" as JSON object. "action" is the seconds argument.
|
184
|
+
# # ':session_id' in the given url is replaced with current 'session id'.
|
185
|
+
# # ':id' in the given url is replaced with the given 'element_id'.
|
186
|
+
# e = @driver.find_element :accessibility_id, 'an element'
|
187
|
+
# @driver.test_action_command(e.id, 'action')
|
188
|
+
#
|
189
|
+
def add_command(method:, url:, name:, &block)
|
190
|
+
unless AVAILABLE_METHODS.include? method
|
191
|
+
raise ::Appium::Core::Error::ArgumentError, "Available method is either #{AVAILABLE_METHODS}"
|
192
|
+
end
|
193
|
+
|
194
|
+
# TODO: Remove this logger before Appium 2.0 release
|
195
|
+
::Appium::Logger.info '[Experimental] this method is experimental for Appium 2.0. This interface may change.'
|
196
|
+
|
197
|
+
@bridge.add_command method: method, url: url, name: name, &block
|
73
198
|
end
|
74
199
|
|
75
200
|
### Methods for Appium
|
76
201
|
|
202
|
+
# Perform 'key' actions for W3C module.
|
203
|
+
# Generate +key+ pointer action here and users can use this via +driver.key_action+
|
204
|
+
# - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/W3CActionBuilder.html
|
205
|
+
# - https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/KeyActions.html
|
206
|
+
#
|
207
|
+
# The pointer type is 'key' by default in the Appium Ruby client.
|
208
|
+
# +driver.action+ in Appium Ruby client has 'pointer' action by default.
|
209
|
+
# This method is a shortcut to set 'key' type.
|
210
|
+
# Hense this method is equal to +driver.action(devices: [::Selenium::WebDriver::Interactions.key('keyboard')])+
|
211
|
+
# as below example.
|
212
|
+
#
|
213
|
+
# @example
|
214
|
+
#
|
215
|
+
# element = @driver.find_element(:id, "some id")
|
216
|
+
# @driver.key_action.send_key('hiあ').perform # The 'send_key' is a part of 'KeyActions'
|
217
|
+
# # is equal to:
|
218
|
+
# # @driver.action(devices: [::Selenium::WebDriver::Interactions.key('keyboard')]).send_keys('hiあ').perform
|
219
|
+
#
|
220
|
+
def key_action(async: false)
|
221
|
+
@bridge.action(
|
222
|
+
async: async,
|
223
|
+
devices: [::Selenium::WebDriver::Interactions.key('keyboard')]
|
224
|
+
)
|
225
|
+
end
|
226
|
+
|
77
227
|
# Lock the device
|
78
228
|
# @return [String]
|
79
229
|
#
|
@@ -138,38 +288,6 @@ module Appium
|
|
138
288
|
end
|
139
289
|
alias is_keyboard_shown keyboard_shown?
|
140
290
|
|
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
291
|
# Returns an instance of DriverSettings to call get/update.
|
174
292
|
#
|
175
293
|
# @example
|
@@ -178,7 +296,7 @@ module Appium
|
|
178
296
|
# @driver.settings.update('allowInvisibleElements': true)
|
179
297
|
#
|
180
298
|
def settings
|
181
|
-
@
|
299
|
+
@settings ||= DriverSettings.new(@bridge)
|
182
300
|
end
|
183
301
|
|
184
302
|
# Get appium Settings for current test session.
|
@@ -200,8 +318,8 @@ module Appium
|
|
200
318
|
#
|
201
319
|
# @example
|
202
320
|
#
|
203
|
-
# @driver.update_settings('allowInvisibleElements': true)
|
204
|
-
# @driver.settings.update('allowInvisibleElements': true)
|
321
|
+
# @driver.update_settings({ 'allowInvisibleElements': true })
|
322
|
+
# @driver.settings.update({ 'allowInvisibleElements': true })
|
205
323
|
# @driver.settings = { 'allowInvisibleElements': true }
|
206
324
|
#
|
207
325
|
def settings=(value)
|
@@ -209,36 +327,10 @@ module Appium
|
|
209
327
|
end
|
210
328
|
alias update_settings settings=
|
211
329
|
|
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
330
|
# Returns an instance of DeviceIME
|
241
331
|
#
|
332
|
+
# @return [Appium::Core::Base::Driver::DeviceIME]
|
333
|
+
#
|
242
334
|
# @example
|
243
335
|
#
|
244
336
|
# @driver.ime.activate engine: 'com.android.inputmethod.latin/.LatinIME'
|
@@ -248,7 +340,7 @@ module Appium
|
|
248
340
|
# @driver.ime.deactivate #=> Deactivate current IME engine
|
249
341
|
#
|
250
342
|
def ime
|
251
|
-
@
|
343
|
+
@ime ||= DeviceIME.new(@bridge)
|
252
344
|
end
|
253
345
|
|
254
346
|
# Android only. Make an engine that is available active.
|
@@ -289,6 +381,8 @@ module Appium
|
|
289
381
|
# @!method ime_activated
|
290
382
|
# Android only. Indicates whether IME input is active at the moment (not if it is available).
|
291
383
|
#
|
384
|
+
# @return [Boolean]
|
385
|
+
#
|
292
386
|
# @example
|
293
387
|
#
|
294
388
|
# @driver.ime_activated #=> True if IME is activated
|
@@ -366,42 +460,10 @@ module Appium
|
|
366
460
|
end
|
367
461
|
alias set_context context=
|
368
462
|
|
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
463
|
# 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
464
|
# On Android, the application under test should be built with debuggable flag enabled in order to get access to
|
397
465
|
# its container on the internal file system.
|
398
466
|
#
|
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
467
|
# @param [String] path Either an absolute path OR, for iOS devices, a path relative to the app, as described.
|
406
468
|
# If the path starts with application id prefix, then the file will be pushed to the root of
|
407
469
|
# the corresponding application container.
|
@@ -418,18 +480,10 @@ module Appium
|
|
418
480
|
@bridge.push_file(path, filedata)
|
419
481
|
end
|
420
482
|
|
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.
|
483
|
+
# Pull a file from the remote device.
|
424
484
|
# On Android the application under test should be built with debuggable flag enabled in order to get access
|
425
485
|
# to its container on the internal file system.
|
426
486
|
#
|
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
487
|
# @param [String] path Either an absolute path OR, for iOS devices, a path relative to the app, as described.
|
434
488
|
# If the path starts with application id prefix, then the file will be pulled from the root
|
435
489
|
# of the corresponding application container.
|
@@ -438,7 +492,6 @@ module Appium
|
|
438
492
|
# Only pulling files from application containers is supported for iOS Simulator.
|
439
493
|
# Provide the remote path in format
|
440
494
|
# <code>@bundle.identifier:container_type/relative_path_in_container</code>
|
441
|
-
# (Make sure this in ifuse doc)
|
442
495
|
#
|
443
496
|
# @return [Base64-decoded] Base64 decoded data
|
444
497
|
#
|
@@ -455,18 +508,10 @@ module Appium
|
|
455
508
|
@bridge.pull_file(path)
|
456
509
|
end
|
457
510
|
|
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.
|
511
|
+
# Pull a folder content from the remote device.
|
461
512
|
# On Android the application under test should be built with debuggable flag enabled in order to get access to
|
462
513
|
# its container on the internal file system.
|
463
514
|
#
|
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
515
|
# @param [String] path Absolute path to the folder.
|
471
516
|
# If the path starts with <em>@applicationId/</em> prefix, then the folder will be pulled
|
472
517
|
# from the root of the corresponding application container.
|
@@ -475,7 +520,6 @@ module Appium
|
|
475
520
|
# Only pulling files from application containers is supported for iOS Simulator.
|
476
521
|
# Provide the remote path in format
|
477
522
|
# <code>@bundle.identifier:container_type/relative_path_in_container</code>
|
478
|
-
# (Make sure this in ifuse doc)
|
479
523
|
#
|
480
524
|
# @return [Base64-decoded] Base64 decoded data which is zip archived
|
481
525
|
#
|
@@ -489,19 +533,6 @@ module Appium
|
|
489
533
|
@bridge.pull_folder(path)
|
490
534
|
end
|
491
535
|
|
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
536
|
# Press keycode on the device.
|
506
537
|
# http://developer.android.com/reference/android/view/KeyEvent.html
|
507
538
|
# @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 +577,7 @@ module Appium
|
|
546
577
|
@bridge.long_press_keycode(key, metastate: metastate, flags: flags)
|
547
578
|
end
|
548
579
|
|
580
|
+
# @deprecated Except for Windows
|
549
581
|
# Start the simulator and application configured with desired capabilities
|
550
582
|
#
|
551
583
|
# @example
|
@@ -556,6 +588,7 @@ module Appium
|
|
556
588
|
@bridge.launch_app
|
557
589
|
end
|
558
590
|
|
591
|
+
# @deprecated Except for Windows
|
559
592
|
# Close an app on device
|
560
593
|
#
|
561
594
|
# @example
|
@@ -566,6 +599,7 @@ module Appium
|
|
566
599
|
@bridge.close_app
|
567
600
|
end
|
568
601
|
|
602
|
+
# @deprecated
|
569
603
|
# Reset the device, relaunching the application.
|
570
604
|
#
|
571
605
|
# @example
|
@@ -573,6 +607,10 @@ module Appium
|
|
573
607
|
# @driver.reset
|
574
608
|
#
|
575
609
|
def reset
|
610
|
+
::Appium::Logger.warn(
|
611
|
+
'[DEPRECATION] reset is deprecated. Please use terminate_app and activate_app, ' \
|
612
|
+
'or quit and create a new session instead.'
|
613
|
+
)
|
576
614
|
@bridge.reset
|
577
615
|
end
|
578
616
|
|
@@ -602,7 +640,9 @@ module Appium
|
|
602
640
|
@bridge.background_app(duration)
|
603
641
|
end
|
604
642
|
|
605
|
-
# Install the given app onto the device
|
643
|
+
# Install the given app onto the device.
|
644
|
+
# Each options can be snake-case or camel-case. Snake-cases will be converted to camel-case
|
645
|
+
# as options value.
|
606
646
|
#
|
607
647
|
# @param [String] path The absolute local path or remote http URL to an .ipa or .apk file,
|
608
648
|
# or a .zip containing one of these.
|
@@ -616,26 +656,26 @@ module Appium
|
|
616
656
|
# @param [Boolean] grant_permissions Only for Android. whether to automatically grant application permissions
|
617
657
|
# on Android 6+ after the installation completes. +false+ by default
|
618
658
|
#
|
659
|
+
# Other parameters such as https://github.com/appium/appium-xcuitest-driver#mobile-installapp also can be set.
|
660
|
+
# Then, arguments in snake case will be camel case as its request parameters.
|
661
|
+
#
|
619
662
|
# @example
|
620
663
|
#
|
621
664
|
# @driver.install_app("/path/to/test.apk")
|
622
665
|
# @driver.install_app("/path/to/test.apk", replace: true, timeout: 20000, allow_test_packages: true,
|
623
666
|
# use_sdcard: false, grant_permissions: false)
|
667
|
+
# @driver.install_app("/path/to/test.ipa", timeoutMs: 20000)
|
624
668
|
#
|
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)
|
669
|
+
def install_app(path, **options)
|
670
|
+
options = options.transform_keys { |key| key.to_s.gsub(/_./) { |v| v[1].upcase } } unless options.nil?
|
671
|
+
@bridge.install_app(path, options)
|
637
672
|
end
|
638
673
|
|
674
|
+
# def capitalize(s)
|
675
|
+
# chars =
|
676
|
+
# chars[1:].map(&:capitalize).join
|
677
|
+
# end
|
678
|
+
|
639
679
|
# @param [Strong] app_id BundleId for iOS or package name for Android
|
640
680
|
# @param [Boolean] keep_data Only for Android. Whether to keep application data and caches after it is uninstalled.
|
641
681
|
# +false+ by default
|
@@ -790,7 +830,7 @@ module Appium
|
|
790
830
|
#
|
791
831
|
# @example: Zoom
|
792
832
|
#
|
793
|
-
# f1 =
|
833
|
+
# f1 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger1')
|
794
834
|
# f1.create_pointer_move(duration: 1, x: 200, y: 500,
|
795
835
|
# origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
796
836
|
# f1.create_pointer_down(:left)
|
@@ -798,7 +838,7 @@ module Appium
|
|
798
838
|
# origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
799
839
|
# f1.create_pointer_up(:left)
|
800
840
|
#
|
801
|
-
# f2 =
|
841
|
+
# f2 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger2')
|
802
842
|
# f2.create_pointer_move(duration: 1, x: 200, y: 500,
|
803
843
|
# origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
804
844
|
# f2.create_pointer_down(:left)
|
@@ -809,7 +849,11 @@ module Appium
|
|
809
849
|
# @driver.perform_actions [f1, f2] #=> 'nil' if the action succeed
|
810
850
|
#
|
811
851
|
def perform_actions(data)
|
812
|
-
raise ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
|
852
|
+
raise ::Appium::Core::Error::ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
|
853
|
+
|
854
|
+
# NOTE: 'add_input' in Selenium Ruby implementation has additional 'pause'.
|
855
|
+
# This implementation is to avoid the additional pause.
|
856
|
+
# https://github.com/SeleniumHQ/selenium/blob/64447d4b03f6986337d1ca8d8b6476653570bcc1/rb/lib/selenium/webdriver/common/action_builder.rb#L207
|
813
857
|
|
814
858
|
@bridge.send_actions data.map(&:encode).compact
|
815
859
|
data.each(&:clear_actions)
|
@@ -853,7 +897,7 @@ module Appium
|
|
853
897
|
end
|
854
898
|
|
855
899
|
# Get the device window's logs.
|
856
|
-
# @return [
|
900
|
+
# @return [Appium::Core::Logs]
|
857
901
|
#
|
858
902
|
# @example
|
859
903
|
#
|
@@ -879,16 +923,15 @@ module Appium
|
|
879
923
|
# Retrieve the capabilities of the specified session.
|
880
924
|
# It's almost same as +@driver.capabilities+ but you can get more details.
|
881
925
|
#
|
882
|
-
# @return [Selenium::WebDriver::Remote::Capabilities]
|
926
|
+
# @return [Selenium::WebDriver::Remote::Capabilities, Selenium::WebDriver::Remote::Capabilities]
|
883
927
|
#
|
884
928
|
# @example
|
885
929
|
# @driver.session_capabilities
|
886
930
|
#
|
887
931
|
# #=> uiautomator2
|
888
|
-
# # <Selenium::WebDriver::Remote::
|
932
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fa38dae1360
|
889
933
|
# # @capabilities=
|
890
|
-
# # {:
|
891
|
-
# # :browser_name=>nil,
|
934
|
+
# # {:browser_name=>nil,
|
892
935
|
# # :browser_version=>nil,
|
893
936
|
# # :platform_name=>"android",
|
894
937
|
# # :page_load_strategy=>nil,
|
@@ -914,8 +957,6 @@ module Appium
|
|
914
957
|
# # "appPackage"=>"io.appium.android.apis",
|
915
958
|
# # "appActivity"=>"io.appium.android.apis.ApiDemos",
|
916
959
|
# # "someCapability"=>"some_capability",
|
917
|
-
# # "unicodeKeyboard"=>true,
|
918
|
-
# # "resetKeyboard"=>true},
|
919
960
|
# # "automationName"=>"uiautomator2",
|
920
961
|
# # "app"=>"/path/to/app/api.apk.zip",
|
921
962
|
# # "platformVersion"=>"8.1.0",
|
@@ -923,8 +964,6 @@ module Appium
|
|
923
964
|
# # "appPackage"=>"io.appium.android.apis",
|
924
965
|
# # "appActivity"=>"io.appium.android.apis.ApiDemos",
|
925
966
|
# # "someCapability"=>"some_capability",
|
926
|
-
# # "unicodeKeyboard"=>true,
|
927
|
-
# # "resetKeyboard"=>true,
|
928
967
|
# # "deviceUDID"=>"emulator-5554",
|
929
968
|
# # "deviceScreenSize"=>"1080x1920",
|
930
969
|
# # "deviceScreenDensity"=>420,
|
@@ -935,10 +974,9 @@ module Appium
|
|
935
974
|
# # "viewportRect"=>{"left"=>0, "top"=>63, "width"=>1080, "height"=>1731}}>
|
936
975
|
# #
|
937
976
|
# #=> XCUITest
|
938
|
-
# # <Selenium::WebDriver::Remote::
|
977
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fb15dc01370
|
939
978
|
# # @capabilities=
|
940
|
-
# # {:
|
941
|
-
# # :browser_name=>"UICatalog",
|
979
|
+
# # {:browser_name=>"UICatalog",
|
942
980
|
# # :browser_version=>nil,
|
943
981
|
# # :platform_name=>"ios",
|
944
982
|
# # :page_load_strategy=>nil,
|
@@ -992,11 +1030,14 @@ module Appium
|
|
992
1030
|
visualize: visualize)
|
993
1031
|
end
|
994
1032
|
|
995
|
-
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil
|
1033
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
|
1034
|
+
multiple: nil, match_neighbour_threshold: nil)
|
996
1035
|
@bridge.find_image_occurrence(full_image: full_image,
|
997
1036
|
partial_image: partial_image,
|
998
1037
|
visualize: visualize,
|
999
|
-
threshold: threshold
|
1038
|
+
threshold: threshold,
|
1039
|
+
multiple: multiple,
|
1040
|
+
match_neighbour_threshold: match_neighbour_threshold)
|
1000
1041
|
end
|
1001
1042
|
|
1002
1043
|
def get_images_similarity(first_image:, second_image:, visualize: false)
|
@@ -1009,14 +1050,14 @@ module Appium
|
|
1009
1050
|
|
1010
1051
|
# @since Appium 1.8.2
|
1011
1052
|
# 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/
|
1053
|
+
# {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison}
|
1013
1054
|
#
|
1014
1055
|
# You can handle settings for the comparision following below.
|
1015
1056
|
# {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 device-settings}
|
1016
1057
|
#
|
1017
1058
|
# @param [String] img_path A path to a partial image you'd like to find
|
1018
1059
|
#
|
1019
|
-
# @return [::
|
1060
|
+
# @return [::Appium::Core::Element]
|
1020
1061
|
#
|
1021
1062
|
# @example
|
1022
1063
|
#
|
@@ -1031,14 +1072,14 @@ module Appium
|
|
1031
1072
|
|
1032
1073
|
# @since Appium 1.8.2
|
1033
1074
|
# Return elements if current view has a partial image. The logic depends on template matching by OpenCV.
|
1034
|
-
# {https://github.com/appium/appium/blob/
|
1075
|
+
# {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison}
|
1035
1076
|
#
|
1036
1077
|
# You can handle settings for the comparision following below.
|
1037
1078
|
# {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 device-settings}
|
1038
1079
|
#
|
1039
1080
|
# @param [String] img_path A path to a partial image you'd like to find
|
1040
1081
|
#
|
1041
|
-
# @return [::
|
1082
|
+
# @return [Array<::Appium::Core::Element>]
|
1042
1083
|
#
|
1043
1084
|
# @example
|
1044
1085
|
#
|
@@ -1086,14 +1127,14 @@ module Appium
|
|
1086
1127
|
@bridge.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
|
1087
1128
|
end
|
1088
1129
|
|
1089
|
-
# Convert vanilla element response to ::
|
1130
|
+
# Convert vanilla element response to ::Appium::Core::Element
|
1090
1131
|
#
|
1091
1132
|
# @param [Hash] id The id which can get as a response from server
|
1092
|
-
# @return [::
|
1133
|
+
# @return [::Appium::Core::Element]
|
1093
1134
|
#
|
1094
1135
|
# @example
|
1095
1136
|
# response = {"element-6066-11e4-a52e-4f735466cecf"=>"xxxx", "ELEMENT"=>"xxxx"}
|
1096
|
-
# ele = @driver.convert_to_element(response) #=> ::
|
1137
|
+
# ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
|
1097
1138
|
# ele.rect #=> Can get the rect of the element
|
1098
1139
|
#
|
1099
1140
|
def convert_to_element(id)
|