appium_lib 9.6.1 → 9.7.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/.rubocop.yml +2 -2
- data/CHANGELOG.md +43 -0
- data/Rakefile +1 -1
- data/appium_lib.gemspec +1 -1
- data/docs/android_docs.md +440 -1295
- data/docs/docs.md +10 -103
- data/docs/index_paths.md +2 -0
- data/docs/ios_docs.md +725 -1674
- data/docs/migration.md +17 -0
- data/lib/appium_lib.rb +1 -2
- data/lib/appium_lib/android/android.rb +20 -0
- data/lib/appium_lib/android/{helper.rb → common/helper.rb} +1 -1
- data/lib/appium_lib/android/uiautomator2.rb +5 -4
- data/lib/appium_lib/android/uiautomator2/bridge.rb +16 -0
- data/lib/appium_lib/appium.rb +201 -0
- data/lib/appium_lib/common/helper.rb +18 -20
- data/lib/appium_lib/common/log.rb +24 -0
- data/lib/appium_lib/common/multi_touch.rb +89 -0
- data/lib/appium_lib/common/touch_actions.rb +48 -0
- data/lib/appium_lib/common/wait.rb +10 -49
- data/lib/appium_lib/core/android.rb +4 -0
- data/lib/appium_lib/core/android/device.rb +142 -0
- data/lib/appium_lib/core/android/search_context.rb +17 -0
- data/lib/appium_lib/core/android/uiautomator1/bridge.rb +16 -0
- data/lib/appium_lib/core/android/uiautomator2/bridge.rb +16 -0
- data/lib/appium_lib/core/android_uiautomator2.rb +4 -0
- data/lib/appium_lib/core/common.rb +6 -0
- data/lib/appium_lib/core/common/base.rb +8 -0
- data/lib/appium_lib/core/common/base/bridge.rb +47 -0
- data/lib/appium_lib/core/common/base/capabilities.rb +16 -0
- data/lib/appium_lib/core/common/base/command.rb +10 -0
- data/lib/appium_lib/core/common/base/driver.rb +40 -0
- data/lib/appium_lib/core/common/base/http_default.rb +12 -0
- data/lib/appium_lib/core/common/base/search_context.rb +89 -0
- data/lib/appium_lib/core/common/base/wait.rb +56 -0
- data/lib/appium_lib/{common → core/common}/command.rb +20 -16
- data/lib/appium_lib/core/common/device.rb +470 -0
- data/lib/appium_lib/core/common/error.rb +13 -0
- data/lib/appium_lib/core/common/log.rb +30 -0
- data/lib/appium_lib/{logger.rb → core/common/logger.rb} +2 -0
- data/lib/appium_lib/core/core.rb +38 -0
- data/lib/appium_lib/core/device/multi_touch.rb +213 -0
- data/lib/appium_lib/core/device/touch_actions.rb +206 -0
- data/lib/appium_lib/core/driver.rb +274 -0
- data/lib/appium_lib/core/ios.rb +6 -0
- data/lib/appium_lib/core/ios/device.rb +44 -0
- data/lib/appium_lib/core/ios/search_context.rb +27 -0
- data/lib/appium_lib/core/ios/uiautomation/bridge.rb +17 -0
- data/lib/appium_lib/core/ios/uiautomation/patch.rb +20 -0
- data/lib/appium_lib/core/ios/xcuitest/bridge.rb +18 -0
- data/lib/appium_lib/{ios → core/ios}/xcuitest/device.rb +5 -5
- data/lib/appium_lib/{ios → core/ios}/xcuitest/search_context.rb +13 -9
- data/lib/appium_lib/core/ios_xcuitest.rb +7 -0
- data/lib/appium_lib/core/patch.rb +56 -0
- data/lib/appium_lib/driver.rb +174 -446
- data/lib/appium_lib/ios/{errors.rb → common/errors.rb} +0 -0
- data/lib/appium_lib/ios/{helper.rb → common/helper.rb} +9 -110
- data/lib/appium_lib/ios/ios.rb +20 -0
- data/lib/appium_lib/ios/xcuitest.rb +1 -3
- data/lib/appium_lib/ios/xcuitest/bridge.rb +19 -0
- data/lib/appium_lib/ios/xcuitest/command.rb +4 -1
- data/lib/appium_lib/ios/xcuitest/{gestures.rb → command/gestures.rb} +1 -1
- data/lib/appium_lib/ios/xcuitest/element.rb +1 -18
- data/lib/appium_lib/ios/xcuitest/helper.rb +0 -6
- data/lib/appium_lib/sauce_labs.rb +29 -0
- data/lib/appium_lib/version.rb +5 -0
- data/release_notes.md +8 -0
- metadata +50 -25
- data/lib/appium_lib/android/client_xpath.rb +0 -51
- data/lib/appium_lib/android/device.rb +0 -39
- data/lib/appium_lib/android/mobile_methods.rb +0 -15
- data/lib/appium_lib/android/patch.rb +0 -16
- data/lib/appium_lib/capabilities.rb +0 -13
- data/lib/appium_lib/common/element/window.rb +0 -10
- data/lib/appium_lib/common/error.rb +0 -8
- data/lib/appium_lib/common/patch.rb +0 -190
- data/lib/appium_lib/common/search_context.rb +0 -10
- data/lib/appium_lib/common/version.rb +0 -5
- data/lib/appium_lib/device/device.rb +0 -611
- data/lib/appium_lib/device/multi_touch.rb +0 -225
- data/lib/appium_lib/device/touch_actions.rb +0 -230
- data/lib/appium_lib/ios/mobile_methods.rb +0 -25
- data/lib/appium_lib/ios/patch.rb +0 -22
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
module Appium
|
|
2
|
+
module Core
|
|
3
|
+
class Driver
|
|
4
|
+
# Selenium webdriver capabilities
|
|
5
|
+
attr_reader :caps
|
|
6
|
+
# Custom URL for the selenium server
|
|
7
|
+
attr_reader :custom_url
|
|
8
|
+
# Export session id to textfile in /tmp for 3rd party tools
|
|
9
|
+
attr_reader :export_session
|
|
10
|
+
# Default wait time for elements to appear
|
|
11
|
+
# Returns the default client side wait.
|
|
12
|
+
# This value is independent of what the server is using
|
|
13
|
+
# @return [Integer]
|
|
14
|
+
attr_reader :default_wait
|
|
15
|
+
# Appium's server port
|
|
16
|
+
attr_reader :port
|
|
17
|
+
# Device type to request from the appium server
|
|
18
|
+
attr_reader :device
|
|
19
|
+
# Automation name sent to appium server or received from server
|
|
20
|
+
# If automation_name is nil, it is not set both client side and server side.
|
|
21
|
+
attr_reader :automation_name
|
|
22
|
+
# Return a time wait timeout
|
|
23
|
+
# Wait time for ::Appium::Common.wait or ::Appium::Common.wait_true.
|
|
24
|
+
# Provide Appium::Drive like { appium_lib: { wait_timeout: 20 } }
|
|
25
|
+
# @return [Integer]
|
|
26
|
+
attr_reader :wait_timeout
|
|
27
|
+
# Return a time wait timeout
|
|
28
|
+
# Wait interval time for ::Appium::Common.wait or ::Appium::Common.wait_true.
|
|
29
|
+
# Provide Appium::Drive like { appium_lib: { wait_interval: 20 } }
|
|
30
|
+
# @return [Integer]
|
|
31
|
+
attr_reader :wait_interval
|
|
32
|
+
# Return http client called in start_driver()
|
|
33
|
+
# @return [Appium::Core::Base::Http::Default] the http client
|
|
34
|
+
attr_reader :http_client
|
|
35
|
+
# instance of AbstractEventListener for logging support
|
|
36
|
+
attr_reader :listener
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
# @return [Appium::Core::Base::Driver]
|
|
41
|
+
attr_reader :driver
|
|
42
|
+
|
|
43
|
+
public
|
|
44
|
+
|
|
45
|
+
# @private
|
|
46
|
+
# @see Appium::Core.for
|
|
47
|
+
#
|
|
48
|
+
# @return [Driver]
|
|
49
|
+
#
|
|
50
|
+
def self.for(target, opts = {})
|
|
51
|
+
new(target, opts)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @private
|
|
55
|
+
def initialize(target, opts = {})
|
|
56
|
+
opts = Appium.symbolize_keys opts
|
|
57
|
+
@caps = get_caps(opts)
|
|
58
|
+
|
|
59
|
+
set_appium_lib_specific_values(get_appium_lib_opts(opts))
|
|
60
|
+
set_app_path
|
|
61
|
+
set_appium_device
|
|
62
|
+
set_automation_name
|
|
63
|
+
|
|
64
|
+
extend_for(device: @device, automation_name: @automation_name, target: target)
|
|
65
|
+
|
|
66
|
+
self
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Creates a new global driver and quits the old one if it exists.
|
|
70
|
+
# You can customise http_client as the following
|
|
71
|
+
#
|
|
72
|
+
# @example
|
|
73
|
+
# ```ruby
|
|
74
|
+
# require 'rubygems'
|
|
75
|
+
# require 'appium_lib'
|
|
76
|
+
#
|
|
77
|
+
# # platformName takes a string or a symbol.
|
|
78
|
+
#
|
|
79
|
+
# # Start iOS driver
|
|
80
|
+
# opts = {
|
|
81
|
+
# caps: {
|
|
82
|
+
# platformName: :ios,
|
|
83
|
+
# app: '/path/to/MyiOS.app'
|
|
84
|
+
# },
|
|
85
|
+
# appium_lib: {
|
|
86
|
+
# wait_timeout: 30
|
|
87
|
+
# }
|
|
88
|
+
# }
|
|
89
|
+
# Appium::Driver.new(opts).start_driver
|
|
90
|
+
#
|
|
91
|
+
# @option http_client_ops [Hash] :http_client Custom HTTP Client
|
|
92
|
+
# @option http_client_ops [Hash] :open_timeout Custom open timeout for http client.
|
|
93
|
+
# @option http_client_ops [Hash] :read_timeout Custom read timeout for http client.
|
|
94
|
+
# @return [Selenium::WebDriver] the new global driver
|
|
95
|
+
def start_driver(server_url:,
|
|
96
|
+
http_client_ops: { http_client: nil, open_timeout: 999_999, read_timeout: 999_999 })
|
|
97
|
+
|
|
98
|
+
# open_timeout and read_timeout are explicit wait.
|
|
99
|
+
open_timeout = http_client_ops.delete(:open_timeout)
|
|
100
|
+
read_timeout = http_client_ops.delete(:read_timeout)
|
|
101
|
+
|
|
102
|
+
http_client = http_client_ops.delete(:http_client)
|
|
103
|
+
@http_client ||= http_client ? http_client : Appium::Core::Base::Http::Default.new
|
|
104
|
+
|
|
105
|
+
@http_client.open_timeout = open_timeout if open_timeout
|
|
106
|
+
@http_client.read_timeout = read_timeout if read_timeout
|
|
107
|
+
|
|
108
|
+
begin
|
|
109
|
+
# included https://github.com/SeleniumHQ/selenium/blob/43f8b3f66e7e01124eff6a5805269ee441f65707/rb/lib/selenium/webdriver/remote/driver.rb#L29
|
|
110
|
+
@driver = ::Appium::Core::Base::Driver.new(http_client: @http_client,
|
|
111
|
+
desired_capabilities: @caps,
|
|
112
|
+
url: server_url,
|
|
113
|
+
listener: @listener)
|
|
114
|
+
|
|
115
|
+
# export session
|
|
116
|
+
write_session_id(@driver.session_id) if @export_session
|
|
117
|
+
rescue Errno::ECONNREFUSED
|
|
118
|
+
raise "ERROR: Unable to connect to Appium. Is the server running on #{server_url}?"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# If "automationName" is set only server side, this method set "automationName" attribute into @automation_name.
|
|
122
|
+
# Since @automation_name is set only client side before start_driver is called.
|
|
123
|
+
set_automation_name_if_nil
|
|
124
|
+
|
|
125
|
+
@driver
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Quits the driver
|
|
129
|
+
# @return [void]
|
|
130
|
+
def quit_driver
|
|
131
|
+
@driver.quit
|
|
132
|
+
rescue
|
|
133
|
+
nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Returns the server's version info
|
|
137
|
+
#
|
|
138
|
+
# ```ruby
|
|
139
|
+
# {
|
|
140
|
+
# "build" => {
|
|
141
|
+
# "version" => "0.18.1",
|
|
142
|
+
# "revision" => "d242ebcfd92046a974347ccc3a28f0e898595198"
|
|
143
|
+
# }
|
|
144
|
+
# }
|
|
145
|
+
# ```
|
|
146
|
+
#
|
|
147
|
+
# Returns blank hash for Selenium Grid since `remote_status` gets 500 error
|
|
148
|
+
#
|
|
149
|
+
# ```ruby
|
|
150
|
+
# {}
|
|
151
|
+
# ```
|
|
152
|
+
#
|
|
153
|
+
# @return [Hash]
|
|
154
|
+
def appium_server_version
|
|
155
|
+
@driver.remote_status
|
|
156
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
|
157
|
+
raise ::Appium::Core::Error::ServerError unless e.message.include?('status code 500')
|
|
158
|
+
# driver.remote_status returns 500 error for using selenium grid
|
|
159
|
+
{}
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Return the platform version as an array of integers
|
|
163
|
+
# @return [Array<Integer>]
|
|
164
|
+
def platform_version
|
|
165
|
+
p_version = @driver.capabilities['platformVersion']
|
|
166
|
+
p_version.split('.').map(&:to_i)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Takes a png screenshot and saves to the target path.
|
|
170
|
+
#
|
|
171
|
+
# Example: screenshot '/tmp/hi.png'
|
|
172
|
+
#
|
|
173
|
+
# @param png_save_path [String] the full path to save the png
|
|
174
|
+
# @return [nil]
|
|
175
|
+
def screenshot(png_save_path)
|
|
176
|
+
@driver.save_screenshot png_save_path
|
|
177
|
+
nil
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
private
|
|
181
|
+
|
|
182
|
+
# @private
|
|
183
|
+
def extend_for(device:, automation_name:, target:)
|
|
184
|
+
target.extend Appium::Core
|
|
185
|
+
target.extend Appium::Core::Device
|
|
186
|
+
|
|
187
|
+
case device
|
|
188
|
+
when :android
|
|
189
|
+
case automation_name
|
|
190
|
+
when :uiautomator2
|
|
191
|
+
::Appium::Core::Android::Uiautomator2::Bridge.for(self)
|
|
192
|
+
else # default and UiAutomator
|
|
193
|
+
::Appium::Core::Android::Uiautomator1::Bridge.for(self)
|
|
194
|
+
end
|
|
195
|
+
when :ios
|
|
196
|
+
case automation_name
|
|
197
|
+
when :xcuitest
|
|
198
|
+
::Appium::Core::Ios::Xcuitest::Bridge.for(self)
|
|
199
|
+
else # default and UIAutomation
|
|
200
|
+
::Appium::Core::Ios::Uiautomation::Bridge.for(self)
|
|
201
|
+
end
|
|
202
|
+
when :mac
|
|
203
|
+
# no Mac specific extentions
|
|
204
|
+
Appium::Logger.debug('mac')
|
|
205
|
+
when :windows
|
|
206
|
+
# no windows specific extentions
|
|
207
|
+
Appium::Logger.debug('windows')
|
|
208
|
+
else
|
|
209
|
+
Appium::Logger.warn('no device matched')
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
target
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# @private
|
|
216
|
+
def get_caps(opts)
|
|
217
|
+
Core::Base::Capabilities.create_capabilities(opts[:caps] || {})
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @private
|
|
221
|
+
def get_appium_lib_opts(opts)
|
|
222
|
+
opts[:appium_lib] || {}
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# @private
|
|
226
|
+
# Path to the .apk, .app or .app.zip.
|
|
227
|
+
# The path can be local or remote for Sauce.
|
|
228
|
+
def set_app_path
|
|
229
|
+
return unless @caps && @caps[:app] && !@caps[:app].empty?
|
|
230
|
+
@caps[:app] = File.expand_path(@caps[:app])
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# @private
|
|
234
|
+
def set_appium_lib_specific_values(appium_lib_opts)
|
|
235
|
+
@custom_url = appium_lib_opts.fetch :server_url, false
|
|
236
|
+
@export_session = appium_lib_opts.fetch :export_session, false
|
|
237
|
+
@default_wait = appium_lib_opts.fetch :wait, 0
|
|
238
|
+
|
|
239
|
+
@port = appium_lib_opts.fetch :port, 4723
|
|
240
|
+
|
|
241
|
+
# timeout and interval used in ::Appium::Comm.wait/wait_true
|
|
242
|
+
@wait_timeout = appium_lib_opts.fetch :wait_timeout, 30
|
|
243
|
+
@wait_interval = appium_lib_opts.fetch :wait_interval, 0.5
|
|
244
|
+
|
|
245
|
+
# to pass it in Selenium.new.
|
|
246
|
+
# `listener = opts.delete(:listener)` is called in Selenium::Driver.new
|
|
247
|
+
@listener = appium_lib_opts.fetch :listener, nil
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# @private
|
|
251
|
+
def set_appium_device
|
|
252
|
+
# https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile
|
|
253
|
+
@device = @caps[:platformName]
|
|
254
|
+
return @device unless @device
|
|
255
|
+
|
|
256
|
+
@device = @device.is_a?(Symbol) ? @device : @device.downcase.strip.intern
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# @private
|
|
260
|
+
def set_automation_name
|
|
261
|
+
@automation_name = @caps[:automationName] if @caps[:automationName]
|
|
262
|
+
@automation_name = if @automation_name
|
|
263
|
+
@automation_name.is_a?(Symbol) ? @automation_name : @automation_name.downcase.strip.intern
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# @private
|
|
268
|
+
def set_automation_name_if_nil
|
|
269
|
+
return unless @automation_name.nil?
|
|
270
|
+
@automation_name = @driver.capabilities['automationName']
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end # module Appium
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Appium
|
|
2
|
+
module Ios
|
|
3
|
+
module Device
|
|
4
|
+
extend Forwardable
|
|
5
|
+
|
|
6
|
+
# @!method touch_id
|
|
7
|
+
# iOS only; Simulate Touch ID with either valid (match == true) or invalid (match == false) fingerprint.
|
|
8
|
+
# @param [Boolean] match fingerprint validity
|
|
9
|
+
# Defaults to true.
|
|
10
|
+
# ```ruby
|
|
11
|
+
# touch_id true #=> Simulate valid fingerprint
|
|
12
|
+
# touch_id false #=> Simulate invalid fingerprint
|
|
13
|
+
# ```
|
|
14
|
+
|
|
15
|
+
# @!method toggle_touch_id_enrollment
|
|
16
|
+
# iOS Simulator only: Toggle touch id enrollment on an iOS Simulator.
|
|
17
|
+
# @param [Boolean] enabled Enable toggle touch id enrollment. Set true by default.
|
|
18
|
+
# ```ruby
|
|
19
|
+
# toggle_touch_id_enrollment #=> Enable toggle enrolled
|
|
20
|
+
# toggle_touch_id_enrollment true #=> Enable toggle enrolled
|
|
21
|
+
# toggle_touch_id_enrollment false #=> Disable toggle enrolled
|
|
22
|
+
# ```
|
|
23
|
+
# toggle_touch_id_enrollment
|
|
24
|
+
class << self
|
|
25
|
+
def extended(_mod)
|
|
26
|
+
::Appium::Core::Device.extend_webdriver_with_forwardable
|
|
27
|
+
|
|
28
|
+
# TODO: TEST ME
|
|
29
|
+
::Appium::Core::Device.add_endpoint_method(:touch_id) do
|
|
30
|
+
def touch_id(match = true)
|
|
31
|
+
execute :touch_id, {}, match: match
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
::Appium::Core::Device.add_endpoint_method(:toggle_touch_id_enrollment) do
|
|
36
|
+
def toggle_touch_id_enrollment(enabled = true)
|
|
37
|
+
execute :toggle_touch_id_enrollment, {}, enabled: enabled
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end # module Device
|
|
43
|
+
end # module iOS
|
|
44
|
+
end # module Appium
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Appium
|
|
2
|
+
module Core
|
|
3
|
+
module Ios
|
|
4
|
+
module SearchContext
|
|
5
|
+
# @!method uiautomation_find
|
|
6
|
+
# find_element/s can be used with a [UIAutomation command](https://developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930).
|
|
7
|
+
#
|
|
8
|
+
# ```ruby
|
|
9
|
+
# find_elements :uiautomation, 'elements()
|
|
10
|
+
# ```
|
|
11
|
+
#
|
|
12
|
+
# @!method ios_predicate_string_find
|
|
13
|
+
# find_element/s can be used with a [Predicates](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html)
|
|
14
|
+
#
|
|
15
|
+
# ```ruby
|
|
16
|
+
# find_elements :predicate, "isWDVisible == 1"
|
|
17
|
+
# find_elements :predicate, 'wdName == "Buttons"'
|
|
18
|
+
# find_elements :predicate, 'wdValue == "SearchBar" AND isWDDivisible == 1'
|
|
19
|
+
# ```
|
|
20
|
+
def self.extend
|
|
21
|
+
::Appium::Core::Base::SearchContext.add_finders(uiautomation: '-ios uiautomation')
|
|
22
|
+
::Appium::Core::Base::SearchContext.add_finders(predicate: '-ios predicate string')
|
|
23
|
+
end
|
|
24
|
+
end # class << self
|
|
25
|
+
end # module Ios
|
|
26
|
+
end # module Core
|
|
27
|
+
end # module Appium
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require_relative '../../ios'
|
|
2
|
+
|
|
3
|
+
module Appium
|
|
4
|
+
module Core
|
|
5
|
+
module Ios
|
|
6
|
+
module Uiautomation
|
|
7
|
+
module Bridge
|
|
8
|
+
def self.for(target)
|
|
9
|
+
Core::Ios::SearchContext.extend
|
|
10
|
+
target.extend Appium::Ios::Device
|
|
11
|
+
patch_webdriver_element
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Appium
|
|
2
|
+
module Core
|
|
3
|
+
module Ios
|
|
4
|
+
module Uiautomation
|
|
5
|
+
# @private
|
|
6
|
+
# class_eval inside a method because class Selenium::WebDriver::Element
|
|
7
|
+
# will trigger as soon as the file is required. in contrast a method
|
|
8
|
+
# will trigger only when invoked.
|
|
9
|
+
def patch_webdriver_element
|
|
10
|
+
Selenium::WebDriver::Element.class_eval do
|
|
11
|
+
# Cross platform way of entering text into a textfield
|
|
12
|
+
def type(text, driver = $driver)
|
|
13
|
+
driver.execute_script %(au.getElement('#{ref}').setValue('#{text}');)
|
|
14
|
+
end # def type
|
|
15
|
+
end # Selenium::WebDriver::Element.class_eval
|
|
16
|
+
end # def patch_webdriver_element
|
|
17
|
+
end # module Uiautomation
|
|
18
|
+
end # module Ios
|
|
19
|
+
end # module Core
|
|
20
|
+
end # module Appium
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative '../../ios_xcuitest'
|
|
2
|
+
|
|
3
|
+
module Appium
|
|
4
|
+
module Core
|
|
5
|
+
module Ios
|
|
6
|
+
module Xcuitest
|
|
7
|
+
module Bridge
|
|
8
|
+
def self.for(target)
|
|
9
|
+
Core::Ios::SearchContext.extend
|
|
10
|
+
Core::Ios::Xcuitest::SearchContext.extend
|
|
11
|
+
target.extend Appium::Ios::Device
|
|
12
|
+
target.extend Appium::Ios::Xcuitest::Device
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'base64'
|
|
2
|
-
|
|
3
1
|
module Appium
|
|
4
2
|
module Ios
|
|
5
3
|
module Xcuitest
|
|
@@ -30,9 +28,10 @@ module Appium
|
|
|
30
28
|
|
|
31
29
|
class << self
|
|
32
30
|
def extended(_mod)
|
|
33
|
-
::Appium::Device.extend_webdriver_with_forwardable
|
|
31
|
+
::Appium::Core::Device.extend_webdriver_with_forwardable
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
# Override
|
|
34
|
+
::Appium::Core::Device.add_endpoint_method(:hide_keyboard) do
|
|
36
35
|
def hide_keyboard(close_key = nil, strategy = nil)
|
|
37
36
|
option = {}
|
|
38
37
|
|
|
@@ -43,7 +42,8 @@ module Appium
|
|
|
43
42
|
end
|
|
44
43
|
end
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
# Override
|
|
46
|
+
::Appium::Core::Device.add_endpoint_method(:background_app) do
|
|
47
47
|
def background_app(duration = 0)
|
|
48
48
|
# https://github.com/appium/ruby_lib/issues/500, https://github.com/appium/appium/issues/7741
|
|
49
49
|
# `execute :background_app, {}, seconds: { timeout: duration_milli_sec }` works over Appium 1.6.4
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module Appium
|
|
2
|
-
module
|
|
3
|
-
module
|
|
4
|
-
module
|
|
5
|
-
|
|
2
|
+
module Core
|
|
3
|
+
module Ios
|
|
4
|
+
module Xcuitest
|
|
5
|
+
module SearchContext
|
|
6
6
|
# @!method ios_class_chain_find
|
|
7
7
|
# Only for XCUITest(WebDriverAgent)
|
|
8
8
|
# find_element/s can be used with a [class chain]( https://github.com/facebook/WebDriverAgent/wiki/Queries)
|
|
@@ -14,12 +14,16 @@ module Appium
|
|
|
14
14
|
# find_elements :class_chain, 'XCUIElementTypeWindow'
|
|
15
15
|
# # select the second last child of the second child window
|
|
16
16
|
# find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]'
|
|
17
|
+
# # matching predicate. <code>`</code> is the mark.
|
|
18
|
+
# find_elements :class_chain, 'XCUIElementTypeWindow[`visible = 1][`name = \"bla\"`]'
|
|
19
|
+
# # containing predicate. `$` is the mark.
|
|
20
|
+
# find_elements :class_chain, 'XCUIElementTypeWindow[$name = \"bla$$$bla\"$]'
|
|
17
21
|
# ```
|
|
18
|
-
def
|
|
19
|
-
::Appium::
|
|
22
|
+
def self.extend
|
|
23
|
+
::Appium::Core::Base::SearchContext.add_finders(class_chain: '-ios class chain')
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
|
-
end
|
|
23
|
-
end # module
|
|
24
|
-
end # module
|
|
26
|
+
end # class << self
|
|
27
|
+
end # module Ios
|
|
28
|
+
end # module Core
|
|
25
29
|
end # module Appium
|