Class: Appium::Core::Base::Driver

Inherits:
Selenium::WebDriver::Driver show all
Extended by:
Forwardable
Includes:
HasLocation, HasRemoteStatus, Rotatable, TakesScreenshot, Waitable, Selenium::WebDriver::DriverExtensions::HasSessionId, Selenium::WebDriver::DriverExtensions::UploadsFiles
Defined in:
lib/appium_lib_core/common/base/driver.rb,
sig/lib/appium_lib_core/common/base/driver.rbs

Constant Summary collapse

AVAILABLE_METHODS =

Returns:

  • (::Array[:get | :head | :post | :put | :delete | :connect | :options | :trace | :patch])
[
  :get, :head, :post, :put, :delete,
  :connect, :options, :trace, :patch
].freeze

Constants included from Rotatable

Rotatable::ORIENTATIONS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Forwardable

def_delegator, def_delegators, def_instance_delegator, def_instance_delegators, def_single_delegator, def_single_delegators

Methods included from Waitable

#wait_until, #wait_until_true

Methods included from HasLocation

#location, #location=, #set_location

Methods included from HasRemoteStatus

#remote_status

Methods included from _Bridge

#execute, #execute_async_script, #execute_script

Methods included from TakesScreenshot

#element_screenshot_as, #save_element_screenshot, #save_screenshot, #save_viewport_screenshot, #screenshot_as

Methods included from Rotatable

#orientation, #rotation=

Methods inherited from Selenium::WebDriver::Driver

#add_extensions, #capabilities, #find_element, #find_elements, #manage, #navigate

Constructor Details

#initialize(bridge: nil, listener: nil, **opts) ⇒ Driver

override

Parameters:

  • bridge: (Object, nil) (defaults to: nil)
  • listener: (Object, nil) (defaults to: nil)
  • opts (Object)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/appium_lib_core/common/base/driver.rb', line 48

def initialize(bridge: nil, listener: nil, **opts) # rubocop:disable Lint/MissingSuper
  original_opts = opts.dup

  # For ::Appium::Core::Waitable
  @wait_timeout = opts.delete(:wait_timeout) || ::Appium::Core::Wait::DEFAULT_TIMEOUT
  @wait_interval = opts.delete(:wait_interval) || ::Appium::Core::Wait::DEFAULT_INTERVAL

  # Selenium WebDriver attributes
  @devtools = nil
  @bidi = nil

  # internal use
  @has_bidi = false

  # steep:ignore:start
  ::Selenium::WebDriver::Remote::Bridge.element_class = ::Appium::Core::Element
  # steep:ignore:end
  bridge ||= create_bridge(**opts)
  add_extensions(bridge.browser)
  @bridge = listener ? ::Appium::Support::EventFiringBridge.new(bridge, listener, **original_opts) : bridge
end

Instance Attribute Details

#bridgeObject (readonly)

Private API. Do not use this for general use. Used by flutter driver to get bridge for creating a new element

Returns:

  • (Object)


45
46
47
# File 'lib/appium_lib_core/common/base/driver.rb', line 45

def bridge
  @bridge
end

Instance Method Details

#activate_app(app_id) ⇒ Hash

Activate(Launch) the specified app.

Examples:


@driver.activate_app("io.appium.bundle") #=> {}

Parameters:

  • app_id (Object)

Returns:

  • (Hash)


702
703
704
705
# File 'lib/appium_lib_core/common/base/driver.rb', line 702

def activate_app(app_id)
  # TODO: use mobile command in the background?
  @bridge.activate_app(app_id)
end

#add_command(method:, url:, name:, &block) { ... } ⇒ Object

Define a new custom method to the driver so that you can define your own method for drivers/plugins in Appium 2.0. Appium 2.0 and its custom drivers/plugins allow you to define custom commands that are not part of W3C spec.

Uses Selenium's Bridge.add_command under the hood to register the command and define the method on the bridge.

Examples:

Simple GET command (no block)


@driver.add_command(
  method: :get,
  url: 'session/:session_id/path/to/custom/url',
  name: :test_command
)
# Send a GET request to 'session/<session id>/path/to/custom/url'
@driver.test_command

POST command with arguments (do/end block)


@driver.add_command(
  method: :post,
  url: 'session/:session_id/path/to/custom/url',
  name: :test_command
) do |argument|
  execute(:test_command, {}, { dummy: argument })
end
# Send a POST request to 'session/<session id>/path/to/custom/url'
# with body "{ dummy: 1 }" as JSON object. "1" is the argument.
# ':session_id' in the given 'url' is replaced with current 'session id'.
@driver.test_command(1)

POST command with arguments (inline block)


@driver.add_command(
  method: :post,
  url: 'session/:session_id/path/to/custom/url',
  name: :test_command
) { |argument| execute(:test_command, {}, { dummy: argument }) }
@driver.test_command(1)

POST command with URL placeholders (do/end block)


@driver.add_command(
  method: :post,
  url: 'session/:session_id/element/:id/custom/action',
  name: :test_action_command
) do |element_id, action|
  execute(:test_action_command, {id: element_id}, { dummy_action: action })
end
# Send a POST request to 'session/<session id>/element/<element id>/custom/action'
# with body "{ dummy_action: #{action} }" as JSON object. "action" is the seconds argument.
# ':session_id' in the given url is replaced with current 'session id'.
# ':id' in the given url is replaced with the given 'element_id'.
e = @driver.find_element :accessibility_id, 'an element'
@driver.test_action_command(e.id, 'action')

POST command with URL placeholders (inline block)


@driver.add_command(
  method: :post,
  url: 'session/:session_id/element/:id/custom/action',
  name: :test_action_command
) { |element_id, action| execute(:test_action_command, {id: element_id}, { dummy_action: action }) }
e = @driver.find_element :accessibility_id, 'an element'
@driver.test_action_command(e.id, 'action')

Parameters:

  • method (Symbol)
  • url (string)

    The url to URL template as https://www.w3.org/TR/webdriver/#endpoints. :session_id is the placeholder of 'session id'. Other place holders can be specified with : prefix like :id. Then, the :id will be replaced with a given value as the seconds argument of execute

  • name (Symbol)

    The name of method that is called as the driver instance method.

  • block (Proc)

    The block becomes the method body. It is executed in the context of the bridge instance, so execute is available. When no block is given, a default implementation calling execute(name) is used.

  • method: (Object)
  • url: (Object)
  • name: (Object)

Yields:

Yield Returns:

  • (Object)

Returns:

  • (Object)

Raises:

  • (ArgumentError)

    If the given method is invalid value.



213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/appium_lib_core/common/base/driver.rb', line 213

def add_command(method:, url:, name:, &block)
  raise ::Appium::Core::Error::ArgumentError, "Available method is either #{AVAILABLE_METHODS}" unless AVAILABLE_METHODS.include? method

  ::Appium::Logger.info "Overriding the command '#{name}' for '#{url}'" if Bridge.extra_commands&.key?(name)

  # Use Selenium's Bridge.add_command to register the command and define the method.
  # When no block is given, create a default implementation that calls execute.
  block ||= proc { execute(name) }
  Bridge.add_command(name, method, url, &block)

  # Ensure the driver delegates the new method to bridge
  self.class.class_eval { def_delegator :@bridge, name } unless self.class.method_defined?(name)
end

#app_installed?(app_id) ⇒ Boolean

Check whether the specified app is installed on the device

Examples:


@driver.app_installed?("io.appium.bundle")

Parameters:

  • app_id (Object)

Returns:

  • (Boolean)


690
691
692
693
# File 'lib/appium_lib_core/common/base/driver.rb', line 690

def app_installed?(app_id)
  # TODO: use mobile command in the background?
  @bridge.app_installed?(app_id)
end

#app_state(app_id) ⇒ AppState::STATUS Also known as: query_app_state

Get the status of an existing application on the device. State:

:not_installed : The current application state cannot be determined/is unknown
:not_running : The application is not running
:running_in_background_suspended : The application is running in the background and is suspended
:running_in_background : The application is running in the background and is not suspended
:running_in_foreground : The application is running in the foreground

For more details: https://developer.apple.com/documentation/xctest/xcuiapplicationstate

Examples:


@driver.app_state("io.appium.bundle") #=> :not_running
# Compatibility for other clients
@driver.query_app_state("io.appium.bundle") #=> :not_running

Parameters:

  • app_id (String)

    A target app's bundle id

Returns:

  • (AppState::STATUS)

    A number of the state



743
744
745
# File 'lib/appium_lib_core/common/base/driver.rb', line 743

def app_state(app_id)
  @bridge.app_state(app_id)
end

#app_strings(language = nil) ⇒ Hash

Return the hash of all localization strings.

Examples:


@driver.app_strings #=> "TransitionsTitle"=>"Transitions", "WebTitle"=>"Web"

Parameters:

  • language (Object, nil) (defaults to: nil)

Returns:

  • (Hash)


612
613
614
# File 'lib/appium_lib_core/common/base/driver.rb', line 612

def app_strings(language = nil)
  @bridge.app_strings(language)
end

#available_contextsArray<String>

Returns All usable contexts, as an array of strings.

Examples:


@driver.available_contexts

Returns:

  • (Array<String>)

    All usable contexts, as an array of strings.



468
469
470
# File 'lib/appium_lib_core/common/base/driver.rb', line 468

def available_contexts
  @bridge.available_contexts
end

#backString

Get the device window's size.

Examples:

@driver.back # back to the previous view

Returns:

  • (String)


879
880
881
# File 'lib/appium_lib_core/common/base/driver.rb', line 879

def back
  navigate.back
end

#background_app(duration = 0) ⇒ String

Backgrounds the app for a set number of seconds. This is a blocking application

Examples:


@driver.background_app
@driver.background_app(5)
@driver.background_app(-1) #=> the app never come back. https://github.com/appium/appium/issues/7741

Parameters:

  • duration (Integer) (defaults to: 0)

    How many seconds to background the app for.

Returns:

  • (String)


627
628
629
# File 'lib/appium_lib_core/common/base/driver.rb', line 627

def background_app(duration = 0)
  @bridge.background_app(duration)
end

#bidi::Selenium::WebDriver::BiDi

Return bidi instance

Examples:


log_entries = []
driver.bidi.send_cmd('session.subscribe', 'events': ['log.entryAdded'], 'contexts': ['NATIVE_APP'])
subscribe_id = driver.bidi.add_callback('log.entryAdded') do |params|
  log_entries << params
end
driver.page_source

driver.bidi.remove_callback('log.entryAdded', subscribe_id)
driver.bidi.send_cmd('session.unsubscribe', 'events': ['log.entryAdded'], 'contexts': ['NATIVE_APP'])

Returns:

Raises:



1048
1049
1050
1051
1052
1053
# File 'lib/appium_lib_core/common/base/driver.rb', line 1048

def bidi
  return @bridge.bidi if @has_bidi

  msg = 'BiDi must be enabled by providing webSocketUrl capability to true'
  raise(::Selenium::WebDriver::Error::WebDriverError, msg)
end

#compare_images(mode: :matchFeatures, first_image:, second_image:, options: nil) ⇒ Object

Parameters:

  • first_image: (Object)
  • second_image: (Object)
  • mode: (::Symbol) (defaults to: :matchFeatures)
  • options: (Object, nil) (defaults to: nil)

Returns:

  • (Object)


936
937
938
# File 'lib/appium_lib_core/common/base/driver.rb', line 936

def compare_images(mode: :matchFeatures, first_image:, second_image:, options: nil)
  @bridge.compare_images(mode: mode, first_image: first_image, second_image: second_image, options: options)
end

#context=(context = nil) ⇒ Object Also known as: set_context

Change the context to the given context.

Examples:


@driver.set_context "NATIVE_APP"
@driver.context = "NATIVE_APP"

Parameters:

  • context (String) (defaults to: nil)

    The context to change to

Returns:

  • (Object)


480
481
482
# File 'lib/appium_lib_core/common/base/driver.rb', line 480

def context=(context = nil)
  @bridge.set_context(context)
end

#convert_to_element(response_id) ⇒ ::Appium::Core::Element

Convert vanilla element response to ::Appium::Core::Element

Examples:

response = {"element-6066-11e4-a52e-4f735466cecf"=>"xxxx", "ELEMENT"=>"xxxx"}
ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
ele.rect #=> Can get the rect of the element

Parameters:

  • response_id (Hash)

    id The id which can get as a response from server

Returns:



1029
1030
1031
# File 'lib/appium_lib_core/common/base/driver.rb', line 1029

def convert_to_element(response_id)
  @bridge.convert_to_element response_id
end

#create_bridge(**opts) ⇒ ::Appium::Core::Base::Bridge

Create a proper bridge instance.

Parameters:

  • opts (Object)

Returns:

Raises:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/appium_lib_core/common/base/driver.rb', line 76

def create_bridge(**opts)
  # for a new session request
  capabilities = opts.delete(:capabilities)
  bridge_extensions = opts.delete(:bridge_extensions)
  bridge_opts = { http_client: opts.delete(:http_client), url: opts.delete(:url) }

  # for attaching to an existing session
  session_id = opts.delete(:existing_session_id)
  automation_name = opts.delete(:automation_name)
  platform_name = opts.delete(:platform_name)

  raise ::Appium::Core::Error::ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?

  @has_bidi = capabilities && capabilities['webSocketUrl'] ? true : false
  bridge_clzz = @has_bidi ? ::Appium::Core::Base::BiDiBridge : ::Appium::Core::Base::Bridge
  # steep:ignore:start
  bridge = bridge_clzz.new(**bridge_opts)
  bridge.extend(bridge_extensions) if bridge_extensions
  # steep:ignore:end

  if session_id.nil?
    bridge.create_session(capabilities)
  else
    # attach to the existing session id
    bridge.attach_to(session_id, platform_name, automation_name)
  end

  bridge
end

#current_contextString

Returns The context currently being used.

Examples:


@driver.current_context

Returns:

  • (String)

    The context currently being used.



458
459
460
# File 'lib/appium_lib_core/common/base/driver.rb', line 458

def current_context
  @bridge.current_context
end

#device_time(format = nil) ⇒ String

Get the time on the device

Examples:


@driver.device_time #=> "2018-06-12T11:13:31+02:00"
@driver.device_time "YYYY-MM-DD" #=> "2018-06-12"

Parameters:

  • format (String) (defaults to: nil)

    The set of format specifiers. Read https://momentjs.com/docs/ to get the full list of supported datetime format specifiers. The default format is YYYY-MM-DDTHH:mm:ssZ, which complies to ISO-8601

Returns:

  • (String)

    Formatted datetime string or the raw command output if formatting fails



805
806
807
# File 'lib/appium_lib_core/common/base/driver.rb', line 805

def device_time(format = nil)
  @bridge.device_time(format)
end

#execute_driver(script: '', type: 'webdriverio', timeout_ms: nil) ⇒ Appium::Core::Base::Device::ExecuteDriver::Result

Run a set of script against the current session, allowing execution of many commands in one Appium request. Supports WebdriverIO API so far. Please read command API for more details about acceptable scripts and the output.

Examples:

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' => []}'

Parameters:

  • script (String) (defaults to: '')

    The string consisting of the script itself

  • type (String) (defaults to: 'webdriverio')

    The name of the script type. Defaults to 'webdriverio'. Depends on server implementation which type is supported.

  • timeout_ms (Integer) (defaults to: nil)

    The number of ms Appium should wait for the script to finish before killing it due to timeout.

  • script: (::String) (defaults to: '')
  • type: (::String) (defaults to: 'webdriverio')
  • timeout_ms: (Object, nil) (defaults to: nil)

Returns:

Raises:

Since:

  • Appium 1.14.0



1015
1016
1017
# File 'lib/appium_lib_core/common/base/driver.rb', line 1015

def execute_driver(script: '', type: 'webdriverio', timeout_ms: nil)
  @bridge.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
end

#find_element_by_image(img_path) ⇒ ::Appium::Core::Element

Return an element if current view has a partial image. The logic depends on template matching by OpenCV. image-comparison

You can handle settings for the comparision following below. device-settings

Examples:


@@driver.update_settings({ fixImageFindScreenshotDims: false, fixImageTemplateSize: true,
                           autoUpdateImageElementPosition: true })
e = @@driver.find_element_by_image './test/functional/data/test_element_image.png'

Parameters:

  • img_path (String)

    A path to a partial image you'd like to find

Returns:

Since:

  • Appium 1.8.2



957
958
959
960
# File 'lib/appium_lib_core/common/base/driver.rb', line 957

def find_element_by_image(img_path)
  template = Base64.strict_encode64 File.read img_path
  find_element :image, template
end

#find_elements_by_image(img_path) ⇒ Array<::Appium::Core::Element>

Return elements if current view has a partial image. The logic depends on template matching by OpenCV. image-comparison

You can handle settings for the comparision following below. device-settings

Examples:


@@driver.update_settings({ fixImageFindScreenshotDims: false, fixImageTemplateSize: true,
                           autoUpdateImageElementPosition: true })
e = @@driver.find_elements_by_image ['./test/functional/data/test_element_image.png']
e == [] # if the 'e' is empty

Parameters:

  • img_path (String)

    A path to a partial image you'd like to find

Returns:

Since:

  • Appium 1.8.2



980
981
982
983
# File 'lib/appium_lib_core/common/base/driver.rb', line 980

def find_elements_by_image(img_path)
  template = Base64.strict_encode64 File.read img_path
  find_elements :image, template
end

#find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil, multiple: nil, match_neighbour_threshold: nil) ⇒ Object

Parameters:

  • full_image: (Object)
  • partial_image: (Object)
  • visualize: (Boolean) (defaults to: false)
  • threshold: (Object, nil) (defaults to: nil)
  • multiple: (Object, nil) (defaults to: nil)
  • match_neighbour_threshold: (Object, nil) (defaults to: nil)

Returns:

  • (Object)


922
923
924
925
926
927
928
929
930
# File 'lib/appium_lib_core/common/base/driver.rb', line 922

def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
                          multiple: nil, match_neighbour_threshold: nil)
  @bridge.find_image_occurrence(full_image: full_image,
                                partial_image: partial_image,
                                visualize: visualize,
                                threshold: threshold,
                                multiple: multiple,
                                match_neighbour_threshold: match_neighbour_threshold)
end

#get_images_similarity(first_image:, second_image:, visualize: false) ⇒ Object

Parameters:

  • first_image: (Object)
  • second_image: (Object)
  • visualize: (Boolean) (defaults to: false)

Returns:

  • (Object)


932
933
934
# File 'lib/appium_lib_core/common/base/driver.rb', line 932

def get_images_similarity(first_image:, second_image:, visualize: false)
  @bridge.get_images_similarity(first_image: first_image, second_image: second_image, visualize: visualize)
end

#get_settingsObject

Get appium Settings for current test session. Alias of @driver.settings.get

Examples:


@driver.get_settings
@driver.settings.get

Returns:

  • (Object)


335
336
337
# File 'lib/appium_lib_core/common/base/driver.rb', line 335

def get_settings
  settings.get
end

#get_timeoutsHash

For W3C. Get the timeout related settings on the server side.

Examples:

@driver.get_timeouts

Returns:

  • (Hash)


903
904
905
# File 'lib/appium_lib_core/common/base/driver.rb', line 903

def get_timeouts
  @bridge.get_timeouts
end

#hide_keyboard(close_key = nil) ⇒ Object

Hide the onscreen keyboard

Examples:


@driver.hide_keyboard # Close a keyboard with the 'Done' button
@driver.hide_keyboard('Finished') # Close a keyboard with the 'Finished' button

Parameters:

  • close_key (String) (defaults to: nil)

    The name of the key which closes the keyboard. Defaults to 'Done' for iOS(except for XCUITest).

Returns:

  • (Object)


300
301
302
# File 'lib/appium_lib_core/common/base/driver.rb', line 300

def hide_keyboard(close_key = nil)
  @bridge.hide_keyboard close_key
end

#imeAppium::Core::Base::Driver::DeviceIME

Deprecated.

Use 'mobile: shell' extension instead.

Returns an instance of DeviceIME

Examples:


@driver.ime.activate engine: 'com.android.inputmethod.latin/.LatinIME'
@driver.ime.available_engines #=> Get the list of IME installed in the target device
@driver.ime.active_engine #=> Get the current active IME such as 'com.android.inputmethod.latin/.LatinIME'
@driver.ime.activated #=> True if IME is activated
@driver.ime.deactivate #=> Deactivate current IME engine

Returns:

  • (Appium::Core::Base::Driver::DeviceIME)


368
369
370
371
# File 'lib/appium_lib_core/common/base/driver.rb', line 368

def ime
  ::Appium::Logger.warn "[DEPRECATION] Please use 'mobile: shell' extension instead"
  @ime ||= DeviceIME.new(@bridge)
end

#ime_activate(ime_name) ⇒ Object

Deprecated.

Use 'mobile: shell' extension instead.

Android only. Make an engine that is available active.

Examples:


@driver.ime_activate engine: 'com.android.inputmethod.latin/.LatinIME'
@driver.ime.activate engine: 'com.android.inputmethod.latin/.LatinIME'

Parameters:

  • ime_name (String)

    The IME owning the activity [required]

Returns:

  • (Object)


383
384
385
# File 'lib/appium_lib_core/common/base/driver.rb', line 383

def ime_activate(ime_name)
  ime.activate(ime_name)
end

#ime_activatedBoolean

Deprecated.

Use 'mobile: shell' extension instead.

Examples:


@driver.ime_activated #=> True if IME is activated
@driver.ime.activated #=> True if IME is activated

Returns:

  • (Boolean)


422
423
424
# File 'lib/appium_lib_core/common/base/driver.rb', line 422

def ime_activated
  ime.activated?
end

#ime_active_engineObject

Deprecated.

Use 'mobile: shell' extension instead.

Android only. Get the name of the active IME engine.

Examples:


@driver.ime_active_engine #=> Get the current active IME such as 'com.android.inputmethod.latin/.LatinIME'
@driver.ime.active_engine #=> Get the current active IME such as 'com.android.inputmethod.latin/.LatinIME'

Returns:

  • (Object)


407
408
409
# File 'lib/appium_lib_core/common/base/driver.rb', line 407

def ime_active_engine
  ime.active_engine
end

#ime_available_enginesObject

Deprecated.

Use 'mobile: shell' extension instead.

Android only. List all available input engines on the machine.

Examples:


@driver.ime_available_engines #=> Get the list of IME installed in the target device
@driver.ime.available_engines #=> Get the list of IME installed in the target device

Returns:

  • (Object)


395
396
397
# File 'lib/appium_lib_core/common/base/driver.rb', line 395

def ime_available_engines
  ime.available_engines
end

#ime_deactivateObject

Deprecated.

Use 'mobile: shell' extension instead.

Android only. De-activates the currently-active IME engine.

Examples:


@driver.ime_deactivate #=> Deactivate current IME engine
@driver.ime.deactivate #=> Deactivate current IME engine

Returns:

  • (Object)


434
435
436
# File 'lib/appium_lib_core/common/base/driver.rb', line 434

def ime_deactivate
  ime.deactivate
end

#install_app(path, **options) ⇒ Object

Install the given app onto the device. Each options can be snake-case or camel-case. Snake-cases will be converted to camel-case as options value.

Other parameters such as https://github.com/appium/appium-xcuitest-driver#mobile-installapp also can be set. Then, arguments in snake case will be camel case as its request parameters.

Examples:


@driver.install_app("/path/to/test.apk")
@driver.install_app("/path/to/test.apk", replace: true, timeout: 20000, allow_test_packages: true,
                    use_sdcard: false, grant_permissions: false)
@driver.install_app("/path/to/test.ipa", timeoutMs: 20000)

Parameters:

  • path (String)

    The absolute local path or remote http URL to an .ipa or .apk file, or a .zip containing one of these.

  • [Boolean] (Hash)

    a customizable set of options

  • [Integer] (Hash)

    a customizable set of options

  • options (Object)

Returns:

  • (Object)


657
658
659
660
661
# File 'lib/appium_lib_core/common/base/driver.rb', line 657

def install_app(path, **options)
  # TODO: use mobile command in the background?
  options = options.transform_keys { |key| key.to_s.gsub(/_./) { |v| v[1]&.upcase } } unless options.nil?
  @bridge.install_app(path, options)
end

#key_action(async: false) ⇒ Object

Perform 'key' actions for W3C module. Generate key pointer action here and users can use this via driver.key_action

The pointer type is 'key' by default in the Appium Ruby client. driver.action in Appium Ruby client has 'pointer' action by default. This method is a shortcut to set 'key' type. Hense this method is equal to driver.action(devices: [::Selenium::WebDriver::Interactions.key('keyboard')]) as below example.

Examples:


element = @driver.find_element(:id, "some id")
@driver.key_action.send_key('hiあ').perform # The 'send_key' is a part of 'KeyActions'
# is equal to:
# @driver.action(devices: [::Selenium::WebDriver::Interactions.key('keyboard')]).send_keys('hiあ').perform

Parameters:

  • async: (Boolean) (defaults to: false)

Returns:

  • (Object)


247
248
249
250
251
252
253
254
# File 'lib/appium_lib_core/common/base/driver.rb', line 247

def key_action(async: false)
  @bridge.action(
    async: async,
    # steep:ignore:start
    devices: [::Selenium::WebDriver::Interactions.key('keyboard')]
    # steep:ignore:end
  )
end

#keyboard_shown?Boolean Also known as: is_keyboard_shown

Get whether keyboard is displayed or not.

Examples:

@driver.is_keyboard_shown # false
@driver.keyboard_shown?   # true

Returns:

  • (Boolean)

    Return true if keyboard is shown. Return false if keyboard is hidden.



311
312
313
# File 'lib/appium_lib_core/common/base/driver.rb', line 311

def keyboard_shown?
  @bridge.is_keyboard_shown
end

#lock(duration = nil) ⇒ String

Lock the device

Examples:


@driver.lock    #=> Lock the device
@driver.lock(5) #=> Lock the device in 5 sec and unlock the device after 5 sec.
                #   Block other commands during locking the device.

Parameters:

  • duration (Object, nil) (defaults to: nil)

Returns:

  • (String)


265
266
267
# File 'lib/appium_lib_core/common/base/driver.rb', line 265

def lock(duration = nil)
  @bridge.lock(duration)
end

#locked?Boolean Also known as: device_locked?

Check current device status is weather locked or not

Examples:


@driver.device_locked?
@driver.locked?

Returns:

  • (Boolean)


276
277
278
# File 'lib/appium_lib_core/common/base/driver.rb', line 276

def locked?
  @bridge.device_locked?
end

#logsAppium::Core::Logs

Get the device window's logs.

Examples:


@driver.logs.available_types # [:syslog, :crashlog, :performance]
@driver.logs.get :syslog # []

Returns:



891
892
893
# File 'lib/appium_lib_core/common/base/driver.rb', line 891

def logs
  @logs ||= Logs.new(@bridge)
end

#long_press_keycode(key, metastate: [], flags: []) ⇒ Object

Examples:


@driver.long_press_keycode 66
@driver.long_press_keycode 66, flags: [0x20, 0x2000]
@driver.long_press_keycode 66, metastate: [1], flags: [32, 8192]

Parameters:

Returns:

  • (Object)


601
602
603
# File 'lib/appium_lib_core/common/base/driver.rb', line 601

def long_press_keycode(key, metastate: [], flags: [])
  @bridge.long_press_keycode(key, metastate: metastate, flags: flags)
end

#match_images_features(first_image:, second_image:, detector_name: 'ORB', match_func: 'BruteForce', good_matches_factor: nil, visualize: false) ⇒ Object

Image Comparison

Parameters:

  • first_image: (Object)
  • second_image: (Object)
  • detector_name: (::String) (defaults to: 'ORB')
  • match_func: (::String) (defaults to: 'BruteForce')
  • good_matches_factor: (Object, nil) (defaults to: nil)
  • visualize: (Boolean) (defaults to: false)

Returns:

  • (Object)


908
909
910
911
912
913
914
915
916
917
918
919
920
# File 'lib/appium_lib_core/common/base/driver.rb', line 908

def match_images_features(first_image:,
                          second_image:,
                          detector_name: 'ORB',
                          match_func: 'BruteForce',
                          good_matches_factor: nil,
                          visualize: false)
  @bridge.match_images_features(first_image: first_image,
                                second_image: second_image,
                                detector_name: detector_name,
                                match_func: match_func,
                                good_matches_factor: good_matches_factor,
                                visualize: visualize)
end

#perform_actions(data) ⇒ Object

Send multiple W3C action chains to server. Use @driver.action for single action chain.

@example: Zoom

f1 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger1')
f1.create_pointer_move(duration: 1, x: 200, y: 500,
                      origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f1.create_pointer_down(:left)
f1.create_pointer_move(duration: 1, x: 200, y: 200,
                      origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f1.create_pointer_up(:left)

f2 = ::Selenium::WebDriver::Interactions.pointer(:touch, name: 'finger2')
f2.create_pointer_move(duration: 1, x: 200, y: 500,
                      origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f2.create_pointer_down(:left)
f2.create_pointer_move(duration: 1, x: 200, y: 800,
                      origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f2.create_pointer_up(:left)

@driver.perform_actions [f1, f2] #=> 'nil' if the action succeed

Parameters:

  • data (Array)

    Array of actions

Returns:

  • nil|error

Raises:



835
836
837
838
839
840
841
842
843
844
845
# File 'lib/appium_lib_core/common/base/driver.rb', line 835

def perform_actions(data)
  raise ::Appium::Core::Error::ArgumentError, "'#{data}' must be Array" unless data.is_a? Array

  # NOTE: 'add_input' in Selenium Ruby implementation has additional 'pause'.
  # This implementation is to avoid the additional pause.
  # https://github.com/SeleniumHQ/selenium/blob/64447d4b03f6986337d1ca8d8b6476653570bcc1/rb/lib/selenium/webdriver/common/action_builder.rb#L207

  @bridge.send_actions data.map(&:encode).compact
  data.each(&:clear_actions)
  nil
end

#press_keycode(key, metastate: [], flags: []) ⇒ Object

Examples:


@driver.press_keycode 66
@driver.press_keycode 66, flags: [0x02]
@driver.press_keycode 66, metastate: [1], flags: [32]

Parameters:

Returns:

  • (Object)


579
580
581
# File 'lib/appium_lib_core/common/base/driver.rb', line 579

def press_keycode(key, metastate: [], flags: [])
  @bridge.press_keycode(key, metastate: metastate, flags: flags)
end

#pull_file(path) ⇒ Base64-decoded

Pull a file from the remote device. On Android the application under test should be built with debuggable flag enabled in order to get access to its container on the internal file system.

Examples:


decoded_file = @driver.pull_file '/local/data/some/path'     #=> Get the file at that path
decoded_file = @driver.pull_file 'Shenanigans.app/some/file'
               #=> Get 'some/file' from the install location of Shenanigans.app
decoded_file = @driver.pull_file '@com.appium.example/Documents/file.txt'
               #=> Get 'file.txt' in @com.appium.example/Documents
File.open('proper_filename', 'wb') { |f| f<< decoded_file }

Parameters:

  • path (String)

    Either an absolute path OR, for iOS devices, a path relative to the app, as described. If the path starts with application id prefix, then the file will be pulled from the root of the corresponding application container. Otherwise the root folder is considered as / on Android and on iOS it is a media folder root (real devices only). Only pulling files from application containers is supported for iOS Simulator. Provide the remote path in format @bundle.identifier:container_type/relative_path_in_container

Returns:

  • (Base64-decoded)

    Base64 decoded data



530
531
532
533
# File 'lib/appium_lib_core/common/base/driver.rb', line 530

def pull_file(path)
  # TODO: use 'mobile: pullFile' internally
  @bridge.pull_file(path)
end

#pull_folder(path) ⇒ Base64-decoded

Pull a folder content from the remote device. On Android the application under test should be built with debuggable flag enabled in order to get access to its container on the internal file system.

Examples:


decoded_file = @driver.pull_folder '/data/local/tmp' #=> Get the folder at that path
decoded_file = @driver.pull_file '@com.appium.example/Documents' #=> Get 'Documents' in @com.appium.example
File.open('proper_filename', 'wb') { |f| f<< decoded_file }

Parameters:

  • path (String)

    Absolute path to the folder. If the path starts with @applicationId/ prefix, then the folder will be pulled from the root of the corresponding application container. Otherwise the root folder is considered as / on Android and on iOS it is a media folder root (real devices only). Only pulling files from application containers is supported for iOS Simulator. Provide the remote path in format @bundle.identifier:container_type/relative_path_in_container

Returns:

  • (Base64-decoded)

    Base64 decoded data which is zip archived



556
557
558
559
# File 'lib/appium_lib_core/common/base/driver.rb', line 556

def pull_folder(path)
  # TODO: use 'mobile: pullFolder' internally
  @bridge.pull_folder(path)
end

#push_file(path, filedata) ⇒ Object

Place a file in a specific location on the device. On Android, the application under test should be built with debuggable flag enabled in order to get access to its container on the internal file system.

Examples:


@driver.push_file "/file/to/path", "data"

file = File.read "your/path/to/test_image.png"
@driver.push_file "/sdcard/Pictures", file # Push a file binary to /sdcard/Pictures path in Android

Parameters:

  • path (String)

    Either an absolute path OR, for iOS devices, a path relative to the app, as described. If the path starts with application id prefix, then the file will be pushed to the root of the corresponding application container.

  • filedata (String)

    Raw file data to be sent to the device. Converted to base64 in the method.

Returns:

  • (Object)


501
502
503
504
# File 'lib/appium_lib_core/common/base/driver.rb', line 501

def push_file(path, filedata)
  # TODO: use 'mobile: pushFile' internally
  @bridge.push_file(path, filedata)
end

#remove_app(app_id, keep_data: nil, timeout: nil) ⇒ Object

Examples:


@driver.remove_app("io.appium.bundle")
@driver.remove_app("io.appium.bundle", keep_data: false, timeout, 10000)

Parameters:

  • app_id (Strong)

    BundleId for iOS or package name for Android

  • keep_data (Boolean) (defaults to: nil)

    Only for Android. Whether to keep application data and caches after it is uninstalled. false by default

  • timeout (Integer) (defaults to: nil)

    Only for Android. How much time to wait for the uninstall to complete. 20000ms by default.

  • keep_data: (Object, nil) (defaults to: nil)
  • timeout: (Object, nil) (defaults to: nil)

Returns:

  • (Object)


678
679
680
681
# File 'lib/appium_lib_core/common/base/driver.rb', line 678

def remove_app(app_id, keep_data: nil, timeout: nil)
  # TODO: use mobile command in the background?
  @bridge.remove_app(app_id, keep_data: keep_data, timeout: timeout)
end

#settingsObject

Returns an instance of DriverSettings to call get/update.

Examples:


@driver.settings.get
@driver.settings.update('allowInvisibleElements': true)

Returns:

  • (Object)


323
324
325
# File 'lib/appium_lib_core/common/base/driver.rb', line 323

def settings
  @settings ||= DriverSettings.new(@bridge)
end

#settings=(value) ⇒ Object Also known as: update_settings

Update Appium Settings for current test session Alias of @driver.settings#update

Examples:


@driver.update_settings({ 'allowInvisibleElements': true })
@driver.settings.update({ 'allowInvisibleElements': true })
@driver.settings = { 'allowInvisibleElements': true }

Parameters:

  • value (Hash)

    Settings to update, keys are settings, values to value to set each setting to

Returns:

  • (Object)


350
351
352
# File 'lib/appium_lib_core/common/base/driver.rb', line 350

def settings=(value)
  settings.update(value)
end

#shakeObject

Cause the device to shake

Examples:


@driver.shake

Returns:

  • (Object)


789
790
791
# File 'lib/appium_lib_core/common/base/driver.rb', line 789

def shake
  @bridge.shake
end

#stop_and_save_recording_screen(file_path) ⇒ Object

Examples:


# iOS
@driver.start_recording_screen video_type: 'libx264'
@driver.stop_and_save_recording_screen 'example.mp4' # Video type 'libx264' can be play as '.mp4' video

# Android
@driver.start_recording_screen
@driver.stop_and_save_recording_screen 'example.mp4'

Parameters:

  • file_path (String)

    The path to save video decoded from base64 from Appium server.

Returns:

  • (Object)


779
780
781
# File 'lib/appium_lib_core/common/base/driver.rb', line 779

def stop_and_save_recording_screen(file_path)
  @bridge.stop_and_save_recording_screen(file_path)
end

#stop_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT') ⇒ Object

Examples:


@driver.stop_recording_screen
@driver.stop_recording_screen remote_path: 'https://example.com', user: 'example', pass: 'pass', method: 'POST'

Parameters:

  • remote_path (String) (defaults to: nil)

    The path to the remote location, where the resulting video should be uploaded. The following protocols are supported: http/https, ftp. Null or empty string value (the default setting) means the content of resulting file should be encoded as Base64 and passed as the endpoint response value. An exception will be thrown if the generated media file is too big to fit into the available process memory.

  • user (String) (defaults to: nil)

    The name of the user for the remote authentication.

  • pass (String) (defaults to: nil)

    The password for the remote authentication.

  • method (String) (defaults to: 'PUT')

    The http multipart upload method name. The 'PUT' one is used by default.

  • remote_path: (Object, nil) (defaults to: nil)
  • user: (Object, nil) (defaults to: nil)
  • pass: (Object, nil) (defaults to: nil)
  • method: (::String) (defaults to: 'PUT')

Returns:

  • (Object)


763
764
765
# File 'lib/appium_lib_core/common/base/driver.rb', line 763

def stop_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT')
  @bridge.stop_recording_screen(remote_path: remote_path, user: user, pass: pass, method: method)
end

#terminate_app(app_id, timeout: nil) ⇒ Boolean

Terminate the specified app.

Examples:


@driver.terminate_app("io.appium.bundle") # true
@driver.terminate_app("io.appium.bundle", timeout: 500)

Parameters:

  • app_id (Strong)

    BundleId for iOS or package name for Android

  • timeout (Integer) (defaults to: nil)

    Only for Android. How much time to wait for the application termination to complete. 500ms by default.

  • timeout: (Object, nil) (defaults to: nil)

Returns:

  • (Boolean)


719
720
721
722
# File 'lib/appium_lib_core/common/base/driver.rb', line 719

def terminate_app(app_id, timeout: nil)
  # TODO: use mobile command in the background?
  @bridge.terminate_app(app_id, timeout: timeout)
end

#unlockObject

Unlock the device

Examples:


@driver.unlock

Returns:

  • (Object)


287
288
289
# File 'lib/appium_lib_core/common/base/driver.rb', line 287

def unlock
  @bridge.unlock
end

#update_sending_request_to(protocol:, host:, port:, path:) ⇒ nil, untyped

Update server_url and HTTP clients following this arguments, protocol, host, port and path. After this method, @bridge.http will be a new instance following them instead of server_url which is set before creating session. If @bridge.http did not have update_sending_request_to method, this method returns immediately.

Examples:


driver = core.start_driver server_url: 'http://example1.com:8000/wd/hub # @bridge.http is for 'http://example1.com:8000/wd/hub/'
driver.update_sending_request_to protocol: 'https', host: 'example2.com', port: 9000, path: '/wd/hub'
driver.manage.timeouts.implicit_wait = 10 # @bridge.http is for 'https://example2.com:9000/wd/hub/'

Parameters:

  • protocol: (Object)
  • host: (Object)
  • port: (Object)
  • path: (Object)

Returns:

  • (nil, untyped)


119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/appium_lib_core/common/base/driver.rb', line 119

def update_sending_request_to(protocol:, host:, port:, path:)
  unless @bridge.http&.class&.method_defined? :update_sending_request_to
    ::Appium::Logger.warn "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
                          'It keeps current connection target.'
    return
  end

  @bridge.http&.update_sending_request_to(scheme: protocol,
                                          host: host,
                                          port: port,
                                          path: path)
end

#window_rectSelenium::WebDriver::Rectangle

Get the device window's rect.

Examples:

size = @driver.window_rect
size.width #=> Integer
size.height #=> Integer
size.x #=> 0
size.y #=> 0

Returns:

  • (Selenium::WebDriver::Rectangle)


869
870
871
# File 'lib/appium_lib_core/common/base/driver.rb', line 869

def window_rect
  manage.window.rect
end

#window_sizeSelenium::WebDriver::Dimension

Get the device window's size.

Examples:

size = @driver.window_size
size.width #=> Integer
size.height #=> Integer

Returns:

  • (Selenium::WebDriver::Dimension)


855
856
857
# File 'lib/appium_lib_core/common/base/driver.rb', line 855

def window_size
  manage.window.size
end

#within_context(context, &block) ⇒ void

This method returns an undefined value.

Perform a block within the given context, then switch back to the starting context.

Examples:


result = @driver.within_context('NATIVE_APP') do
  @driver.find_element :tag, "button"
end # The result of 'find_element :tag, "button"'

Parameters:

  • context (String)

    The context to switch to for the duration of the block.

  • block (Proc)

    The block to involve within the context



448
449
450
# File 'lib/appium_lib_core/common/base/driver.rb', line 448

def within_context(context, &block)
  block_given? ? @bridge.within_context(context, &block) : @bridge.within_context(context)
end