class Appium::Driver

Attributes

appium_debug[R]

Boolean debug mode for the Appium Ruby bindings

appium_device[R]
appium_port[R]
appium_server_status[R]

Appium’s server version

appium_wait_interval[R]
appium_wait_timeout[R]
automation_name[R]
core[R]

Instance of Appium::Core::Driver

custom_url[R]
default_wait[R]
driver[R]

Returns the driver @return [Driver] the driver

global_webdriver_http_sleep[RW]

The amount to sleep in seconds before every webdriver http call.

http_client[R]
listener[R]
sauce[R]

SauceLab’s settings

sauce_access_key[R]

Access Key for use on Sauce Labs. Set ‘false` to disable Sauce, even when SAUCE_ACCESS_KEY is in ENV. same as @sauce.access_key

sauce_endpoint[R]

Override the Sauce Appium endpoint to allow e.g. TestObject tests same as @sauce.endpoint

sauce_username[R]

Username for use on Sauce Labs. Set ‘false` to disable Sauce, even when SAUCE_USERNAME is in ENV. same as @sauce.username

Public Class Methods

absolute_app_path(opts) click to toggle source
Deprecated

Converts app_path to an absolute path.

opts is the full options hash (caps and appium_lib). If server_url is set then the app path is used as is.

if app isn’t set then an error is raised.

@return [String] APP_PATH as an absolute path

# File lib/appium_lib/driver.rb, line 386
def self.absolute_app_path(opts)
  raise 'opts must be a hash' unless opts.is_a? Hash

  # FIXME: 'caps' and 'app' will be correct
  caps            = opts[:caps] || opts['caps'] || {}
  app_path        = caps[:app] || caps['app']
  raise 'absolute_app_path invoked and app is not set!' if app_path.nil? || app_path.empty?
  # Sauce storage API. http://saucelabs.com/docs/rest#storage
  return app_path if app_path.start_with? 'sauce-storage:'
  return app_path if app_path =~ URI::DEFAULT_PARSER.make_regexp # public URL for Sauce

  ::Appium::Logger.warn('[Deprecation] Converting the path to absolute path will be removed. ' \
                        'Please specify the full path which can be accessible from the appium server')

  absolute_app_path = File.expand_path app_path
  if File.exist? absolute_app_path
    absolute_app_path
  else
    ::Appium::Logger.info("Use #{app_path}")
    app_path
  end
end
new(opts = {}, global_driver = false) click to toggle source

Creates a new driver. The driver is defined as global scope by default. We can avoid defining global driver.

@example

require 'rubygems'
require 'appium_lib'

# platformName takes a string or a symbol.
# Start iOS driver with global scope
opts = {
         caps: {
           platformName: :ios,
           app: '/path/to/MyiOS.app'
         },
         appium_lib: {
           server_url: 'http://127.0.0.1:4723'
           wait_timeout: 30
         }
       }
appium_driver = Appium::Driver.new(opts, true)
appium_driver.start_driver

# Start Android driver with global scope
opts = {
         caps: {
           platformName: :android,
           app: '/path/to/my.apk'
         },
         appium_lib: {
           wait_timeout: 30,
           wait_interval: 1
         }
       }
appium_driver = Appium::Driver.new(opts, true)
appium_driver.start_driver

# Start iOS driver without global scope
opts = {
         caps: {
           platformName: :ios,
           app: '/path/to/MyiOS.app'
         },
         appium_lib: {
           wait_timeout: 30
         }
       }
appium_driver = Appium::Driver.new(opts, false)
appium_driver.start_driver

# Start iOS driver without global scope
opts = {
         caps: {
           platformName: :ios,
           app: '/path/to/MyiOS.app'
         },
         appium_lib: {
           wait_timeout: 30
         },
         global_driver: false
       }
appium_driver = Appium::Driver.new(opts)
appium_driver.start_driver

@param opts [Object] A hash containing various options. @param global_driver [Bool] A bool require global driver before initialize. @return [Driver]

# File lib/appium_lib/driver.rb, line 153
def initialize(opts = {}, global_driver = false)
  # Capybara can't put `global_driver` as the 2nd argument.
  global_driver = opts.delete :global_driver if global_driver.nil?

  $driver&.driver_quit if global_driver

  raise 'opts must be a hash' unless opts.is_a? Hash

  @core = ::Appium::Core.for(opts)
  extend ::Appium::Core::Device

  opts = Appium.symbolize_keys opts
  appium_lib_opts = opts[:appium_lib] || {}

  @caps = @core.caps
  @custom_url = @core.custom_url
  @default_wait = @core.default_wait || 0
  @appium_port = @core.port
  @appium_wait_timeout = @core.wait_timeout
  @appium_wait_interval = @core.wait_interval
  @listener = @core.listener
  @appium_device = @core.device
  @automation_name = @core.automation_name

  # Arrange the app capability. This must be after @core = ::Appium::Core.for(opts)
  set_app_path(opts)

  # enable debug patch
  @appium_debug = appium_lib_opts.fetch :debug, !!defined?(Pry) # rubocop:disable Style/DoubleNegation
  set_sauce_related_values(appium_lib_opts)

  # Extend Common methods
  extend Appium::Common
  extend Appium::Device

  # Extend each driver's methods
  extend_for(device: @core.device, automation_name: @core.automation_name)

  # for command

  if @appium_debug
    Appium::Logger.debug opts unless opts.empty?
    Appium::Logger.debug "Debug is: #{@appium_debug}"
    Appium::Logger.debug "Device is: #{@core.device}"
  end

  # Save global reference to last created Appium driver for top level methods.
  $driver = self if global_driver

  self # rubocop:disable Lint/Void # return newly created driver
end

Public Instance Methods

action() click to toggle source

An entry point to chain W3C actions Read www.rubydoc.info/github/appium/ruby_lib_core/Appium/Core/Base/Bridge/W3C#action-instance_method

@return [Selenium::WebDriver::PointerActions]

@example

element = find_element(:id, "some id")
action.click(element).perform # The `click` is a part of `PointerActions`
# File lib/appium_lib/driver.rb, line 331
def action
  @driver.action
end
appium_client_version() click to toggle source

Returns the client’s version info

@example

{
    "version" => "9.1.1"
}

@return [Hash]

# File lib/appium_lib/driver.rb, line 374
def appium_client_version
  { version: ::Appium::VERSION }
end
appium_server_version() click to toggle source

Returns the server’s version info

@example

{
  "build" => {
      "version" => "0.18.1",
      "revision" => "d242ebcfd92046a974347ccc3a28f0e898595198"
  }
}

@return [Hash]

# File lib/appium_lib/driver.rb, line 346
def appium_server_version
  @core.appium_server_version
rescue Selenium::WebDriver::Error::WebDriverError => ex
  raise ::Appium::Core::Error::ServerError unless ex.message.include?('content-type=""')

  # server (TestObject for instance) does not respond to status call
  {}
end
Also aliased as: remote_status
automation_name_is_espresso?() click to toggle source

Return true if automationName is ‘Espresso’ @return [Boolean]

# File lib/appium_lib/driver.rb, line 311
def automation_name_is_espresso?
  !@core.automation_name.nil? && @core.automation_name == :espresso
end
automation_name_is_uiautomator2?() click to toggle source

Return true if automationName is ‘uiautomator2’ @return [Boolean]

# File lib/appium_lib/driver.rb, line 305
def automation_name_is_uiautomator2?
  !@core.automation_name.nil? && @core.automation_name == :uiautomator2
end
automation_name_is_xcuitest?() click to toggle source

Return true if automationName is ‘XCUITest’ @return [Boolean]

# File lib/appium_lib/driver.rb, line 317
def automation_name_is_xcuitest?
  !@core.automation_name.nil? && @core.automation_name == :xcuitest
end
current_url() click to toggle source
# File lib/appium_lib/driver.rb, line 677
def current_url
  @driver.current_url
end
device_is_android?() click to toggle source
# File lib/appium_lib/driver.rb, line 291
def device_is_android?
  @core.device == :android
end
device_is_ios?() click to toggle source
# File lib/appium_lib/driver.rb, line 295
def device_is_ios?
  @core.device == :ios
end
device_is_windows?() click to toggle source
# File lib/appium_lib/driver.rb, line 299
def device_is_windows?
  @core.device == :windows
end
driver_attributes() click to toggle source

Returns a hash of the driver attributes

# File lib/appium_lib/driver.rb, line 273
def driver_attributes
  {
    caps:                @core.caps,
    automation_name:     @core.automation_name,
    custom_url:          @core.custom_url,
    default_wait:        @default_wait,
    sauce_username:      @sauce.username,
    sauce_access_key:    @sauce.access_key,
    sauce_endpoint:      @sauce.endpoint,
    port:                @core.port,
    device:              @core.device,
    debug:               @appium_debug,
    listener:            @listener,
    wait_timeout:        @core.wait_timeout,
    wait_interval:       @core.wait_interval
  }
end
driver_quit() click to toggle source

Quits the driver @return [void]

# File lib/appium_lib/driver.rb, line 454
def driver_quit
  @driver&.quit
  @driver = nil
rescue Selenium::WebDriver::Error::WebDriverError
  nil
end
Also aliased as: quit_driver
element_screenshot(element, png_save_path) click to toggle source

Takes a png screenshot of particular element’s area

@example

el = find_element :accessibility_id, zzz
element_screenshot el, '/tmp/hi.png'

@param [String] element Element take a screenshot @param [String] png_save_path the full path to save the png @return [File]

# File lib/appium_lib/driver.rb, line 447
def element_screenshot(element, png_save_path)
  @driver.take_element_screenshot element, png_save_path
  nil
end
execute_async_script(script, *args) click to toggle source

Wrap calling selenium webdrier APIs via ruby_core

Get the window handles of open browser windows

# File lib/appium_lib/driver.rb, line 620
def execute_async_script(script, *args)
  @driver.execute_async_script script, *args
end
execute_driver(script: '', type: 'webdriverio', timeout_ms: nil) click to toggle source

Run a set of script against the current session, allowing execution of many commands in one Appium request. Supports {webdriver.io/docs/api.html WebdriverIO} API so far. Please read {appium.io/docs/en/commands/session/execute-driver command API} for more details about acceptable scripts and the output.

@param [String] script The string consisting of the script itself @param [String] type The name of the script type.

Defaults to 'webdriverio'. Depends on server implementation which type is supported.

@param [Integer] timeout_ms The number of ‘ms` Appium should wait for the script to finish

before killing it due to timeout.

@return [Appium::Core::Base::Device::ExecuteDriver::Result] The script result parsed by

Appium::Core::Base::Device::ExecuteDriver::Result.

@raise [::Selenium::WebDriver::Error::UnknownError] If something error happens in the script.

It has the original message.

@example

script = <<~SCRIPT
  const status = await driver.status();
  console.warn('warning message');
  return [status];
SCRIPT
r = @@driver.execute_driver(script: script, type: 'webdriverio', timeout: 10_000)
r        #=> An instance of Appium::Core::Base::Device::ExecuteDriver::Result
r.result #=> The `result` key part as the result of the script
r.logs   #=> The `logs` key part as `{'log' => [], 'warn' => [], 'error' => []}`
# File lib/appium_lib/driver.rb, line 652
def execute_driver(script: '', type: 'webdriverio', timeout_ms: nil)
  @driver.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
end
execute_script(script, *args) click to toggle source

The same as @driver.execute_script @param [String] script The script to execute @param [*args] args The args to pass to the script @return [Object]

# File lib/appium_lib/driver.rb, line 612
def execute_script(script, *args)
  @driver.execute_script script, *args
end
exists(pre_check = 0, post_check = @default_wait) { || ... } click to toggle source

Returns existence of element.

Example:

exists { button(‘sign in’) } ? puts(‘true’) : puts(‘false’)

@param [Integer] pre_check The amount in seconds to set the

wait to before checking existence

@param [Integer] post_check The amount in seconds to set the

wait to after checking existence

@yield The block to call @return [Boolean]

# File lib/appium_lib/driver.rb, line 588
def exists(pre_check = 0, post_check = @default_wait)
  # do not uset set_wait here.
  # it will cause problems with other methods reading the default_wait of 0
  # which then gets converted to a 1 second wait.
  @driver.manage.timeouts.implicit_wait = pre_check
  # the element exists unless an error is raised.
  exists                                = true

  begin
    yield # search for element
  rescue StandardError
    exists = false # error means it's not there
  end

  # restore wait
  @driver.manage.timeouts.implicit_wait = post_check if post_check != pre_check

  exists
end
find_element(*args) click to toggle source

Calls @driver.find_element

@example

@driver = Appium::Driver.new(opts, false)
@driver.start_driver
@driver.find_element :accessibility_id, zzz

If you call ‘Appium.promote_appium_methods`, you can call `find_element` directly.

@param [*args] args The args to use @return [Element]

# File lib/appium_lib/driver.rb, line 730
def find_element(*args)
  @driver.find_element(*args)
end
find_element_by_image(png_img_path) click to toggle source

Return ImageElement if current view has a partial image

@param [String] png_img_path A path to a partial image you’d like to find

@return [::Appium::Core::ImageElement] @raise [::Appium::Core::Error::NoSuchElementError|::Appium::Core::Error::CoreError] No such element

@example

@driver.find_element_by_image './test/functional/data/test_element_image.png'
# File lib/appium_lib/driver.rb, line 745
def find_element_by_image(png_img_path)
  @driver.find_element_by_image(png_img_path)
end
find_elements(*args) click to toggle source

Calls @driver.find_elements_with_appium

@example

@driver = Appium::Driver.new(opts, false)
@driver.start_driver
@driver.find_elements :predicate, yyy

If you call ‘Appium.promote_appium_methods`, you can call `find_elements` directly.

@example

@driver = Appium::Driver.new(opts, false)
@driver.start_driver
@driver.find_elements :predicate, yyy

If you call ‘Appium.promote_appium_methods`, you can call `find_elements` directly.

@param [*args] args The args to use @return [Array<Element>] Array is empty when no elements are found.

# File lib/appium_lib/driver.rb, line 714
def find_elements(*args)
  @driver.find_elements(*args)
end
find_elements_by_image(png_img_paths) click to toggle source

Return ImageElement if current view has partial images

@param [[String]] png_img_paths Paths to a partial image you’d like to find

@return [[::Appium::Core::ImageElement]] @return [::Appium::Core::Error::CoreError]

@example

@driver.find_elements_by_image ['./test/functional/data/test_element_image.png']
# File lib/appium_lib/driver.rb, line 760
def find_elements_by_image(png_img_paths)
  @driver.find_elements_by_image(png_img_paths)
end
get(url) click to toggle source
# File lib/appium_lib/driver.rb, line 673
def get(url)
  @driver.get(url)
end
log_event(vendor:, event:) click to toggle source

@since Appium 1.16.0

Logs a custom event. The event is available via {::Appium::Core::Events#get}.

@param [String] vendor The vendor prefix for the event @param [String] event The name of event @return [nil]

@example

log_event vendor: 'appium', event: 'funEvent'

log_event = { vendor: 'appium', event: 'anotherEvent' }
log_events #=> {...., 'appium:funEvent' => [1572957315, 1572960305],
           #          'appium:anotherEvent' => 1572959315}
# File lib/appium_lib/driver.rb, line 796
def log_event(vendor:, event:)
  @driver.logs.event vendor: vendor, event: event
end
log_event=(log_event) click to toggle source
# File lib/appium_lib/driver.rb, line 800
def log_event=(log_event)
  unless log_event.is_a?(Hash)
    raise ::Appium::Core::Error::ArgumentError('log_event should be Hash like { vendor: "appium", event: "funEvent"}')
  end

  @driver.logs.event vendor: log_event[:vendor], event: log_event[:event]
end
log_events(type = nil) click to toggle source

@since Appium 1.16.0 Returns events with filtering with ‘type’. Defaults to all available events.

@param [String] type The type of events to get @return [Hash]

@example

log_events #=> {}
log_events #=> {'commands' => [{'cmd' => 123455, ....}], 'startTime' => 1572954894127, }
# File lib/appium_lib/driver.rb, line 819
def log_events(type = nil)
  @driver.logs.events(type)
end
manage() click to toggle source
# File lib/appium_lib/driver.rb, line 669
def manage
  @driver.manage
end
navigate() click to toggle source
no_wait() click to toggle source

Set implicit wait to zero.

# File lib/appium_lib/driver.rb, line 557
def no_wait
  @driver.manage.timeouts.implicit_wait = 0
end
platform_version() click to toggle source

Return the platform version as an array of integers @return [Array<Integer>]

# File lib/appium_lib/driver.rb, line 358
def platform_version
  return [] if @driver.nil?

  p_version = @driver.capabilities['platformVersion']
  p_version.split('.').map(&:to_i)
end
quit_driver()
Alias for: driver_quit
remote_status()
restart() click to toggle source

Restarts the driver @return [Driver] the driver

# File lib/appium_lib/driver.rb, line 420
def restart
  driver_quit
  start_driver
end
screenshot(png_save_path) click to toggle source

Takes a png screenshot and saves to the target path.

@example

screenshot '/tmp/hi.png'

@param png_save_path [String] the full path to save the png @return [File]

# File lib/appium_lib/driver.rb, line 433
def screenshot(png_save_path)
  @driver.save_screenshot png_save_path
end
server_url() click to toggle source

Get the server url @return [String] the server url

# File lib/appium_lib/driver.rb, line 411
def server_url
  return @core.custom_url if @core.custom_url
  return @sauce.server_url if @sauce.sauce_server_url?

  "http://127.0.0.1:#{@core.port}/wd/hub"
end
set_implicit_wait(wait) click to toggle source

To ignore error for Espresso Driver

# File lib/appium_lib/driver.rb, line 546
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::Core::Error::ServerError
  end

  {}
end
set_location(opts = {}) click to toggle source

Calls @driver.set_location

@note This method does not work on real devices.

@param [Hash] opts consisting of: @option opts [Float] :latitude the latitude in degrees (required) @option opts [Float] :longitude the longitude in degees (required) @option opts [Float] :altitude the altitude, defaulting to 75 @return [Selenium::WebDriver::Location] the location constructed by the selenium webdriver

# File lib/appium_lib/driver.rb, line 773
def set_location(opts = {})
  latitude = opts.fetch(:latitude)
  longitude = opts.fetch(:longitude)
  altitude = opts.fetch(:altitude, 75)
  @driver.set_location(latitude, longitude, altitude)
end
set_wait(timeout = nil) click to toggle source

Set implicit wait. Default to @default_wait.

@example

set_wait 2
set_wait # @default_wait

@param timeout [Integer] the timeout in seconds @return [void]

# File lib/appium_lib/driver.rb, line 571
def set_wait(timeout = nil)
  timeout = @default_wait if timeout.nil?
  @driver.manage.timeouts.implicit_wait = timeout
end
start_driver(http_client_ops = { http_client: ::Appium::Http::Default.new, open_timeout: 999_999, read_timeout: 999_999 }) click to toggle source

Creates a new global driver and quits the old one if it exists. You can customise http_client as the following

Read www.rubydoc.info/github/appium/ruby_lib_core/Appium/Core/Device to understand more what the driver can call instance methods.

@example

require 'rubygems'
require 'appium_lib'

# platformName takes a string or a symbol.
# Start iOS driver
opts = {
         caps: {
           platformName: :ios,
           app: '/path/to/MyiOS.app'
         },
         appium_lib: {
           wait_timeout: 30
         }
       }
appium_driver = Appium::Driver.new(opts) #=> return an Appium::Driver instance
appium_driver.start_driver #=> return an Appium::Core::Base::Driver

@option http_client_ops [Hash] :http_client Custom HTTP Client @option http_client_ops [Hash] :open_timeout Custom open timeout for http client. @option http_client_ops [Hash] :read_timeout Custom read timeout for http client. @return [Selenium::WebDriver] the new global driver

# File lib/appium_lib/driver.rb, line 519
def start_driver(http_client_ops =
                     { http_client: ::Appium::Http::Default.new, open_timeout: 999_999, read_timeout: 999_999 })

  # TODO: do not kill the previous session in the future version.
  if $driver.nil?
    driver_quit
  else
    $driver.driver_quit
  end

  # If automationName is set only in server side, then the following automation_name should be nil before
  # starting driver.
  automation_name = @core.automation_name

  @driver = @core.start_driver(server_url: server_url, http_client_ops: http_client_ops)
  @http_client = @core.http_client

  # if automation_name was nil before start_driver, then re-extend driver specific methods
  # to be able to extend correctly.
  extend_for(device: @core.device, automation_name: @core.automation_name) if automation_name.nil?

  @appium_server_status = appium_server_version

  @driver
end
switch_to() click to toggle source

@return [TargetLocator] @see TargetLocator

# File lib/appium_lib/driver.rb, line 687
def switch_to
  @driver.switch_to
end
title() click to toggle source
# File lib/appium_lib/driver.rb, line 681
def title
  @driver.title
end
window_handle() click to toggle source

Get the current window handle

# File lib/appium_lib/driver.rb, line 661
def window_handle
  @driver.window_handle
end
window_handles() click to toggle source
# File lib/appium_lib/driver.rb, line 656
def window_handles
  @driver.window_handles
end
window_rect() click to toggle source

Get the device window’s rect. @return [Selenium::WebDriver::Rectangle]

@example

size = @driver.window_size
size.width #=> Integer
size.height #=> Integer
size.x #=> Integer
size.y #=> Integer
# File lib/appium_lib/driver.rb, line 486
def window_rect
  @driver.window_rect
end
window_size() click to toggle source

Get the device window’s size. @return [Selenium::WebDriver::Dimension]

@example

size = @driver.window_size
size.width #=> Integer
size.height #=> Integer
# File lib/appium_lib/driver.rb, line 471
def window_size
  @driver.window_size
end
x() click to toggle source

Quit the driver and Pry. quit and exit are reserved by Pry. @return [void]

# File lib/appium_lib/driver.rb, line 826
def x
  driver_quit
  exit # exit pry
end

Private Instance Methods

extend_for(device:, automation_name:) click to toggle source

@private

# File lib/appium_lib/driver.rb, line 208
def extend_for(device:, automation_name:)
  case device
  when :android
    case automation_name
    when :uiautomator2
      ::Appium::Android::Uiautomator2::Bridge.for(self)
    when :espresso
      ::Appium::Android::Espresso::Bridge.for(self)
    else # default and UiAutomator
      ::Appium::Android::Bridge.for(self)
    end
  when :ios, :tvos
    # default and XCUITest
    ::Appium::Ios::Xcuitest::Bridge.for(self)
  when :mac
    # no Mac specific extentions
    Appium::Logger.debug('mac')
  when :windows
    # no windows specific extentions
    Appium::Logger.debug('windows')
  when :tizen
    # https://github.com/Samsung/appium-tizen-driver
    Appium::Logger.debug('tizen')
  when :youiengine
    # https://github.com/YOU-i-Labs/appium-youiengine-driver
    Appium::Logger.debug('YouiEngine')
  else
    case automation_name
    when :youiengine
      # https://github.com/YOU-i-Labs/appium-youiengine-driver
      Appium::Logger.debug('YouiEngine')
    else
      Appium::Logger.debug('no device matched') # core also shows warning message
    end
  end
end
set_app_path(opts) click to toggle source

@private Deprecated. TODO: remove

# File lib/appium_lib/driver.rb, line 247
def set_app_path(opts)
  return unless @core.caps

  # return the path exists on the local
  return if @core.caps['app'] && !@core.caps['app'].nil? && File.exist?(@core.caps['app'])
  return if @core.caps[:app] && !@core.caps[:app].nil? && File.exist?(@core.caps[:app])

  # The app file is not exact path
  if !@core.caps['app'].nil?
    @core.caps['app'] = self.class.absolute_app_path opts
  elsif !@core.caps[:app].nil?
    @core.caps[:app] = self.class.absolute_app_path opts
  end
end