Class: Appium::Driver
- Inherits:
-
Object
- Object
- Appium::Driver
- Defined in:
- lib/appium_lib/driver.rb
Instance Attribute Summary collapse
-
#appium_debug ⇒ Object
readonly
Boolean debug mode for the Appium Ruby bindings.
-
#appium_device ⇒ Object
readonly
Returns the value of attribute appium_device.
-
#appium_port ⇒ Object
readonly
Returns the value of attribute appium_port.
-
#appium_server_status ⇒ Object
readonly
Appium’s server version.
-
#appium_wait_interval ⇒ Object
readonly
Returns the value of attribute appium_wait_interval.
-
#appium_wait_timeout ⇒ Object
readonly
Returns the value of attribute appium_wait_timeout.
-
#automation_name ⇒ Object
readonly
Returns the value of attribute automation_name.
-
#caps ⇒ Object
readonly
from Core read www.rubydoc.info/github/appium/ruby_lib_core/Appium/Core/Driver.
-
#core ⇒ Object
readonly
Instance of Appium::Core::Driver.
-
#custom_url ⇒ Object
readonly
Returns the value of attribute custom_url.
-
#default_wait ⇒ Object
readonly
Returns the value of attribute default_wait.
-
#driver ⇒ Driver
readonly
Returns the driver.
-
#export_session ⇒ Object
readonly
Returns the value of attribute export_session.
-
#export_session_path ⇒ Object
readonly
Returns the value of attribute export_session_path.
-
#global_webdriver_http_sleep ⇒ Object
The amount to sleep in seconds before every webdriver http call.
-
#http_client ⇒ Object
readonly
Returns the value of attribute http_client.
-
#listener ⇒ Object
readonly
Returns the value of attribute listener.
-
#sauce ⇒ Object
readonly
SauceLab’s settings.
-
#sauce_access_key ⇒ Object
readonly
Access Key for use on Sauce Labs.
-
#sauce_endpoint ⇒ Object
readonly
Override the Sauce Appium endpoint to allow e.g.
-
#sauce_username ⇒ Object
readonly
Username for use on Sauce Labs.
Class Method Summary collapse
-
.absolute_app_path(opts) ⇒ String
Converts app_path to an absolute path.
Instance Method Summary collapse
-
#action ⇒ TouchAction|Selenium::WebDriver::PointerActions
An entry point to chain W3C actions.
-
#appium_client_version ⇒ Hash
Returns the client’s version info.
-
#appium_server_version ⇒ Hash
(also: #remote_status)
Returns the server’s version info.
-
#automation_name_is_espresso? ⇒ Boolean
Return true if automationName is ‘Espresso’.
-
#automation_name_is_uiautomator2? ⇒ Boolean
Return true if automationName is ‘uiautomator2’.
-
#automation_name_is_xcuitest? ⇒ Boolean
Return true if automationName is ‘XCUITest’.
- #current_url ⇒ Object
- #device_is_android? ⇒ Boolean
- #device_is_ios? ⇒ Boolean
- #device_is_windows? ⇒ Boolean
-
#dialect ⇒ :oss | :w3c
Get the dialect value whether current driver is OSS or W3C.
-
#driver_attributes ⇒ Object
Returns a hash of the driver attributes.
-
#driver_quit ⇒ void
(also: #quit_driver)
Quits the driver.
-
#element_screenshot(element, png_save_path) ⇒ File
Takes a png screenshot of particular element’s area.
-
#execute_async_script(script, *args) ⇒ Object
Wrap calling selenium webdrier APIs via ruby_core.
-
#execute_script(script, *args) ⇒ Object
The same as @driver.execute_script.
-
#exists(pre_check = 0, post_check = @core.default_wait) { ... } ⇒ Boolean
Returns existence of element.
-
#find_element(*args) ⇒ Element
Calls @driver.find_element.
-
#find_element_by_image(png_img_path) ⇒ ::Appium::Core::ImageElement
Return ImageElement if current view has a partial image.
-
#find_elements(*args) ⇒ Array<Element>
Calls @driver.find_elements_with_appium.
-
#find_elements_by_image(png_img_paths) ⇒ [::Appium::Core::ImageElement], ::Appium::Core::Error::CoreError
Return ImageElement if current view has partial images.
- #get(url) ⇒ Object
-
#initialize(opts = {}, global_driver = nil) ⇒ Driver
constructor
Creates a new driver.
- #manage ⇒ Object
- #navigate ⇒ Object
-
#no_wait ⇒ Object
Set implicit wait to zero.
-
#platform_version ⇒ Array<Integer>
Return the platform version as an array of integers.
-
#restart ⇒ Driver
Restarts the driver.
-
#screenshot(png_save_path) ⇒ File
Takes a png screenshot and saves to the target path.
-
#server_url ⇒ String
Get the server url.
-
#set_implicit_wait(wait) ⇒ Object
To ignore error for Espresso Driver.
-
#set_location(opts = {}) ⇒ Selenium::WebDriver::Location
Calls @driver.set_location.
-
#set_wait(timeout = nil) ⇒ void
Set implicit wait.
-
#start_driver(http_client_ops = { http_client: ::Appium::Http::Default.new, open_timeout: 999_999, read_timeout: 999_999 }) ⇒ Selenium::WebDriver
Creates a new global driver and quits the old one if it exists.
- #switch_to ⇒ TargetLocator
- #title ⇒ Object
-
#window_handle ⇒ Object
Get the current window handle.
- #window_handles ⇒ Object
-
#window_rect ⇒ Selenium::WebDriver::Rectangle
Get the device window’s rect.
-
#window_size ⇒ Selenium::WebDriver::Dimension
Get the device window’s size.
-
#x ⇒ void
Quit the driver and Pry.
Constructor Details
#initialize(opts = {}, global_driver = nil) ⇒ Driver
Creates a new driver. The driver is defined as global scope by default. We can avoid defining global driver.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/appium_lib/driver.rb', line 140 def initialize(opts = {}, global_driver = nil) # TODO: set `global_driver = false` by default in the future. # Capybara can't put `global_driver` as the 2nd argument. global_driver = opts.delete :global_driver if global_driver.nil? if global_driver.nil? 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)' global_driver = true # if global_driver is nil, then global_driver must be default value. end if global_driver $driver.driver_quit if $driver end 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 @export_session = @core.export_session @export_session_path = @core.export_session_path @default_wait = @core.default_wait @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) (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 |
Instance Attribute Details
#appium_debug ⇒ Object (readonly)
Boolean debug mode for the Appium Ruby bindings
67 68 69 |
# File 'lib/appium_lib/driver.rb', line 67 def appium_debug @appium_debug end |
#appium_device ⇒ Object (readonly)
Returns the value of attribute appium_device.
57 58 59 |
# File 'lib/appium_lib/driver.rb', line 57 def appium_device @appium_device end |
#appium_port ⇒ Object (readonly)
Returns the value of attribute appium_port.
56 57 58 |
# File 'lib/appium_lib/driver.rb', line 56 def appium_port @appium_port end |
#appium_server_status ⇒ Object (readonly)
Appium’s server version
65 66 67 |
# File 'lib/appium_lib/driver.rb', line 65 def appium_server_status @appium_server_status end |
#appium_wait_interval ⇒ Object (readonly)
Returns the value of attribute appium_wait_interval.
62 63 64 |
# File 'lib/appium_lib/driver.rb', line 62 def appium_wait_interval @appium_wait_interval end |
#appium_wait_timeout ⇒ Object (readonly)
Returns the value of attribute appium_wait_timeout.
61 62 63 |
# File 'lib/appium_lib/driver.rb', line 61 def appium_wait_timeout @appium_wait_timeout end |
#automation_name ⇒ Object (readonly)
Returns the value of attribute automation_name.
58 59 60 |
# File 'lib/appium_lib/driver.rb', line 58 def automation_name @automation_name end |
#caps ⇒ Object (readonly)
51 52 53 |
# File 'lib/appium_lib/driver.rb', line 51 def caps @caps end |
#core ⇒ Object (readonly)
Instance of Appium::Core::Driver
72 73 74 |
# File 'lib/appium_lib/driver.rb', line 72 def core @core end |
#custom_url ⇒ Object (readonly)
Returns the value of attribute custom_url.
52 53 54 |
# File 'lib/appium_lib/driver.rb', line 52 def custom_url @custom_url end |
#default_wait ⇒ Object (readonly)
Returns the value of attribute default_wait.
55 56 57 |
# File 'lib/appium_lib/driver.rb', line 55 def default_wait @default_wait end |
#driver ⇒ Driver (readonly)
Returns the driver
70 71 72 |
# File 'lib/appium_lib/driver.rb', line 70 def driver @driver end |
#export_session ⇒ Object (readonly)
Returns the value of attribute export_session.
53 54 55 |
# File 'lib/appium_lib/driver.rb', line 53 def export_session @export_session end |
#export_session_path ⇒ Object (readonly)
Returns the value of attribute export_session_path.
54 55 56 |
# File 'lib/appium_lib/driver.rb', line 54 def export_session_path @export_session_path end |
#global_webdriver_http_sleep ⇒ Object
The amount to sleep in seconds before every webdriver http call.
35 36 37 |
# File 'lib/appium_lib/driver.rb', line 35 def global_webdriver_http_sleep @global_webdriver_http_sleep end |
#http_client ⇒ Object (readonly)
Returns the value of attribute http_client.
60 61 62 |
# File 'lib/appium_lib/driver.rb', line 60 def http_client @http_client end |
#listener ⇒ Object (readonly)
Returns the value of attribute listener.
59 60 61 |
# File 'lib/appium_lib/driver.rb', line 59 def listener @listener end |
#sauce ⇒ Object (readonly)
SauceLab’s settings
38 39 40 |
# File 'lib/appium_lib/driver.rb', line 38 def sauce @sauce end |
#sauce_access_key ⇒ Object (readonly)
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
44 45 46 |
# File 'lib/appium_lib/driver.rb', line 44 def sauce_access_key @sauce_access_key end |
#sauce_endpoint ⇒ Object (readonly)
Override the Sauce Appium endpoint to allow e.g. TestObject tests same as @sauce.endpoint
47 48 49 |
# File 'lib/appium_lib/driver.rb', line 47 def sauce_endpoint @sauce_endpoint end |
#sauce_username ⇒ Object (readonly)
Username for use on Sauce Labs. Set false to disable Sauce, even when SAUCE_USERNAME is in ENV. same as @sauce.username
41 42 43 |
# File 'lib/appium_lib/driver.rb', line 41 def sauce_username @sauce_username end |
Class Method Details
.absolute_app_path(opts) ⇒ String
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.
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
# File 'lib/appium_lib/driver.rb', line 398 def self.absolute_app_path(opts) raise 'opts must be a hash' unless opts.is_a? Hash caps = opts[:caps] || {} app_path = 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 absolute_app_path = File. app_path app_path = if File.exist? absolute_app_path absolute_app_path else ::Appium::Logger.info("Use #{app_path}") app_path end app_path end |
Instance Method Details
#action ⇒ TouchAction|Selenium::WebDriver::PointerActions
An entry point to chain W3C actions. Returns TouchAction.new if it works as MJSONWP instead of W3C action. Read www.rubydoc.info/github/appium/ruby_lib_core/Appium/Core/Base/Bridge/W3C#action-instance_method
341 342 343 344 345 346 347 348 |
# File 'lib/appium_lib/driver.rb', line 341 def action if @driver.dialect != :w3c ::Appium::Logger.info('Calls TouchAction instead of W3C actions for MJSONWP module') TouchAction.new($driver || @driver) else @driver.action end end |
#appium_client_version ⇒ Hash
Returns the client’s version info
386 387 388 |
# File 'lib/appium_lib/driver.rb', line 386 def appium_client_version { version: ::Appium::VERSION } end |
#appium_server_version ⇒ Hash Also known as: remote_status
Returns the server’s version info
361 362 363 364 365 366 367 368 |
# File 'lib/appium_lib/driver.rb', line 361 def appium_server_version @core.appium_server_version rescue Selenium::WebDriver::Error::WebDriverError => ex raise ::Appium::Core::Error::ServerError unless ex..include?('content-type=""') # server (TestObject for instance) does not respond to status call {} end |
#automation_name_is_espresso? ⇒ Boolean
Return true if automationName is ‘Espresso’
301 302 303 |
# File 'lib/appium_lib/driver.rb', line 301 def automation_name_is_espresso? !@core.automation_name.nil? && @core.automation_name == :espresso end |
#automation_name_is_uiautomator2? ⇒ Boolean
Return true if automationName is ‘uiautomator2’
295 296 297 |
# File 'lib/appium_lib/driver.rb', line 295 def automation_name_is_uiautomator2? !@core.automation_name.nil? && @core.automation_name == :uiautomator2 end |
#automation_name_is_xcuitest? ⇒ Boolean
Return true if automationName is ‘XCUITest’
307 308 309 |
# File 'lib/appium_lib/driver.rb', line 307 def automation_name_is_xcuitest? !@core.automation_name.nil? && @core.automation_name == :xcuitest end |
#current_url ⇒ Object
646 647 648 |
# File 'lib/appium_lib/driver.rb', line 646 def current_url @driver.current_url end |
#device_is_android? ⇒ Boolean
281 282 283 |
# File 'lib/appium_lib/driver.rb', line 281 def device_is_android? @core.device == :android end |
#device_is_ios? ⇒ Boolean
285 286 287 |
# File 'lib/appium_lib/driver.rb', line 285 def device_is_ios? @core.device == :ios end |
#device_is_windows? ⇒ Boolean
289 290 291 |
# File 'lib/appium_lib/driver.rb', line 289 def device_is_windows? @core.device == :windows end |
#dialect ⇒ :oss | :w3c
Get the dialect value whether current driver is OSS or W3C
327 328 329 |
# File 'lib/appium_lib/driver.rb', line 327 def dialect @driver.dialect end |
#driver_attributes ⇒ Object
Returns a hash of the driver attributes
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/appium_lib/driver.rb', line 259 def driver_attributes # rubocop:disable Layout/AlignHash { caps: @core.caps, automation_name: @core.automation_name, custom_url: @core.custom_url, export_session: @core.export_session, export_session_path: @core.export_session_path, default_wait: @core.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 } # rubocop:enable Layout/AlignHash end |
#driver_quit ⇒ void Also known as: quit_driver
This method returns an undefined value.
Quits the driver
464 465 466 |
# File 'lib/appium_lib/driver.rb', line 464 def driver_quit @core.quit_driver end |
#element_screenshot(element, png_save_path) ⇒ File
Takes a png screenshot of particular element’s area
457 458 459 460 |
# File 'lib/appium_lib/driver.rb', line 457 def element_screenshot(element, png_save_path) @driver.take_element_screenshot element, png_save_path nil end |
#execute_async_script(script, *args) ⇒ Object
Wrap calling selenium webdrier APIs via ruby_core
Get the window handles of open browser windows
621 622 623 |
# File 'lib/appium_lib/driver.rb', line 621 def execute_async_script(script, *args) @driver.execute_async_script script, *args end |
#execute_script(script, *args) ⇒ Object
The same as @driver.execute_script
613 614 615 |
# File 'lib/appium_lib/driver.rb', line 613 def execute_script(script, *args) @driver.execute_script script, *args end |
#exists(pre_check = 0, post_check = @core.default_wait) { ... } ⇒ Boolean
Returns existence of element.
Example:
exists { button(‘sign in’) } ? puts(‘true’) : puts(‘false’)
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 |
# File 'lib/appium_lib/driver.rb', line 589 def exists(pre_check = 0, post_check = @core.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) ⇒ Element
Calls @driver.find_element
If you call Appium.promote_appium_methods, you can call find_element directly.
699 700 701 |
# File 'lib/appium_lib/driver.rb', line 699 def find_element(*args) @driver.find_element(*args) end |
#find_element_by_image(png_img_path) ⇒ ::Appium::Core::ImageElement
Return ImageElement if current view has a partial image
714 715 716 |
# File 'lib/appium_lib/driver.rb', line 714 def find_element_by_image(png_img_path) @driver.find_element_by_image(png_img_path) end |
#find_elements(*args) ⇒ Array<Element>
Calls @driver.find_elements_with_appium
If you call Appium.promote_appium_methods, you can call find_elements directly.
If you call Appium.promote_appium_methods, you can call find_elements directly.
683 684 685 |
# File 'lib/appium_lib/driver.rb', line 683 def find_elements(*args) @driver.find_elements(*args) end |
#find_elements_by_image(png_img_paths) ⇒ [::Appium::Core::ImageElement], ::Appium::Core::Error::CoreError
Return ImageElement if current view has partial images
729 730 731 |
# File 'lib/appium_lib/driver.rb', line 729 def find_elements_by_image(png_img_paths) @driver.find_elements_by_image(png_img_paths) end |
#get(url) ⇒ Object
642 643 644 |
# File 'lib/appium_lib/driver.rb', line 642 def get(url) @driver.get(url) end |
#manage ⇒ Object
638 639 640 |
# File 'lib/appium_lib/driver.rb', line 638 def manage @driver.manage end |
#navigate ⇒ Object
634 635 636 |
# File 'lib/appium_lib/driver.rb', line 634 def navigate @driver.navigate end |
#no_wait ⇒ Object
Set implicit wait to zero.
558 559 560 |
# File 'lib/appium_lib/driver.rb', line 558 def no_wait @driver.manage.timeouts.implicit_wait = 0 end |
#platform_version ⇒ Array<Integer>
Return the platform version as an array of integers
373 374 375 |
# File 'lib/appium_lib/driver.rb', line 373 def platform_version @core.platform_version end |
#restart ⇒ Driver
Restarts the driver
430 431 432 433 |
# File 'lib/appium_lib/driver.rb', line 430 def restart driver_quit start_driver end |
#screenshot(png_save_path) ⇒ File
Takes a png screenshot and saves to the target path.
443 444 445 |
# File 'lib/appium_lib/driver.rb', line 443 def screenshot(png_save_path) @driver.save_screenshot png_save_path end |
#server_url ⇒ String
Get the server url
421 422 423 424 425 426 |
# File 'lib/appium_lib/driver.rb', line 421 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) ⇒ Object
To ignore error for Espresso Driver
547 548 549 550 551 552 553 554 555 |
# File 'lib/appium_lib/driver.rb', line 547 def set_implicit_wait(wait) @driver.manage.timeouts.implicit_wait = wait rescue Selenium::WebDriver::Error::UnknownError => e unless e..include?('The operation requested is not yet implemented by Espresso driver') raise ::Appium::Core::Error::ServerError end {} end |
#set_location(opts = {}) ⇒ Selenium::WebDriver::Location
This method does not work on real devices.
Calls @driver.set_location
742 743 744 745 746 747 |
# File 'lib/appium_lib/driver.rb', line 742 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) ⇒ void
This method returns an undefined value.
Set implicit wait. Default to @core.default_wait.
572 573 574 575 |
# File 'lib/appium_lib/driver.rb', line 572 def set_wait(timeout = nil) timeout = @core.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 }) ⇒ Selenium::WebDriver
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.
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
# File 'lib/appium_lib/driver.rb', line 526 def start_driver(http_client_ops = { http_client: ::Appium::Http::Default.new, open_timeout: 999_999, read_timeout: 999_999 }) @core.quit_driver # 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 ⇒ TargetLocator
656 657 658 |
# File 'lib/appium_lib/driver.rb', line 656 def switch_to @driver.switch_to end |
#title ⇒ Object
650 651 652 |
# File 'lib/appium_lib/driver.rb', line 650 def title @driver.title end |
#window_handle ⇒ Object
Get the current window handle
630 631 632 |
# File 'lib/appium_lib/driver.rb', line 630 def window_handle @driver.window_handle end |
#window_handles ⇒ Object
625 626 627 |
# File 'lib/appium_lib/driver.rb', line 625 def window_handles @driver.window_handles end |
#window_rect ⇒ Selenium::WebDriver::Rectangle
Get the device window’s rect.
493 494 495 |
# File 'lib/appium_lib/driver.rb', line 493 def window_rect @driver.window_rect end |
#window_size ⇒ Selenium::WebDriver::Dimension
Get the device window’s size.
478 479 480 |
# File 'lib/appium_lib/driver.rb', line 478 def window_size @driver.window_size end |
#x ⇒ void
This method returns an undefined value.
Quit the driver and Pry. quit and exit are reserved by Pry.
752 753 754 755 |
# File 'lib/appium_lib/driver.rb', line 752 def x driver_quit exit # exit pry end |