lib/appium_lib/driver.rb in appium_lib-9.5.0 vs lib/appium_lib/driver.rb in appium_lib-9.6.0
- old
+ new
@@ -22,12 +22,22 @@
require_relative 'ios/element/button'
require_relative 'ios/element/generic'
require_relative 'ios/element/textfield'
require_relative 'ios/element/text'
require_relative 'ios/mobile_methods'
-require_relative 'ios/xcuitest_gestures'
+# ios - xcuitest
+require_relative 'ios/xcuitest/element'
+require_relative 'ios/xcuitest/gestures'
+require_relative 'ios/xcuitest/mobile_methods'
+require_relative 'ios/xcuitest/device'
+require_relative 'ios/xcuitest/helper'
+require_relative 'ios/xcuitest/element/text'
+require_relative 'ios/xcuitest/element/textfield'
+require_relative 'ios/xcuitest/element/generic'
+require_relative 'ios/xcuitest/element/button'
+
# android
require_relative 'android/helper'
require_relative 'android/patch'
require_relative 'android/client_xpath'
require_relative 'android/element/alert'
@@ -35,10 +45,15 @@
require_relative 'android/element/generic'
require_relative 'android/element/textfield'
require_relative 'android/element/text'
require_relative 'android/mobile_methods'
+require_relative 'android/device'
+
+# android - uiautomator2
+require_relative 'android/uiautomator2/helper.rb'
+
# device methods
require_relative 'device/device'
require_relative 'device/touch_actions'
require_relative 'device/multi_touch'
@@ -166,12 +181,12 @@
# only for the shared module use case.
#
# if modules is a module instead of an array, then the constants of
# that module are promoted on.
# otherwise, the array of modules will be used as the promotion target.
- def self.promote_singleton_appium_methods(modules)
- raise 'Driver is nil' if $driver.nil?
+ def self.promote_singleton_appium_methods(modules, driver = $driver)
+ raise 'Global $driver is nil' if driver.nil?
target_modules = []
if modules.is_a? Module
modules.constants.each do |sub_module|
@@ -183,19 +198,19 @@
end
target_modules.each do |const|
# noinspection RubyResolve
# rubocop:disable Style/MultilineIfModifier
- $driver.public_methods(false).each do |m|
+ driver.public_methods(false).each do |m|
const.send(:define_singleton_method, m) do |*args, &block|
begin
super(*args, &block) # promote.rb
rescue NoMethodError, ArgumentError
- $driver.send m, *args, &block if $driver.respond_to?(m)
+ driver.send m, *args, &block if driver.respond_to?(m)
end
# override unless there's an existing method with matching arity
- end unless const.respond_to?(m) && const.method(m).arity == $driver.method(m).arity
+ end unless const.respond_to?(m) && const.method(m).arity == driver.method(m).arity
end
# rubocop:enable Style/MultilineIfModifier
end
end
@@ -219,17 +234,17 @@
#
# ```ruby
# # promote on minispec
# Appium.promote_appium_methods Minitest::Spec
# ```
- def self.promote_appium_methods(class_array)
- raise 'Driver is nil' if $driver.nil?
+ def self.promote_appium_methods(class_array, driver = $driver)
+ raise 'Driver is nil' if driver.nil?
# Wrap single class into an array
class_array = [class_array] unless class_array.class == Array
# Promote Appium driver methods to class instance methods.
class_array.each do |klass|
- $driver.public_methods(false).each do |m|
+ driver.public_methods(false).each do |m|
klass.class_eval do
define_method m do |*args, &block|
begin
# Prefer existing method.
# super will invoke method missing on driver
@@ -237,11 +252,11 @@
# minitest also defines a name method,
# so rescue argument error
# and call the name method on $driver
rescue NoMethodError, ArgumentError
- $driver.send m, *args, &block if $driver.respond_to?(m)
+ driver.send m, *args, &block if driver.respond_to?(m)
end
end
end
end
end
@@ -318,21 +333,22 @@
# Wait interval time for ::Appium::Common.wait or ::Appium::Common.wait_true.
# Provide Appium::Drive like { appium_lib: { wait_interval: 20 } }
# @return [Integer]
attr_reader :appium_wait_interval
- # Creates a new driver
+ # Creates a new driver. The driver is defined as global scope by default.
+ # We can avoid defining global driver.
#
# @example
#
# ```ruby
# require 'rubygems'
# require 'appium_lib'
#
# # platformName takes a string or a symbol.
#
- # # Start iOS driver
+ # # Start iOS driver with global scope
# opts = {
# caps: {
# platformName: :ios,
# app: '/path/to/MyiOS.app'
# },
@@ -340,11 +356,11 @@
# wait_timeout: 30
# }
# }
# Appium::Driver.new(opts).start_driver
#
- # # Start Android driver
+ # # Start Android driver with global scope
# opts = {
# caps: {
# platformName: :android,
# app: '/path/to/my.apk'
# },
@@ -352,17 +368,34 @@
# wait_timeout: 30,
# wait_interval: 1
# }
# }
# Appium::Driver.new(opts).start_driver
+ #
+ # # Start iOS driver without global scope
+ # opts = {
+ # caps: {
+ # platformName: :ios,
+ # app: '/path/to/MyiOS.app'
+ # },
+ # appium_lib: {
+ # wait_timeout: 30
+ # }
+ # }
+ # Appium::Driver.new(opts, false).start_driver
# ```
#
# @param opts [Object] A hash containing various options.
+ # @param global_driver [Bool] A bool require global driver before initialize.
# @return [Driver]
- def initialize(opts = {})
- # quit last driver
- $driver.driver_quit if $driver
+ def initialize(opts = {}, global_driver = true)
+ if global_driver
+ warn '[DEPRECATION] Appium::Driver.new(opts) will not generate global driver by default.' \
+ 'If you would like to generate the global driver dy default, ' \
+ 'please initialise driver with Appium::Driver.new(opts, true)'
+ $driver.driver_quit if $driver
+ end
raise 'opts must be a hash' unless opts.is_a? Hash
opts = Appium.symbolize_keys opts
@caps = Capabilities.init_caps_for_appium(opts[:caps] || {})
@@ -389,15 +422,23 @@
extend Appium::Common
extend Appium::Device
if device_is_android?
extend Appium::Android
+ extend Appium::Android::Device
+ if automation_name_is_uiautomator2?
+ extend Appium::Android::Uiautomator2::Helper
+ end
else
extend Appium::Ios
- if automation_name_is_xcuitest? # Override touch actions
+ if automation_name_is_xcuitest?
+ # Override touch actions and patch_webdriver_element
extend Appium::Ios::Xcuitest
+ extend Appium::Ios::Xcuitest::Helper
extend Appium::Ios::Xcuitest::Gesture
+ extend Appium::Ios::Xcuitest::Device
+ extend Appium::Ios::Xcuitest::Element
end
end
# apply os specific patches
patch_webdriver_element
@@ -415,11 +456,11 @@
Appium::Logger.debug "Device is: #{@appium_device}"
patch_webdriver_bridge
end
# Save global reference to last created Appium driver for top level methods.
- $driver = self
+ $driver = self if global_driver
self # return newly created driver
end
private
@@ -483,10 +524,16 @@
# @return [Boolean]
def automation_name_is_uiautomator2?
!@automation_name.nil? && @automation_name == :uiautomator2
end
+ # Return true if automationName is 'Espresso'
+ # @return [Boolean]
+ def automation_name_is_espresso?
+ !@automation_name.nil? && @automation_name == :espresso
+ end
+
# Return true if the target Appium server is over REQUIRED_VERSION_XCUITEST.
# If the Appium server is under REQUIRED_VERSION_XCUITEST, then error is raised.
# @return [Boolean]
def check_server_version_xcuitest
if automation_name_is_xcuitest? &&
@@ -615,10 +662,13 @@
@driver.quit
rescue
nil
end
+ # Alias for driver_quit
+ alias_method :quit_driver, :driver_quit
+
# Creates a new global driver and quits the old one if it exists.
# You can customise http_client as the following
#
# @example
# ```ruby
@@ -675,12 +725,22 @@
@appium_server_status = appium_server_version
check_server_version_xcuitest
set_automation_name_if_nil
- @driver.manage.timeouts.implicit_wait = @default_wait
+ set_implicit_wait(@default_wait)
@driver
+ end
+
+ # To ignore error for Espresso Driver
+ def set_implicit_wait(wait)
+ @driver.manage.timeouts.implicit_wait = wait
+ rescue Selenium::WebDriver::Error::UnknownError => e
+ unless e.message.include?('The operation requested is not yet implemented by Espresso driver')
+ raise ::Appium::Error::ServerError
+ end
+ {}
end
# Set implicit wait to zero.
def no_wait
@driver.manage.timeouts.implicit_wait = 0