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,56 @@
|
|
|
1
|
+
require_relative '../version'
|
|
2
|
+
|
|
3
|
+
module Appium
|
|
4
|
+
module Core
|
|
5
|
+
# Implement useful features for element.
|
|
6
|
+
class Selenium::WebDriver::Element # rubocop:disable Style/ClassAndModuleChildren
|
|
7
|
+
# Note: For testing .text should be used over value, and name.
|
|
8
|
+
|
|
9
|
+
# Returns the value attribute
|
|
10
|
+
#
|
|
11
|
+
# Fixes NoMethodError: undefined method `value' for Selenium::WebDriver::Element
|
|
12
|
+
def value
|
|
13
|
+
attribute :value
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Returns the name attribute
|
|
17
|
+
#
|
|
18
|
+
# Fixes NoMethodError: undefined method `name' for Selenium::WebDriver::Element
|
|
19
|
+
def name
|
|
20
|
+
attribute :name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Enable access to iOS accessibility label
|
|
24
|
+
# accessibility identifier is supported as 'name'
|
|
25
|
+
def label
|
|
26
|
+
attribute :label
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Alias for type
|
|
30
|
+
alias type send_keys
|
|
31
|
+
|
|
32
|
+
# For use with mobile tap.
|
|
33
|
+
#
|
|
34
|
+
# ```ruby
|
|
35
|
+
# execute_script 'mobile: tap', :x => 0.0, :y => 0.98
|
|
36
|
+
# ```
|
|
37
|
+
#
|
|
38
|
+
# @return [OpenStruct] the relative x, y in a struct. ex: { x: 0.50, y: 0.20 }
|
|
39
|
+
def location_rel(driver = $driver)
|
|
40
|
+
rect = self.rect
|
|
41
|
+
location_x = rect.x.to_f
|
|
42
|
+
location_y = rect.y.to_f
|
|
43
|
+
|
|
44
|
+
size_width = rect.width.to_f
|
|
45
|
+
size_height = rect.height.to_f
|
|
46
|
+
|
|
47
|
+
center_x = location_x + (size_width / 2.0)
|
|
48
|
+
center_y = location_y + (size_height / 2.0)
|
|
49
|
+
|
|
50
|
+
w = driver.window_size
|
|
51
|
+
OpenStruct.new(x: "#{center_x} / #{w.width.to_f}",
|
|
52
|
+
y: "#{center_y} / #{w.height.to_f}")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end # module Core
|
|
56
|
+
end # module Appium
|
data/lib/appium_lib/driver.rb
CHANGED
|
@@ -1,56 +1,3 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
|
-
require 'ap'
|
|
3
|
-
require 'selenium-webdriver'
|
|
4
|
-
require 'nokogiri'
|
|
5
|
-
|
|
6
|
-
# base
|
|
7
|
-
require_relative 'capabilities'
|
|
8
|
-
|
|
9
|
-
# common
|
|
10
|
-
require_relative 'common/helper'
|
|
11
|
-
require_relative 'common/wait'
|
|
12
|
-
require_relative 'common/patch'
|
|
13
|
-
require_relative 'common/version'
|
|
14
|
-
require_relative 'common/error'
|
|
15
|
-
require_relative 'common/search_context'
|
|
16
|
-
require_relative 'common/command'
|
|
17
|
-
require_relative 'common/element/window'
|
|
18
|
-
|
|
19
|
-
# ios
|
|
20
|
-
require_relative 'ios/helper'
|
|
21
|
-
require_relative 'ios/patch'
|
|
22
|
-
require_relative 'ios/errors'
|
|
23
|
-
|
|
24
|
-
require_relative 'ios/element/alert'
|
|
25
|
-
require_relative 'ios/element/button'
|
|
26
|
-
require_relative 'ios/element/generic'
|
|
27
|
-
require_relative 'ios/element/textfield'
|
|
28
|
-
require_relative 'ios/element/text'
|
|
29
|
-
require_relative 'ios/mobile_methods'
|
|
30
|
-
|
|
31
|
-
require_relative 'ios/xcuitest'
|
|
32
|
-
|
|
33
|
-
# android
|
|
34
|
-
require_relative 'android/helper'
|
|
35
|
-
require_relative 'android/patch'
|
|
36
|
-
require_relative 'android/client_xpath'
|
|
37
|
-
require_relative 'android/element/alert'
|
|
38
|
-
require_relative 'android/element/button'
|
|
39
|
-
require_relative 'android/element/generic'
|
|
40
|
-
require_relative 'android/element/textfield'
|
|
41
|
-
require_relative 'android/element/text'
|
|
42
|
-
require_relative 'android/mobile_methods'
|
|
43
|
-
|
|
44
|
-
require_relative 'android/device'
|
|
45
|
-
|
|
46
|
-
# android - uiautomator2
|
|
47
|
-
require_relative 'android/uiautomator2'
|
|
48
|
-
|
|
49
|
-
# device methods
|
|
50
|
-
require_relative 'device/device'
|
|
51
|
-
require_relative 'device/touch_actions'
|
|
52
|
-
require_relative 'device/multi_touch'
|
|
53
|
-
|
|
54
1
|
# Fix uninitialized constant Minitest (NameError)
|
|
55
2
|
module Minitest
|
|
56
3
|
# Fix superclass mismatch for class Spec
|
|
@@ -62,206 +9,11 @@ module Minitest
|
|
|
62
9
|
end
|
|
63
10
|
end
|
|
64
11
|
|
|
12
|
+
require_relative 'core/core'
|
|
13
|
+
|
|
65
14
|
module Appium
|
|
66
15
|
REQUIRED_VERSION_XCUITEST = '1.6.0'.freeze
|
|
67
16
|
|
|
68
|
-
# Load arbitrary text ([toml format](https://github.com/toml-lang/toml))
|
|
69
|
-
# The toml is parsed by https://github.com/fbernier/tomlrb .
|
|
70
|
-
#
|
|
71
|
-
# ```
|
|
72
|
-
# [caps]
|
|
73
|
-
# app = "path/to/app"
|
|
74
|
-
#
|
|
75
|
-
# [appium_lib]
|
|
76
|
-
# port = 8080
|
|
77
|
-
# ```
|
|
78
|
-
#
|
|
79
|
-
# :app is expanded
|
|
80
|
-
# :require is expanded
|
|
81
|
-
# all keys are converted to symbols
|
|
82
|
-
#
|
|
83
|
-
# @param opts [Hash] file: '/path/to/appium.txt', verbose: true
|
|
84
|
-
# @return [hash] the symbolized hash with updated :app and :require keys
|
|
85
|
-
def self.load_settings(opts = {})
|
|
86
|
-
raise 'opts must be a hash' unless opts.is_a? Hash
|
|
87
|
-
raise 'opts must not be empty' if opts.empty?
|
|
88
|
-
|
|
89
|
-
toml = opts[:file]
|
|
90
|
-
raise 'Must pass a capability file which has [caps] and [appium_lib]' unless toml
|
|
91
|
-
verbose = opts.fetch :verbose, false
|
|
92
|
-
|
|
93
|
-
Appium::Logger.info "appium settings path: #{toml}" if verbose
|
|
94
|
-
|
|
95
|
-
toml_exists = File.exist? toml
|
|
96
|
-
Appium::Logger.info "Exists? #{toml_exists}" if verbose
|
|
97
|
-
|
|
98
|
-
raise "toml doesn't exist #{toml}" unless toml_exists
|
|
99
|
-
require 'tomlrb'
|
|
100
|
-
Appium::Logger.info "Loading #{toml}" if verbose
|
|
101
|
-
|
|
102
|
-
data = Tomlrb.load_file(toml, symbolize_keys: true)
|
|
103
|
-
if verbose
|
|
104
|
-
Appium::Logger.ap_info data unless data.empty?
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
if data && data[:caps] && data[:caps][:app] && !data[:caps][:app].empty?
|
|
108
|
-
data[:caps][:app] = Appium::Driver.absolute_app_path data
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
if data && data[:appium_lib] && data[:appium_lib][:require]
|
|
112
|
-
parent_dir = File.dirname toml
|
|
113
|
-
data[:appium_lib][:require] = expand_required_files(parent_dir, data[:appium_lib][:require])
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
data
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
class << self
|
|
120
|
-
# rubocop:disable Style/Alias
|
|
121
|
-
alias_method :load_appium_txt, :load_settings
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# @param [String] base_dir parent directory of loaded appium.txt (toml)
|
|
125
|
-
# @param [String] file_paths
|
|
126
|
-
# @return [Array] list of require files as an array, nil if require doesn't exist
|
|
127
|
-
def self.expand_required_files(base_dir, file_paths)
|
|
128
|
-
# ensure files are absolute
|
|
129
|
-
Array(file_paths).map! do |f|
|
|
130
|
-
file = File.exist?(f) ? f : File.join(base_dir, f)
|
|
131
|
-
file = File.expand_path file
|
|
132
|
-
|
|
133
|
-
File.exist?(file) ? file : nil
|
|
134
|
-
end
|
|
135
|
-
file_paths.compact! # remove nils
|
|
136
|
-
|
|
137
|
-
files = []
|
|
138
|
-
|
|
139
|
-
# now expand dirs
|
|
140
|
-
file_paths.each do |item|
|
|
141
|
-
unless File.directory? item
|
|
142
|
-
# save file
|
|
143
|
-
files << item
|
|
144
|
-
next # only look inside folders
|
|
145
|
-
end
|
|
146
|
-
Dir.glob(File.expand_path(File.join(item, '**', '*.rb'))) do |f|
|
|
147
|
-
# do not add folders to the file list
|
|
148
|
-
files << File.expand_path(f) unless File.directory? f
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
files
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# convert all keys (including nested) to symbols
|
|
156
|
-
#
|
|
157
|
-
# based on deep_symbolize_keys & deep_transform_keys from rails
|
|
158
|
-
# https://github.com/rails/docrails/blob/a3b1105ada3da64acfa3843b164b14b734456a50/activesupport/lib/active_support/core_ext/hash/keys.rb#L84
|
|
159
|
-
def self.symbolize_keys(hash)
|
|
160
|
-
raise 'symbolize_keys requires a hash' unless hash.is_a? Hash
|
|
161
|
-
result = {}
|
|
162
|
-
hash.each do |key, value|
|
|
163
|
-
key = key.to_sym rescue key # rubocop:disable Style/RescueModifier
|
|
164
|
-
result[key] = value.is_a?(Hash) ? symbolize_keys(value) : value
|
|
165
|
-
end
|
|
166
|
-
result
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# This method is intended to work with page objects that share
|
|
170
|
-
# a common module. For example, Page::HomePage, Page::SignIn
|
|
171
|
-
# those could be promoted on with Appium.promote_singleton_appium_methods Page
|
|
172
|
-
#
|
|
173
|
-
# If you are promoting on an individual class then you should use
|
|
174
|
-
# Appium.promote_appium_methods instead. The singleton method is intended
|
|
175
|
-
# only for the shared module use case.
|
|
176
|
-
#
|
|
177
|
-
# if modules is a module instead of an array, then the constants of
|
|
178
|
-
# that module are promoted on.
|
|
179
|
-
# otherwise, the array of modules will be used as the promotion target.
|
|
180
|
-
def self.promote_singleton_appium_methods(modules, driver = $driver)
|
|
181
|
-
raise 'Global $driver is nil' if driver.nil?
|
|
182
|
-
|
|
183
|
-
target_modules = []
|
|
184
|
-
|
|
185
|
-
if modules.is_a? Module
|
|
186
|
-
modules.constants.each do |sub_module|
|
|
187
|
-
target_modules << modules.const_get(sub_module)
|
|
188
|
-
end
|
|
189
|
-
else
|
|
190
|
-
raise 'modules must be a module or an array' unless modules.is_a? Array
|
|
191
|
-
target_modules = modules
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
target_modules.each do |const|
|
|
195
|
-
# noinspection RubyResolve
|
|
196
|
-
# rubocop:disable Style/MultilineIfModifier
|
|
197
|
-
driver.public_methods(false).each do |m|
|
|
198
|
-
const.send(:define_singleton_method, m) do |*args, &block|
|
|
199
|
-
begin
|
|
200
|
-
super(*args, &block) # promote.rb
|
|
201
|
-
rescue NoMethodError, ArgumentError
|
|
202
|
-
driver.send m, *args, &block if driver.respond_to?(m)
|
|
203
|
-
end
|
|
204
|
-
# override unless there's an existing method with matching arity
|
|
205
|
-
end unless const.respond_to?(m) && const.method(m).arity == driver.method(m).arity
|
|
206
|
-
end
|
|
207
|
-
# rubocop:enable Style/MultilineIfModifier
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
##
|
|
212
|
-
# Promote appium methods to class instance methods
|
|
213
|
-
#
|
|
214
|
-
# @param class_array [Array<Class>] An array of classes
|
|
215
|
-
#
|
|
216
|
-
# To promote methods to all classes:
|
|
217
|
-
#
|
|
218
|
-
# ```ruby
|
|
219
|
-
# Appium.promote_appium_methods Object
|
|
220
|
-
# ```
|
|
221
|
-
#
|
|
222
|
-
# It's better to promote on specific classes instead of Object
|
|
223
|
-
#
|
|
224
|
-
# ```ruby
|
|
225
|
-
# # promote on rspec
|
|
226
|
-
# Appium.promote_appium_methods RSpec::Core::ExampleGroup
|
|
227
|
-
# ```
|
|
228
|
-
#
|
|
229
|
-
# ```ruby
|
|
230
|
-
# # promote on minispec
|
|
231
|
-
# Appium.promote_appium_methods Minitest::Spec
|
|
232
|
-
# ```
|
|
233
|
-
def self.promote_appium_methods(class_array, driver = $driver)
|
|
234
|
-
raise 'Driver is nil' if driver.nil?
|
|
235
|
-
# Wrap single class into an array
|
|
236
|
-
class_array = [class_array] unless class_array.class == Array
|
|
237
|
-
# Promote Appium driver methods to class instance methods.
|
|
238
|
-
class_array.each do |klass|
|
|
239
|
-
driver.public_methods(false).each do |m|
|
|
240
|
-
klass.class_eval do
|
|
241
|
-
define_method m do |*args, &block|
|
|
242
|
-
begin
|
|
243
|
-
# Prefer existing method.
|
|
244
|
-
# super will invoke method missing on driver
|
|
245
|
-
super(*args, &block)
|
|
246
|
-
|
|
247
|
-
# minitest also defines a name method,
|
|
248
|
-
# so rescue argument error
|
|
249
|
-
# and call the name method on $driver
|
|
250
|
-
rescue NoMethodError, ArgumentError
|
|
251
|
-
driver.send m, *args, &block if driver.respond_to?(m)
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
nil # return nil
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
def self.selenium_webdriver_version_more?(version)
|
|
261
|
-
require 'rubygems'
|
|
262
|
-
Gem.loaded_specs['selenium-webdriver'].version >= Gem::Version.new(version)
|
|
263
|
-
end
|
|
264
|
-
|
|
265
17
|
class Driver
|
|
266
18
|
# attr readers are promoted to global scope. To avoid clobbering, they're
|
|
267
19
|
# made available via the driver_attributes method
|
|
@@ -270,52 +22,41 @@ module Appium
|
|
|
270
22
|
|
|
271
23
|
# The amount to sleep in seconds before every webdriver http call.
|
|
272
24
|
attr_accessor :global_webdriver_http_sleep
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
attr_reader :custom_url
|
|
277
|
-
# Export session id to textfile in /tmp for 3rd party tools
|
|
278
|
-
attr_reader :export_session
|
|
279
|
-
# Default wait time for elements to appear
|
|
280
|
-
# Returns the default client side wait.
|
|
281
|
-
# This value is independent of what the server is using
|
|
282
|
-
# @return [Integer]
|
|
283
|
-
attr_reader :default_wait
|
|
25
|
+
|
|
26
|
+
# SauceLab's settings
|
|
27
|
+
attr_reader :sauce
|
|
284
28
|
# Username for use on Sauce Labs. Set `false` to disable Sauce, even when SAUCE_USERNAME is in ENV.
|
|
29
|
+
# same as @sauce.username
|
|
285
30
|
attr_reader :sauce_username
|
|
286
31
|
# Access Key for use on Sauce Labs. Set `false` to disable Sauce, even when SAUCE_ACCESS_KEY is in ENV.
|
|
32
|
+
# same as @sauce.access_key
|
|
287
33
|
attr_reader :sauce_access_key
|
|
288
34
|
# Override the Sauce Appium endpoint to allow e.g. TestObject tests
|
|
35
|
+
# same as @sauce.endpoint
|
|
289
36
|
attr_reader :sauce_endpoint
|
|
290
|
-
|
|
37
|
+
|
|
38
|
+
# from Core
|
|
39
|
+
attr_reader :caps
|
|
40
|
+
attr_reader :custom_url
|
|
41
|
+
attr_reader :export_session
|
|
42
|
+
attr_reader :default_wait
|
|
291
43
|
attr_reader :appium_port
|
|
292
|
-
# Device type to request from the appium server
|
|
293
44
|
attr_reader :appium_device
|
|
294
|
-
# Automation name sent to appium server or received from server
|
|
295
|
-
# If automation_name is nil, it is not set both client side and server side.
|
|
296
45
|
attr_reader :automation_name
|
|
46
|
+
attr_reader :listener
|
|
47
|
+
attr_reader :http_client
|
|
48
|
+
attr_reader :appium_wait_timeout
|
|
49
|
+
attr_reader :appium_wait_interval
|
|
50
|
+
|
|
297
51
|
# Appium's server version
|
|
298
52
|
attr_reader :appium_server_status
|
|
299
53
|
# Boolean debug mode for the Appium Ruby bindings
|
|
300
54
|
attr_reader :appium_debug
|
|
301
|
-
# instance of AbstractEventListener for logging support
|
|
302
|
-
attr_reader :listener
|
|
303
55
|
# Returns the driver
|
|
304
56
|
# @return [Driver] the driver
|
|
305
57
|
attr_reader :driver
|
|
306
|
-
#
|
|
307
|
-
|
|
308
|
-
attr_reader :http_client
|
|
309
|
-
# Return a time wait timeout
|
|
310
|
-
# Wait time for ::Appium::Common.wait or ::Appium::Common.wait_true.
|
|
311
|
-
# Provide Appium::Drive like { appium_lib: { wait_timeout: 20 } }
|
|
312
|
-
# @return [Integer]
|
|
313
|
-
attr_reader :appium_wait_timeout
|
|
314
|
-
# Return a time wait timeout
|
|
315
|
-
# Wait interval time for ::Appium::Common.wait or ::Appium::Common.wait_true.
|
|
316
|
-
# Provide Appium::Drive like { appium_lib: { wait_interval: 20 } }
|
|
317
|
-
# @return [Integer]
|
|
318
|
-
attr_reader :appium_wait_interval
|
|
58
|
+
# Instance of Appium::Core::Driver
|
|
59
|
+
attr_reader :core
|
|
319
60
|
|
|
320
61
|
# Creates a new driver. The driver is defined as global scope by default.
|
|
321
62
|
# We can avoid defining global driver.
|
|
@@ -338,7 +79,7 @@ module Appium
|
|
|
338
79
|
# wait_timeout: 30
|
|
339
80
|
# }
|
|
340
81
|
# }
|
|
341
|
-
# Appium::Driver.new(opts).start_driver
|
|
82
|
+
# Appium::Driver.new(opts, true).start_driver
|
|
342
83
|
#
|
|
343
84
|
# # Start Android driver with global scope
|
|
344
85
|
# opts = {
|
|
@@ -351,7 +92,7 @@ module Appium
|
|
|
351
92
|
# wait_interval: 1
|
|
352
93
|
# }
|
|
353
94
|
# }
|
|
354
|
-
# Appium::Driver.new(opts).start_driver
|
|
95
|
+
# Appium::Driver.new(opts, true).start_driver
|
|
355
96
|
#
|
|
356
97
|
# # Start iOS driver without global scope
|
|
357
98
|
# opts = {
|
|
@@ -370,6 +111,7 @@ module Appium
|
|
|
370
111
|
# @param global_driver [Bool] A bool require global driver before initialize.
|
|
371
112
|
# @return [Driver]
|
|
372
113
|
def initialize(opts = {}, global_driver = nil)
|
|
114
|
+
# TODO: set `global_driver = false` by default in the future.
|
|
373
115
|
if global_driver.nil?
|
|
374
116
|
warn '[DEPRECATION] Appium::Driver.new(opts) will not generate global driver by default.' \
|
|
375
117
|
'If you would like to generate the global driver dy default, ' \
|
|
@@ -382,68 +124,41 @@ module Appium
|
|
|
382
124
|
end
|
|
383
125
|
raise 'opts must be a hash' unless opts.is_a? Hash
|
|
384
126
|
|
|
385
|
-
|
|
386
|
-
@caps = Capabilities.init_caps_for_appium(opts[:caps] || {})
|
|
127
|
+
@core = Appium::Core.for(self, opts)
|
|
387
128
|
|
|
388
|
-
|
|
129
|
+
opts = Appium.symbolize_keys opts
|
|
130
|
+
appium_lib_opts = opts[:appium_lib] || {}
|
|
389
131
|
|
|
390
|
-
|
|
132
|
+
@caps = @core.caps
|
|
133
|
+
@custom_url = @core.custom_url
|
|
134
|
+
@export_session = @core.export_session
|
|
135
|
+
@default_wait = @core.default_wait
|
|
136
|
+
@appium_port = @core.port
|
|
137
|
+
@appium_wait_timeout = @core.wait_timeout
|
|
138
|
+
@appium_wait_interval = @core.wait_interval
|
|
139
|
+
@listener = @core.listener
|
|
140
|
+
@appium_device = @core.device
|
|
141
|
+
@automation_name = @core.automation_name
|
|
391
142
|
|
|
392
|
-
#
|
|
393
|
-
|
|
394
|
-
if @caps && @caps[:app] && !@caps[:app].empty?
|
|
395
|
-
@caps[:app] = self.class.absolute_app_path opts
|
|
396
|
-
end
|
|
143
|
+
# override opts[:app] if sauce labs
|
|
144
|
+
set_app_path(opts)
|
|
397
145
|
|
|
398
|
-
#
|
|
399
|
-
@
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
@automation_name = @caps[:automationName] if @caps[:automationName]
|
|
403
|
-
@automation_name = if @automation_name
|
|
404
|
-
@automation_name.is_a?(Symbol) ? @automation_name : @automation_name.downcase.strip.intern
|
|
405
|
-
end
|
|
146
|
+
# enable debug patch
|
|
147
|
+
@appium_debug = appium_lib_opts.fetch :debug, !!defined?(Pry)
|
|
148
|
+
set_sauce_related_values(appium_lib_opts)
|
|
406
149
|
|
|
407
|
-
#
|
|
150
|
+
# Extend Common methods
|
|
408
151
|
extend Appium::Common
|
|
409
|
-
extend Appium::Device
|
|
410
|
-
|
|
411
|
-
if device_is_android?
|
|
412
|
-
extend Appium::Android
|
|
413
|
-
extend Appium::Android::Device
|
|
414
|
-
if automation_name_is_uiautomator2?
|
|
415
|
-
extend Appium::Android::Uiautomator2
|
|
416
|
-
extend Appium::Android::Uiautomator2::Helper
|
|
417
|
-
extend Appium::Android::Uiautomator2::Element
|
|
418
|
-
end
|
|
419
|
-
else
|
|
420
|
-
extend Appium::Ios
|
|
421
|
-
if automation_name_is_xcuitest?
|
|
422
|
-
extend Appium::Ios::Xcuitest
|
|
423
|
-
extend Appium::Ios::Xcuitest::SearchContext
|
|
424
|
-
extend Appium::Ios::Xcuitest::Command
|
|
425
|
-
extend Appium::Ios::Xcuitest::Helper
|
|
426
|
-
extend Appium::Ios::Xcuitest::Gesture
|
|
427
|
-
extend Appium::Ios::Xcuitest::Device
|
|
428
|
-
extend Appium::Ios::Xcuitest::Element
|
|
429
|
-
end
|
|
430
|
-
end
|
|
431
152
|
|
|
432
|
-
#
|
|
433
|
-
|
|
153
|
+
# Extend each driver's methods
|
|
154
|
+
extend_for(device: @core.device, automation_name: @core.automation_name)
|
|
434
155
|
|
|
435
156
|
# for command
|
|
436
|
-
patch_remote_driver_commands
|
|
437
|
-
|
|
438
|
-
# enable debug patch
|
|
439
|
-
# !!'constant' == true
|
|
440
|
-
@appium_debug = appium_lib_opts.fetch :debug, !!defined?(Pry)
|
|
441
157
|
|
|
442
158
|
if @appium_debug
|
|
443
159
|
Appium::Logger.ap_debug opts unless opts.empty?
|
|
444
160
|
Appium::Logger.debug "Debug is: #{@appium_debug}"
|
|
445
|
-
Appium::Logger.debug "Device is: #{@
|
|
446
|
-
patch_webdriver_bridge
|
|
161
|
+
Appium::Logger.debug "Device is: #{@core.device}"
|
|
447
162
|
end
|
|
448
163
|
|
|
449
164
|
# Save global reference to last created Appium driver for top level methods.
|
|
@@ -454,27 +169,47 @@ module Appium
|
|
|
454
169
|
|
|
455
170
|
private
|
|
456
171
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
172
|
+
# @private
|
|
173
|
+
def extend_for(device:, automation_name:)
|
|
174
|
+
case device
|
|
175
|
+
when :android
|
|
176
|
+
case automation_name
|
|
177
|
+
when :uiautomator2
|
|
178
|
+
::Appium::Android::Uiautomator2::Bridge.for(self)
|
|
179
|
+
else # default and UiAutomator
|
|
180
|
+
::Appium::Android::Bridge.for(self)
|
|
181
|
+
end
|
|
182
|
+
when :ios
|
|
183
|
+
case automation_name
|
|
184
|
+
when :xcuitest
|
|
185
|
+
::Appium::Ios::Xcuitest::Bridge.for(self)
|
|
186
|
+
else # default and UIAutomation
|
|
187
|
+
::Appium::Ios::Bridge.for(self)
|
|
188
|
+
end
|
|
189
|
+
when :mac
|
|
190
|
+
# no Mac specific extentions
|
|
191
|
+
Appium::Logger.debug('mac')
|
|
192
|
+
when :windows
|
|
193
|
+
# no windows specific extentions
|
|
194
|
+
Appium::Logger.debug('windows')
|
|
195
|
+
else
|
|
196
|
+
Appium::Logger.warn('no device matched')
|
|
197
|
+
end
|
|
198
|
+
end
|
|
461
199
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
@
|
|
465
|
-
@sauce_access_key = nil if !@sauce_access_key || (@sauce_access_key.is_a?(String) && @sauce_access_key.empty?)
|
|
466
|
-
@sauce_endpoint = appium_lib_opts.fetch :sauce_endpoint, ENV['SAUCE_ENDPOINT']
|
|
467
|
-
@sauce_endpoint = 'ondemand.saucelabs.com:443/wd/hub' if
|
|
468
|
-
!@sauce_endpoint || (@sauce_endpoint.is_a?(String) && @sauce_endpoint.empty?)
|
|
200
|
+
# @private
|
|
201
|
+
def set_app_path(opts)
|
|
202
|
+
return unless @core.caps && @core.caps[:app] && !@core.caps[:app].empty?
|
|
469
203
|
|
|
470
|
-
@
|
|
471
|
-
|
|
472
|
-
@appium_wait_timeout = appium_lib_opts.fetch :wait_timeout, 30
|
|
473
|
-
@appium_wait_interval = appium_lib_opts.fetch :wait_interval, 0.5
|
|
204
|
+
@core.caps[:app] = self.class.absolute_app_path opts
|
|
205
|
+
end
|
|
474
206
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
@
|
|
207
|
+
# @private
|
|
208
|
+
def set_sauce_related_values(appium_lib_opts)
|
|
209
|
+
@sauce = Appium::SauceLabs.new(appium_lib_opts)
|
|
210
|
+
@sauce_username = @sauce.username
|
|
211
|
+
@sauce_access_key = @sauce.access_key
|
|
212
|
+
@sauce_endpoint = @sauce.endpoint
|
|
478
213
|
end
|
|
479
214
|
|
|
480
215
|
public
|
|
@@ -482,43 +217,51 @@ module Appium
|
|
|
482
217
|
# Returns a hash of the driver attributes
|
|
483
218
|
def driver_attributes
|
|
484
219
|
{
|
|
485
|
-
caps: @caps,
|
|
486
|
-
automation_name: @automation_name,
|
|
487
|
-
custom_url: @custom_url,
|
|
488
|
-
export_session: @export_session,
|
|
489
|
-
default_wait: @default_wait,
|
|
490
|
-
sauce_username: @
|
|
491
|
-
sauce_access_key: @
|
|
492
|
-
sauce_endpoint: @
|
|
493
|
-
port: @
|
|
494
|
-
device: @
|
|
220
|
+
caps: @core.caps,
|
|
221
|
+
automation_name: @core.automation_name,
|
|
222
|
+
custom_url: @core.custom_url,
|
|
223
|
+
export_session: @core.export_session,
|
|
224
|
+
default_wait: @core.default_wait,
|
|
225
|
+
sauce_username: @sauce.username,
|
|
226
|
+
sauce_access_key: @sauce.access_key,
|
|
227
|
+
sauce_endpoint: @sauce.endpoint,
|
|
228
|
+
port: @core.port,
|
|
229
|
+
device: @core.device,
|
|
495
230
|
debug: @appium_debug,
|
|
496
231
|
listener: @listener,
|
|
497
|
-
wait_timeout: @
|
|
498
|
-
wait_interval: @
|
|
232
|
+
wait_timeout: @core.wait_timeout,
|
|
233
|
+
wait_interval: @core.wait_interval
|
|
499
234
|
}
|
|
500
235
|
end
|
|
501
236
|
|
|
502
237
|
def device_is_android?
|
|
503
|
-
@
|
|
238
|
+
@core.device == :android
|
|
504
239
|
end
|
|
505
240
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
241
|
+
def device_is_ios?
|
|
242
|
+
@core.device == :ios
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def device_is_windows?
|
|
246
|
+
@core.device == :windows
|
|
510
247
|
end
|
|
511
248
|
|
|
512
249
|
# Return true if automationName is 'uiautomator2'
|
|
513
250
|
# @return [Boolean]
|
|
514
251
|
def automation_name_is_uiautomator2?
|
|
515
|
-
!@automation_name.nil? && @automation_name == :uiautomator2
|
|
252
|
+
!@core.automation_name.nil? && @core.automation_name == :uiautomator2
|
|
516
253
|
end
|
|
517
254
|
|
|
518
255
|
# Return true if automationName is 'Espresso'
|
|
519
256
|
# @return [Boolean]
|
|
520
257
|
def automation_name_is_espresso?
|
|
521
|
-
!@automation_name.nil? && @automation_name == :espresso
|
|
258
|
+
!@core.automation_name.nil? && @core.automation_name == :espresso
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Return true if automationName is 'XCUITest'
|
|
262
|
+
# @return [Boolean]
|
|
263
|
+
def automation_name_is_xcuitest?
|
|
264
|
+
!@core.automation_name.nil? && @core.automation_name == :xcuitest
|
|
522
265
|
end
|
|
523
266
|
|
|
524
267
|
# Return true if the target Appium server is over REQUIRED_VERSION_XCUITEST.
|
|
@@ -528,7 +271,8 @@ module Appium
|
|
|
528
271
|
if automation_name_is_xcuitest? &&
|
|
529
272
|
!@appium_server_status.empty? &&
|
|
530
273
|
(@appium_server_status['build']['version'] < REQUIRED_VERSION_XCUITEST)
|
|
531
|
-
raise
|
|
274
|
+
raise(Appium::Core::Error::NotSupportedAppiumServer,
|
|
275
|
+
"XCUITest requires Appium version >= #{REQUIRED_VERSION_XCUITEST}")
|
|
532
276
|
end
|
|
533
277
|
true
|
|
534
278
|
end
|
|
@@ -544,23 +288,25 @@ module Appium
|
|
|
544
288
|
# }
|
|
545
289
|
# ```
|
|
546
290
|
#
|
|
547
|
-
# Returns blank hash for Selenium Grid since `remote_status` gets 500 error
|
|
548
|
-
#
|
|
549
|
-
# ```ruby
|
|
550
|
-
# {}
|
|
551
|
-
# ```
|
|
552
|
-
#
|
|
553
291
|
# @return [Hash]
|
|
554
292
|
def appium_server_version
|
|
555
|
-
|
|
293
|
+
@core.appium_server_version
|
|
556
294
|
rescue Selenium::WebDriver::Error::WebDriverError => ex
|
|
557
|
-
raise ::Appium::Error::ServerError unless ex.message.include?('content-type=""')
|
|
295
|
+
raise ::Appium::Core::Error::ServerError unless ex.message.include?('content-type=""')
|
|
558
296
|
# server (TestObject for instance) does not respond to status call
|
|
559
297
|
{}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Return the platform version as an array of integers
|
|
301
|
+
# @return [Array<Integer>]
|
|
302
|
+
def platform_version
|
|
303
|
+
@core.platform_version
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# @private
|
|
307
|
+
def ios_version
|
|
308
|
+
warn '[DEPRECATION] ios_version will be removed. Please use platform_version instead.'
|
|
309
|
+
platform_version
|
|
564
310
|
end
|
|
565
311
|
|
|
566
312
|
# Returns the client's version info
|
|
@@ -618,12 +364,9 @@ module Appium
|
|
|
618
364
|
# Get the server url
|
|
619
365
|
# @return [String] the server url
|
|
620
366
|
def server_url
|
|
621
|
-
return @custom_url if @custom_url
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
else
|
|
625
|
-
"http://127.0.0.1:#{@appium_port}/wd/hub"
|
|
626
|
-
end
|
|
367
|
+
return @core.custom_url if @core.custom_url
|
|
368
|
+
return @sauce.server_url if @sauce.sauce_server_url?
|
|
369
|
+
"http://127.0.0.1:#{@core.port}/wd/hub"
|
|
627
370
|
end
|
|
628
371
|
|
|
629
372
|
# Restarts the driver
|
|
@@ -640,21 +383,26 @@ module Appium
|
|
|
640
383
|
# @param png_save_path [String] the full path to save the png
|
|
641
384
|
# @return [nil]
|
|
642
385
|
def screenshot(png_save_path)
|
|
643
|
-
@
|
|
644
|
-
nil
|
|
386
|
+
@core.screenshot png_save_path
|
|
645
387
|
end
|
|
646
388
|
|
|
647
389
|
# Quits the driver
|
|
648
390
|
# @return [void]
|
|
649
391
|
def driver_quit
|
|
650
|
-
|
|
651
|
-
@driver.quit
|
|
652
|
-
rescue
|
|
653
|
-
nil
|
|
392
|
+
@core.quit_driver
|
|
654
393
|
end
|
|
394
|
+
alias quit_driver driver_quit
|
|
655
395
|
|
|
656
|
-
#
|
|
657
|
-
|
|
396
|
+
# Get the device window's size.
|
|
397
|
+
# @return [Selenium::WebDriver::Dimension]
|
|
398
|
+
#
|
|
399
|
+
# @example
|
|
400
|
+
# size = @driver.window_size
|
|
401
|
+
# size.width #=> Integer
|
|
402
|
+
# size.height #=> Integer
|
|
403
|
+
def window_size
|
|
404
|
+
@driver.window_size
|
|
405
|
+
end
|
|
658
406
|
|
|
659
407
|
# Creates a new global driver and quits the old one if it exists.
|
|
660
408
|
# You can customise http_client as the following
|
|
@@ -683,40 +431,23 @@ module Appium
|
|
|
683
431
|
# @option http_client_ops [Hash] :read_timeout Custom read timeout for http client.
|
|
684
432
|
# @return [Selenium::WebDriver] the new global driver
|
|
685
433
|
def start_driver(http_client_ops = { http_client: nil, open_timeout: 999_999, read_timeout: 999_999 })
|
|
686
|
-
|
|
687
|
-
open_timeout = http_client_ops.delete(:open_timeout)
|
|
688
|
-
read_timeout = http_client_ops.delete(:read_timeout)
|
|
434
|
+
driver_quit
|
|
689
435
|
|
|
690
|
-
|
|
691
|
-
|
|
436
|
+
# If automationName is set only in server side, then the following automation_name should be nil before
|
|
437
|
+
# starting driver.
|
|
438
|
+
automation_name = @core.automation_name
|
|
692
439
|
|
|
693
|
-
@
|
|
694
|
-
@http_client
|
|
440
|
+
@driver = @core.start_driver(server_url: server_url, http_client_ops: http_client_ops)
|
|
441
|
+
@http_client = @core.http_client
|
|
695
442
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
http_client: @http_client,
|
|
700
|
-
desired_capabilities: @caps,
|
|
701
|
-
url: server_url,
|
|
702
|
-
listener: @listener)
|
|
703
|
-
|
|
704
|
-
# Load touch methods.
|
|
705
|
-
@driver.extend Selenium::WebDriver::DriverExtensions::HasTouchScreen
|
|
706
|
-
@driver.extend Selenium::WebDriver::DriverExtensions::HasLocation
|
|
707
|
-
|
|
708
|
-
# export session
|
|
709
|
-
write_session_id(@driver.session_id) if @export_session
|
|
710
|
-
rescue Errno::ECONNREFUSED
|
|
711
|
-
raise "ERROR: Unable to connect to Appium. Is the server running on #{server_url}?"
|
|
712
|
-
end
|
|
443
|
+
# if automation_name was nil before start_driver, then re-extend driver specific methods
|
|
444
|
+
# to be able to extend correctly.
|
|
445
|
+
extend_for(device: @core.device, automation_name: @core.automation_name) if automation_name.nil?
|
|
713
446
|
|
|
714
447
|
@appium_server_status = appium_server_version
|
|
715
|
-
|
|
716
448
|
check_server_version_xcuitest
|
|
717
|
-
set_automation_name_if_nil
|
|
718
449
|
|
|
719
|
-
set_implicit_wait(@default_wait)
|
|
450
|
+
set_implicit_wait(@core.default_wait)
|
|
720
451
|
|
|
721
452
|
@driver
|
|
722
453
|
end
|
|
@@ -726,7 +457,7 @@ module Appium
|
|
|
726
457
|
@driver.manage.timeouts.implicit_wait = wait
|
|
727
458
|
rescue Selenium::WebDriver::Error::UnknownError => e
|
|
728
459
|
unless e.message.include?('The operation requested is not yet implemented by Espresso driver')
|
|
729
|
-
raise ::Appium::Error::ServerError
|
|
460
|
+
raise ::Appium::Core::Error::ServerError
|
|
730
461
|
end
|
|
731
462
|
{}
|
|
732
463
|
end
|
|
@@ -736,18 +467,18 @@ module Appium
|
|
|
736
467
|
@driver.manage.timeouts.implicit_wait = 0
|
|
737
468
|
end
|
|
738
469
|
|
|
739
|
-
# Set implicit wait. Default to @default_wait.
|
|
470
|
+
# Set implicit wait. Default to @core.default_wait.
|
|
740
471
|
#
|
|
741
472
|
# ```ruby
|
|
742
473
|
# set_wait 2
|
|
743
|
-
# set_wait # @default_wait
|
|
474
|
+
# set_wait # @core.default_wait
|
|
744
475
|
#
|
|
745
476
|
# ```
|
|
746
477
|
#
|
|
747
478
|
# @param timeout [Integer] the timeout in seconds
|
|
748
479
|
# @return [void]
|
|
749
480
|
def set_wait(timeout = nil)
|
|
750
|
-
timeout = @default_wait if timeout.nil?
|
|
481
|
+
timeout = @core.default_wait if timeout.nil?
|
|
751
482
|
@driver.manage.timeouts.implicit_wait = timeout
|
|
752
483
|
end
|
|
753
484
|
|
|
@@ -763,7 +494,7 @@ module Appium
|
|
|
763
494
|
# wait to after checking existence
|
|
764
495
|
# @yield The block to call
|
|
765
496
|
# @return [Boolean]
|
|
766
|
-
def exists(pre_check = 0, post_check = @default_wait)
|
|
497
|
+
def exists(pre_check = 0, post_check = @core.default_wait)
|
|
767
498
|
# do not uset set_wait here.
|
|
768
499
|
# it will cause problems with other methods reading the default_wait of 0
|
|
769
500
|
# which then gets converted to a 1 second wait.
|
|
@@ -793,17 +524,19 @@ module Appium
|
|
|
793
524
|
|
|
794
525
|
# Calls @driver.find_elements_with_appium
|
|
795
526
|
#
|
|
796
|
-
#
|
|
797
|
-
#
|
|
798
|
-
#
|
|
799
|
-
#
|
|
527
|
+
# @example
|
|
528
|
+
# ```ruby
|
|
529
|
+
# @driver = Appium::Driver.new(opts, false)
|
|
530
|
+
# @driver.find_elements :predicate, yyy
|
|
531
|
+
# ```
|
|
800
532
|
#
|
|
801
533
|
# If you call `Appium.promote_appium_methods`, you can call `find_elements` directly.
|
|
802
534
|
#
|
|
803
|
-
#
|
|
804
|
-
#
|
|
805
|
-
#
|
|
806
|
-
#
|
|
535
|
+
# @example
|
|
536
|
+
# ```ruby
|
|
537
|
+
# @driver = Appium::Driver.new(opts, false)
|
|
538
|
+
# @driver.find_elements :predicate, yyy
|
|
539
|
+
# ```
|
|
807
540
|
#
|
|
808
541
|
# If you call `Appium.promote_appium_methods`, you can call `find_elements` directly.
|
|
809
542
|
#
|
|
@@ -815,10 +548,11 @@ module Appium
|
|
|
815
548
|
|
|
816
549
|
# Calls @driver.find_element
|
|
817
550
|
#
|
|
818
|
-
#
|
|
819
|
-
#
|
|
820
|
-
#
|
|
821
|
-
#
|
|
551
|
+
# @example
|
|
552
|
+
# ```ruby
|
|
553
|
+
# @driver = Appium::Driver.new(opts, false)
|
|
554
|
+
# @driver.find_element :accessibility_id, zzz
|
|
555
|
+
# ```
|
|
822
556
|
#
|
|
823
557
|
# If you call `Appium.promote_appium_methods`, you can call `find_element` directly.
|
|
824
558
|
#
|
|
@@ -854,19 +588,13 @@ module Appium
|
|
|
854
588
|
|
|
855
589
|
private
|
|
856
590
|
|
|
591
|
+
# @private
|
|
857
592
|
def write_session_id(session_id)
|
|
858
593
|
File.open('/tmp/appium_lib_session', 'w') { |f| f.puts session_id }
|
|
859
594
|
rescue IOError => e
|
|
860
595
|
::Appium::Logger.warn e
|
|
861
596
|
nil
|
|
862
597
|
end
|
|
863
|
-
|
|
864
|
-
# If "automationName" is set only server side, this method set "automationName" attribute into @automation_name.
|
|
865
|
-
# Since @automation_name is set only client side before start_driver is called.
|
|
866
|
-
def set_automation_name_if_nil
|
|
867
|
-
return unless @automation_name.nil?
|
|
868
|
-
@automation_name = @driver.capabilities['automationName']
|
|
869
|
-
end
|
|
870
598
|
end # class Driver
|
|
871
599
|
end # module Appium
|
|
872
600
|
|