lib/appium_lib/driver.rb in appium_lib-9.6.1 vs lib/appium_lib/driver.rb in appium_lib-9.7.0

- old
+ new

@@ -1,58 +1,5 @@ -require 'rubygems' -require 'ap' -require 'selenium-webdriver' -require 'nokogiri' - -# base -require_relative 'capabilities' - -# common -require_relative 'common/helper' -require_relative 'common/wait' -require_relative 'common/patch' -require_relative 'common/version' -require_relative 'common/error' -require_relative 'common/search_context' -require_relative 'common/command' -require_relative 'common/element/window' - -# ios -require_relative 'ios/helper' -require_relative 'ios/patch' -require_relative 'ios/errors' - -require_relative 'ios/element/alert' -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' - -# android -require_relative 'android/helper' -require_relative 'android/patch' -require_relative 'android/client_xpath' -require_relative 'android/element/alert' -require_relative 'android/element/button' -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' - -# device methods -require_relative 'device/device' -require_relative 'device/touch_actions' -require_relative 'device/multi_touch' - # Fix uninitialized constant Minitest (NameError) module Minitest # Fix superclass mismatch for class Spec class Runnable end @@ -60,264 +7,58 @@ end class Spec < Test end end +require_relative 'core/core' + module Appium REQUIRED_VERSION_XCUITEST = '1.6.0'.freeze - # Load arbitrary text ([toml format](https://github.com/toml-lang/toml)) - # The toml is parsed by https://github.com/fbernier/tomlrb . - # - # ``` - # [caps] - # app = "path/to/app" - # - # [appium_lib] - # port = 8080 - # ``` - # - # :app is expanded - # :require is expanded - # all keys are converted to symbols - # - # @param opts [Hash] file: '/path/to/appium.txt', verbose: true - # @return [hash] the symbolized hash with updated :app and :require keys - def self.load_settings(opts = {}) - raise 'opts must be a hash' unless opts.is_a? Hash - raise 'opts must not be empty' if opts.empty? - - toml = opts[:file] - raise 'Must pass a capability file which has [caps] and [appium_lib]' unless toml - verbose = opts.fetch :verbose, false - - Appium::Logger.info "appium settings path: #{toml}" if verbose - - toml_exists = File.exist? toml - Appium::Logger.info "Exists? #{toml_exists}" if verbose - - raise "toml doesn't exist #{toml}" unless toml_exists - require 'tomlrb' - Appium::Logger.info "Loading #{toml}" if verbose - - data = Tomlrb.load_file(toml, symbolize_keys: true) - if verbose - Appium::Logger.ap_info data unless data.empty? - end - - if data && data[:caps] && data[:caps][:app] && !data[:caps][:app].empty? - data[:caps][:app] = Appium::Driver.absolute_app_path data - end - - if data && data[:appium_lib] && data[:appium_lib][:require] - parent_dir = File.dirname toml - data[:appium_lib][:require] = expand_required_files(parent_dir, data[:appium_lib][:require]) - end - - data - end - - class << self - # rubocop:disable Style/Alias - alias_method :load_appium_txt, :load_settings - end - - # @param [String] base_dir parent directory of loaded appium.txt (toml) - # @param [String] file_paths - # @return [Array] list of require files as an array, nil if require doesn't exist - def self.expand_required_files(base_dir, file_paths) - # ensure files are absolute - Array(file_paths).map! do |f| - file = File.exist?(f) ? f : File.join(base_dir, f) - file = File.expand_path file - - File.exist?(file) ? file : nil - end - file_paths.compact! # remove nils - - files = [] - - # now expand dirs - file_paths.each do |item| - unless File.directory? item - # save file - files << item - next # only look inside folders - end - Dir.glob(File.expand_path(File.join(item, '**', '*.rb'))) do |f| - # do not add folders to the file list - files << File.expand_path(f) unless File.directory? f - end - end - - files - end - - # convert all keys (including nested) to symbols - # - # based on deep_symbolize_keys & deep_transform_keys from rails - # https://github.com/rails/docrails/blob/a3b1105ada3da64acfa3843b164b14b734456a50/activesupport/lib/active_support/core_ext/hash/keys.rb#L84 - def self.symbolize_keys(hash) - raise 'symbolize_keys requires a hash' unless hash.is_a? Hash - result = {} - hash.each do |key, value| - key = key.to_sym rescue key # rubocop:disable Style/RescueModifier - result[key] = value.is_a?(Hash) ? symbolize_keys(value) : value - end - result - end - - # This method is intended to work with page objects that share - # a common module. For example, Page::HomePage, Page::SignIn - # those could be promoted on with Appium.promote_singleton_appium_methods Page - # - # If you are promoting on an individual class then you should use - # Appium.promote_appium_methods instead. The singleton method is intended - # 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, driver = $driver) - raise 'Global $driver is nil' if driver.nil? - - target_modules = [] - - if modules.is_a? Module - modules.constants.each do |sub_module| - target_modules << modules.const_get(sub_module) - end - else - raise 'modules must be a module or an array' unless modules.is_a? Array - target_modules = modules - end - - target_modules.each do |const| - # noinspection RubyResolve - # rubocop:disable Style/MultilineIfModifier - 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) - 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 - # rubocop:enable Style/MultilineIfModifier - end - end - - ## - # Promote appium methods to class instance methods - # - # @param class_array [Array<Class>] An array of classes - # - # To promote methods to all classes: - # - # ```ruby - # Appium.promote_appium_methods Object - # ``` - # - # It's better to promote on specific classes instead of Object - # - # ```ruby - # # promote on rspec - # Appium.promote_appium_methods RSpec::Core::ExampleGroup - # ``` - # - # ```ruby - # # promote on minispec - # Appium.promote_appium_methods Minitest::Spec - # ``` - 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| - klass.class_eval do - define_method m do |*args, &block| - begin - # Prefer existing method. - # super will invoke method missing on driver - super(*args, &block) - - # 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) - end - end - end - end - end - nil # return nil - end - - def self.selenium_webdriver_version_more?(version) - require 'rubygems' - Gem.loaded_specs['selenium-webdriver'].version >= Gem::Version.new(version) - end - class Driver # attr readers are promoted to global scope. To avoid clobbering, they're # made available via the driver_attributes method # # attr_accessor is repeated for each one so YARD documents them properly. # The amount to sleep in seconds before every webdriver http call. attr_accessor :global_webdriver_http_sleep - # Selenium webdriver capabilities - attr_reader :caps - # Custom URL for the selenium server - attr_reader :custom_url - # Export session id to textfile in /tmp for 3rd party tools - attr_reader :export_session - # Default wait time for elements to appear - # Returns the default client side wait. - # This value is independent of what the server is using - # @return [Integer] - attr_reader :default_wait + + # SauceLab's settings + attr_reader :sauce # Username for use on Sauce Labs. Set `false` to disable Sauce, even when SAUCE_USERNAME is in ENV. + # same as @sauce.username attr_reader :sauce_username # 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 attr_reader :sauce_access_key # Override the Sauce Appium endpoint to allow e.g. TestObject tests + # same as @sauce.endpoint attr_reader :sauce_endpoint - # Appium's server port + + # from Core + attr_reader :caps + attr_reader :custom_url + attr_reader :export_session + attr_reader :default_wait attr_reader :appium_port - # Device type to request from the appium server attr_reader :appium_device - # Automation name sent to appium server or received from server - # If automation_name is nil, it is not set both client side and server side. attr_reader :automation_name + attr_reader :listener + attr_reader :http_client + attr_reader :appium_wait_timeout + attr_reader :appium_wait_interval + # Appium's server version attr_reader :appium_server_status # Boolean debug mode for the Appium Ruby bindings attr_reader :appium_debug - # instance of AbstractEventListener for logging support - attr_reader :listener # Returns the driver # @return [Driver] the driver attr_reader :driver - # Return http client called in start_driver() - # @return [Selenium::WebDriver::Remote::Http::Default] the http client - attr_reader :http_client - # Return a time wait timeout - # Wait time for ::Appium::Common.wait or ::Appium::Common.wait_true. - # Provide Appium::Drive like { appium_lib: { wait_timeout: 20 } } - # @return [Integer] - attr_reader :appium_wait_timeout - # Return a time wait timeout - # 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 + # Instance of Appium::Core::Driver + attr_reader :core # Creates a new driver. The driver is defined as global scope by default. # We can avoid defining global driver. # # @example @@ -336,11 +77,11 @@ # }, # appium_lib: { # wait_timeout: 30 # } # } - # Appium::Driver.new(opts).start_driver + # Appium::Driver.new(opts, true).start_driver # # # Start Android driver with global scope # opts = { # caps: { # platformName: :android, @@ -349,11 +90,11 @@ # appium_lib: { # wait_timeout: 30, # wait_interval: 1 # } # } - # Appium::Driver.new(opts).start_driver + # Appium::Driver.new(opts, true).start_driver # # # Start iOS driver without global scope # opts = { # caps: { # platformName: :ios, @@ -368,10 +109,11 @@ # # @param opts [Object] A hash containing various options. # @param global_driver [Bool] A bool require global driver before initialize. # @return [Driver] def initialize(opts = {}, global_driver = nil) + # TODO: set `global_driver = false` by default in the future. 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. @@ -380,157 +122,159 @@ if global_driver $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] || {}) + @core = Appium::Core.for(self, opts) - appium_lib_opts = opts[:appium_lib] || {} + opts = Appium.symbolize_keys opts + appium_lib_opts = opts[:appium_lib] || {} - set_appium_lib_specific_values(appium_lib_opts) + @caps = @core.caps + @custom_url = @core.custom_url + @export_session = @core.export_session + @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 - # Path to the .apk, .app or .app.zip. - # The path can be local or remote for Sauce. - if @caps && @caps[:app] && !@caps[:app].empty? - @caps[:app] = self.class.absolute_app_path opts - end + # override opts[:app] if sauce labs + set_app_path(opts) - # https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile - @appium_device = @caps[:platformName] - @appium_device = @appium_device.is_a?(Symbol) ? @appium_device : @appium_device.downcase.strip.intern if @appium_device + # enable debug patch + @appium_debug = appium_lib_opts.fetch :debug, !!defined?(Pry) + set_sauce_related_values(appium_lib_opts) - @automation_name = @caps[:automationName] if @caps[:automationName] - @automation_name = if @automation_name - @automation_name.is_a?(Symbol) ? @automation_name : @automation_name.downcase.strip.intern - end - - # load common methods + # Extend Common methods 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 - extend Appium::Android::Uiautomator2::Helper - extend Appium::Android::Uiautomator2::Element - end - else - extend Appium::Ios - if automation_name_is_xcuitest? - extend Appium::Ios::Xcuitest - extend Appium::Ios::Xcuitest::SearchContext - extend Appium::Ios::Xcuitest::Command - extend Appium::Ios::Xcuitest::Helper - extend Appium::Ios::Xcuitest::Gesture - extend Appium::Ios::Xcuitest::Device - extend Appium::Ios::Xcuitest::Element - end - end + # Extend each driver's methods + extend_for(device: @core.device, automation_name: @core.automation_name) - # apply os specific patches - patch_webdriver_element - # for command - patch_remote_driver_commands - # enable debug patch - # !!'constant' == true - @appium_debug = appium_lib_opts.fetch :debug, !!defined?(Pry) - if @appium_debug Appium::Logger.ap_debug opts unless opts.empty? Appium::Logger.debug "Debug is: #{@appium_debug}" - Appium::Logger.debug "Device is: #{@appium_device}" - patch_webdriver_bridge + 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 # return newly created driver end private - def set_appium_lib_specific_values(appium_lib_opts) - @custom_url = appium_lib_opts.fetch :server_url, false - @export_session = appium_lib_opts.fetch :export_session, false - @default_wait = appium_lib_opts.fetch :wait, 0 + # @private + def extend_for(device:, automation_name:) + case device + when :android + case automation_name + when :uiautomator2 + ::Appium::Android::Uiautomator2::Bridge.for(self) + else # default and UiAutomator + ::Appium::Android::Bridge.for(self) + end + when :ios + case automation_name + when :xcuitest + ::Appium::Ios::Xcuitest::Bridge.for(self) + else # default and UIAutomation + ::Appium::Ios::Bridge.for(self) + end + when :mac + # no Mac specific extentions + Appium::Logger.debug('mac') + when :windows + # no windows specific extentions + Appium::Logger.debug('windows') + else + Appium::Logger.warn('no device matched') + end + end - @sauce_username = appium_lib_opts.fetch :sauce_username, ENV['SAUCE_USERNAME'] - @sauce_username = nil if !@sauce_username || (@sauce_username.is_a?(String) && @sauce_username.empty?) - @sauce_access_key = appium_lib_opts.fetch :sauce_access_key, ENV['SAUCE_ACCESS_KEY'] - @sauce_access_key = nil if !@sauce_access_key || (@sauce_access_key.is_a?(String) && @sauce_access_key.empty?) - @sauce_endpoint = appium_lib_opts.fetch :sauce_endpoint, ENV['SAUCE_ENDPOINT'] - @sauce_endpoint = 'ondemand.saucelabs.com:443/wd/hub' if - !@sauce_endpoint || (@sauce_endpoint.is_a?(String) && @sauce_endpoint.empty?) + # @private + def set_app_path(opts) + return unless @core.caps && @core.caps[:app] && !@core.caps[:app].empty? - @appium_port = appium_lib_opts.fetch :port, 4723 - # timeout and interval used in ::Appium::Comm.wait/wait_true - @appium_wait_timeout = appium_lib_opts.fetch :wait_timeout, 30 - @appium_wait_interval = appium_lib_opts.fetch :wait_interval, 0.5 + @core.caps[:app] = self.class.absolute_app_path opts + end - # to pass it in Selenium.new. - # `listener = opts.delete(:listener)` is called in Selenium::Driver.new - @listener = appium_lib_opts.fetch :listener, nil + # @private + def set_sauce_related_values(appium_lib_opts) + @sauce = Appium::SauceLabs.new(appium_lib_opts) + @sauce_username = @sauce.username + @sauce_access_key = @sauce.access_key + @sauce_endpoint = @sauce.endpoint end public # Returns a hash of the driver attributes def driver_attributes { - caps: @caps, - automation_name: @automation_name, - custom_url: @custom_url, - export_session: @export_session, - default_wait: @default_wait, - sauce_username: @sauce_username, - sauce_access_key: @sauce_access_key, - sauce_endpoint: @sauce_endpoint, - port: @appium_port, - device: @appium_device, + caps: @core.caps, + automation_name: @core.automation_name, + custom_url: @core.custom_url, + export_session: @core.export_session, + 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: @appium_wait_timeout, - wait_interval: @appium_wait_interval + wait_timeout: @core.wait_timeout, + wait_interval: @core.wait_interval } end def device_is_android? - @appium_device == :android + @core.device == :android end - # Return true if automationName is 'XCUITest' - # @return [Boolean] - def automation_name_is_xcuitest? - !@automation_name.nil? && @automation_name == :xcuitest + def device_is_ios? + @core.device == :ios end + def device_is_windows? + @core.device == :windows + end + # Return true if automationName is 'uiautomator2' # @return [Boolean] def automation_name_is_uiautomator2? - !@automation_name.nil? && @automation_name == :uiautomator2 + !@core.automation_name.nil? && @core.automation_name == :uiautomator2 end # Return true if automationName is 'Espresso' # @return [Boolean] def automation_name_is_espresso? - !@automation_name.nil? && @automation_name == :espresso + !@core.automation_name.nil? && @core.automation_name == :espresso end + # Return true if automationName is 'XCUITest' + # @return [Boolean] + def automation_name_is_xcuitest? + !@core.automation_name.nil? && @core.automation_name == :xcuitest + 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? && !@appium_server_status.empty? && (@appium_server_status['build']['version'] < REQUIRED_VERSION_XCUITEST) - raise Appium::Error::NotSupportedAppiumServer, "XCUITest requires Appium version >= #{REQUIRED_VERSION_XCUITEST}" + raise(Appium::Core::Error::NotSupportedAppiumServer, + "XCUITest requires Appium version >= #{REQUIRED_VERSION_XCUITEST}") end true end # Returns the server's version info @@ -542,29 +286,31 @@ # "revision" => "d242ebcfd92046a974347ccc3a28f0e898595198" # } # } # ``` # - # Returns blank hash for Selenium Grid since `remote_status` gets 500 error - # - # ```ruby - # {} - # ``` - # # @return [Hash] def appium_server_version - driver.remote_status + @core.appium_server_version rescue Selenium::WebDriver::Error::WebDriverError => ex - raise ::Appium::Error::ServerError unless ex.message.include?('content-type=""') + raise ::Appium::Core::Error::ServerError unless ex.message.include?('content-type=""') # server (TestObject for instance) does not respond to status call {} - rescue Selenium::WebDriver::Error::ServerError => e - raise ::Appium::Error::ServerError unless e.message.include?('status code 500') - # driver.remote_status returns 500 error for using selenium grid - {} end + # Return the platform version as an array of integers + # @return [Array<Integer>] + def platform_version + @core.platform_version + end + + # @private + def ios_version + warn '[DEPRECATION] ios_version will be removed. Please use platform_version instead.' + platform_version + end + # Returns the client's version info # # ```ruby # { # "version" => "9.1.1" @@ -616,16 +362,13 @@ end # Get the server url # @return [String] the server url def server_url - return @custom_url if @custom_url - if !@sauce_username.nil? && !@sauce_access_key.nil? - "https://#{@sauce_username}:#{@sauce_access_key}@#{@sauce_endpoint}" - else - "http://127.0.0.1:#{@appium_port}/wd/hub" - end + 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 # Restarts the driver # @return [Driver] the driver def restart @@ -638,25 +381,30 @@ # Example: screenshot '/tmp/hi.png' # # @param png_save_path [String] the full path to save the png # @return [nil] def screenshot(png_save_path) - @driver.save_screenshot png_save_path - nil + @core.screenshot png_save_path end # Quits the driver # @return [void] def driver_quit - # rescue NoSuchDriverError or nil driver - @driver.quit - rescue - nil + @core.quit_driver end + alias quit_driver driver_quit - # Alias for driver_quit - alias_method :quit_driver, :driver_quit + # Get the device window's size. + # @return [Selenium::WebDriver::Dimension] + # + # @example + # size = @driver.window_size + # size.width #=> Integer + # size.height #=> Integer + def window_size + @driver.window_size + end # Creates a new global driver and quits the old one if it exists. # You can customise http_client as the following # # @example @@ -681,75 +429,58 @@ # @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 def start_driver(http_client_ops = { http_client: nil, open_timeout: 999_999, read_timeout: 999_999 }) - # open_timeout and read_timeout are explicit wait. - open_timeout = http_client_ops.delete(:open_timeout) - read_timeout = http_client_ops.delete(:read_timeout) + driver_quit - http_client = http_client_ops.delete(:http_client) - @http_client ||= http_client ? http_client : Selenium::WebDriver::Remote::Http::Default.new + # If automationName is set only in server side, then the following automation_name should be nil before + # starting driver. + automation_name = @core.automation_name - @http_client.open_timeout = open_timeout if open_timeout - @http_client.read_timeout = read_timeout if read_timeout + @driver = @core.start_driver(server_url: server_url, http_client_ops: http_client_ops) + @http_client = @core.http_client - begin - driver_quit - @driver = Selenium::WebDriver.for(:remote, - http_client: @http_client, - desired_capabilities: @caps, - url: server_url, - listener: @listener) + # 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? - # Load touch methods. - @driver.extend Selenium::WebDriver::DriverExtensions::HasTouchScreen - @driver.extend Selenium::WebDriver::DriverExtensions::HasLocation - - # export session - write_session_id(@driver.session_id) if @export_session - rescue Errno::ECONNREFUSED - raise "ERROR: Unable to connect to Appium. Is the server running on #{server_url}?" - end - @appium_server_status = appium_server_version - check_server_version_xcuitest - set_automation_name_if_nil - set_implicit_wait(@default_wait) + set_implicit_wait(@core.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 + raise ::Appium::Core::Error::ServerError end {} end # Set implicit wait to zero. def no_wait @driver.manage.timeouts.implicit_wait = 0 end - # Set implicit wait. Default to @default_wait. + # Set implicit wait. Default to @core.default_wait. # # ```ruby # set_wait 2 - # set_wait # @default_wait + # set_wait # @core.default_wait # # ``` # # @param timeout [Integer] the timeout in seconds # @return [void] def set_wait(timeout = nil) - timeout = @default_wait if timeout.nil? + timeout = @core.default_wait if timeout.nil? @driver.manage.timeouts.implicit_wait = timeout end # Returns existence of element. # @@ -761,11 +492,11 @@ # 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] - def exists(pre_check = 0, post_check = @default_wait) + 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. @@ -791,21 +522,23 @@ @driver.execute_script script, *args end # Calls @driver.find_elements_with_appium # - # ``` - # @driver = Appium::Driver.new() - # @driver.find_elements :predicate, yyy - # ``` + # @example + # ```ruby + # @driver = Appium::Driver.new(opts, false) + # @driver.find_elements :predicate, yyy + # ``` # # If you call `Appium.promote_appium_methods`, you can call `find_elements` directly. # - # ``` - # @driver = Appium::Driver.new() - # @driver.find_elements :predicate, yyy - # ``` + # @example + # ```ruby + # @driver = Appium::Driver.new(opts, false) + # @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. @@ -813,14 +546,15 @@ @driver.find_elements(*args) end # Calls @driver.find_element # - # ``` - # @driver = Appium::Driver.new() - # @driver.find_element :accessibility_id, zzz - # ``` + # @example + # ```ruby + # @driver = Appium::Driver.new(opts, false) + # @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] @@ -852,21 +586,15 @@ exit # exit pry end private + # @private def write_session_id(session_id) File.open('/tmp/appium_lib_session', 'w') { |f| f.puts session_id } rescue IOError => e ::Appium::Logger.warn e nil - end - - # If "automationName" is set only server side, this method set "automationName" attribute into @automation_name. - # Since @automation_name is set only client side before start_driver is called. - def set_automation_name_if_nil - return unless @automation_name.nil? - @automation_name = @driver.capabilities['automationName'] end end # class Driver end # module Appium # Paging in Pry is annoying :q required to exit.