# encoding: utf-8 # Add status to WebDriver # https://code.google.com/p/selenium/issues/detail?id=5669 class Selenium::WebDriver::Driver # @private def status bridge.status end end class Selenium::WebDriver::Remote::Bridge # @private def status raw_execute :status end end class Selenium::WebDriver::Remote::Bridge command :status, :get, 'status' end # end Add status to WebDriver module Appium::Common # Implement useful features for element. class Selenium::WebDriver::Element # Note: For testing .text should be used over value, and name. # Returns the value attribute # # Fixes NoMethodError: undefined method `value' for Selenium::WebDriver::Element def value self.attribute :value end # Returns the name attribute # # Fixes NoMethodError: undefined method `name' for Selenium::WebDriver::Element def name self.attribute :name end # Returns the type attribute # # Fixes Selenium::WebDriver::Error::UnknownError: Not yet implemented def tag_name self.attribute :type end # For use with mobile tap. # # ```ruby # execute_script 'mobile: tap', :x => 0.0, :y => 0.98 # ``` # # https://github.com/appium/appium/wiki/Automating-mobile-gestures # @return [OpenStruct] the relative x, y in a struct. ex: { x: 0.50, y: 0.20 } def location_rel xy = self.location w = $driver.window_size OpenStruct.new( x: xy.x.to_f / w.width.to_f, y: xy.y.to_f / w.height.to_f ) end end end # module Appium::Common # Print JSON posted to Appium. Not scoped to an Appium module. # # Requires from lib/selenium/webdriver/remote.rb require 'selenium/webdriver/remote/capabilities' require 'selenium/webdriver/remote/bridge' require 'selenium/webdriver/remote/server_error' require 'selenium/webdriver/remote/response' require 'selenium/webdriver/remote/commands' require 'selenium/webdriver/remote/http/common' require 'selenium/webdriver/remote/http/default' # @private # Show http calls to the Selenium server. # # Invaluable for debugging. def patch_webdriver_bridge Selenium::WebDriver::Remote::Bridge.class_eval do # Code from lib/selenium/webdriver/remote/bridge.rb def raw_execute(command, opts = {}, command_hash = nil) verb, path = Selenium::WebDriver::Remote::COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}") path = path.dup path[':session_id'] = @session_id if path.include?(':session_id') begin opts.each { |key, value| path[key.inspect] = escaper.escape(value.to_s) } rescue IndexError raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}" end # convert /// into / path.gsub! /\/+/, '/' # change path from session/efac972c-941a-499c-803c-d7d008749/execute # to /execute # path may be nil, session, or not have anything after the session_id. path_str = path path_str = '/' + path_str unless path_str.nil? || path_str.length <= 0 || path_str[0] == '/' path_match = path.match /.*\h{8}-\h{4}-\h{4}-\h{4}-\h{12}/ path_str = path.sub(path_match[0], '') unless path_match.nil? puts "#{verb} #{path_str}" unless command_hash.nil? || command_hash.length == 0 print_command = command_hash.clone print_command.delete :args if print_command[:args] == [] mobile_find = 'mobile: find' if print_command[:script] == mobile_find args = print_command[:args] puts "#{mobile_find}"#" #{args}" # [[[[3, "sign"]]]] => [[[3, "sign"]]] # # [[[[4, "android.widget.EditText"], [7, "z"]], [[4, "android.widget.EditText"], [3, "z"]]]] # => [[[4, "android.widget.EditText"], [7, "z"]], [[4, "android.widget.EditText"], [3, "z"]]] args = args[0] option = args[0].to_s.downcase has_option = ! option.match(/all|scroll/).nil? puts option if has_option start = has_option ? 1 : 0 start.upto(args.length-1) do |selector_index| selectors = args[selector_index] selectors_size = selectors.length selectors.each_index do |pair_index| pair = selectors[pair_index] res = $driver.dynamic_code_to_string pair[0], pair[1] if selectors_size == 1 || pair_index >= selectors_size - 1 puts res elsif selectors_size > 1 && pair_index < selectors_size print res + '.' end end end # start.upto else ap print_command end end delay = $driver.global_webdriver_http_sleep sleep delay if !delay.nil? && delay > 0 # puts "verb: #{verb}, path #{path}, command_hash #{command_hash.to_json}" http.call verb, path, command_hash end # def end # class end # def # Print Appium's origValue error messages. class Selenium::WebDriver::Remote::Response # @private def error_message val = value case val when Hash msg = val['origValue'] || val['message'] or return 'unknown error' msg << " (#{ val['class'] })" if val['class'] when String msg = val else msg = "unknown error, status=#{status}: #{val.inspect}" end msg end end