class Selenium::WebDriver::Remote::Bridge
w3c.github.io/webdriver/#endpoints @api private
Constants
- COMMANDS
- ESCAPE_CSS_REGEXP
- PORT
- QUIT_ERRORS
- UNICODE_CODE_POINT
Attributes
Public Class Methods
Initializes the bridge with the given server URL @param [String, URI] :url url for the remote server @param [Object] :http_client an HTTP client instance that implements the same protocol as Http::Default
@api private
# File lib/selenium/webdriver/remote/bridge.rb, line 38 def initialize(url:, http_client: nil) uri = url.is_a?(URI) ? url : URI.parse(url) uri.path += '/' unless uri.path.end_with?('/') @http = http_client || Http::Default.new @http.server_url = uri @file_detector = nil end
Public Instance Methods
alerts
# File lib/selenium/webdriver/remote/bridge.rb, line 112 def accept_alert execute :accept_alert end
actions
# File lib/selenium/webdriver/remote/bridge.rb, line 372 def action(async = false) ActionBuilder.new self, Interactions.pointer(:mouse, name: 'mouse'), Interactions.key('keyboard'), async end
finding elements
# File lib/selenium/webdriver/remote/bridge.rb, line 520 def active_element Element.new self, element_id_from(execute(:get_active_element)) end
# File lib/selenium/webdriver/remote/bridge.rb, line 120 def alert=(keys) execute :send_alert_text, {}, {value: keys.split(//), text: keys} end
# File lib/selenium/webdriver/remote/bridge.rb, line 124 def alert_text execute :get_alert_text end
# File lib/selenium/webdriver/remote/bridge.rb, line 81 def browser @browser ||= begin name = @capabilities.browser_name name ? name.tr(' ', '_').downcase.to_sym : 'unknown' end end
# File lib/selenium/webdriver/remote/bridge.rb, line 428 def clear_element(element) execute :element_clear, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 294 def clear_local_storage execute_script('localStorage.clear()') end
# File lib/selenium/webdriver/remote/bridge.rb, line 318 def clear_session_storage execute_script('sessionStorage.clear()') end
# File lib/selenium/webdriver/remote/bridge.rb, line 400 def click_element(element) execute :element_click, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 193 def close execute :close_window end
Creates session.
# File lib/selenium/webdriver/remote/bridge.rb, line 51 def create_session(capabilities) response = execute(:new_session, {}, prepare_capabilities_payload(capabilities)) @session_id = response['sessionId'] capabilities = response['capabilities'] raise Error::WebDriverError, 'no sessionId in returned payload' unless @session_id @capabilities = Capabilities.json_create(capabilities) case @capabilities[:browser_name] when 'chrome' extend(WebDriver::Chrome::Features) when 'firefox' extend(WebDriver::Firefox::Features) when 'msedge' extend(WebDriver::Edge::Features) when 'Safari', 'Safari Technology Preview' extend(WebDriver::Safari::Features) end end
# File lib/selenium/webdriver/remote/bridge.rb, line 116 def dismiss_alert execute :dismiss_alert end
# File lib/selenium/webdriver/remote/bridge.rb, line 464 def element_aria_label(element) execute :get_element_aria_label, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 460 def element_aria_role(element) execute :get_element_aria_role, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 447 def element_attribute(element, name) WebDriver.logger.info "Using script for :getAttribute of #{name}" execute_atom :getAttribute, element, name end
# File lib/selenium/webdriver/remote/bridge.rb, line 507 def element_displayed?(element) WebDriver.logger.info 'Using script for :isDisplayed' execute_atom :isDisplayed, element end
# File lib/selenium/webdriver/remote/bridge.rb, line 452 def element_dom_attribute(element, name) execute :get_element_attribute, id: element, name: name end
# File lib/selenium/webdriver/remote/bridge.rb, line 499 def element_enabled?(element) execute :is_element_enabled, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 476 def element_location(element) data = execute :get_element_rect, id: element Point.new data['x'], data['y'] end
# File lib/selenium/webdriver/remote/bridge.rb, line 488 def element_location_once_scrolled_into_view(element) send_keys_to_element(element, ['']) element_location(element) end
# File lib/selenium/webdriver/remote/bridge.rb, line 456 def element_property(element, name) execute :get_element_property, id: element, name: name end
# File lib/selenium/webdriver/remote/bridge.rb, line 482 def element_rect(element) data = execute :get_element_rect, id: element Rectangle.new data['x'], data['y'], data['width'], data['height'] end
# File lib/selenium/webdriver/remote/bridge.rb, line 270 def element_screenshot(element) execute :take_element_screenshot, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 503 def element_selected?(element) execute :is_element_selected, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 493 def element_size(element) data = execute :get_element_rect, id: element Dimension.new data['width'], data['height'] end
element properties
# File lib/selenium/webdriver/remote/bridge.rb, line 443 def element_tag_name(element) execute :get_element_tag_name, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 472 def element_text(element) execute :get_element_text, id: element end
# File lib/selenium/webdriver/remote/bridge.rb, line 468 def element_value(element) element_property element, 'value' end
# File lib/selenium/webdriver/remote/bridge.rb, line 512 def element_value_of_css_property(element, prop) execute :get_element_css_value, id: element, property_name: prop end
# File lib/selenium/webdriver/remote/bridge.rb, line 335 def execute_async_script(script, *args) result = execute :execute_async_script, {}, {script: script, args: args} unwrap_script_result result end
javascript execution
# File lib/selenium/webdriver/remote/bridge.rb, line 330 def execute_script(script, *args) result = execute :execute_script, {}, {script: script, args: args} unwrap_script_result result end
# File lib/selenium/webdriver/remote/bridge.rb, line 526 def find_element_by(how, what, parent_ref = []) how, what = convert_locator(how, what) return execute_atom(:findElements, Support::RelativeLocator.new(what).as_json).first if how == 'relative' parent_type, parent_id = parent_ref id = case parent_type when :element execute :find_child_element, {id: parent_id}, {using: how, value: what.to_s} when :shadow_root execute :find_shadow_child_element, {id: parent_id}, {using: how, value: what.to_s} else execute :find_element, {}, {using: how, value: what.to_s} end Element.new self, element_id_from(id) end
# File lib/selenium/webdriver/remote/bridge.rb, line 544 def find_elements_by(how, what, parent_ref = []) how, what = convert_locator(how, what) return execute_atom :findElements, Support::RelativeLocator.new(what).as_json if how == 'relative' parent_type, parent_id = parent_ref ids = case parent_type when :element execute :find_child_elements, {id: parent_id}, {using: how, value: what.to_s} when :shadow_root execute :find_shadow_child_elements, {id: parent_id}, {using: how, value: what.to_s} else execute :find_elements, {}, {using: how, value: what.to_s} end ids.map { |id| Element.new self, element_id_from(id) } end
# File lib/selenium/webdriver/remote/bridge.rb, line 242 def full_screen_window execute :fullscreen_window end
# File lib/selenium/webdriver/remote/bridge.rb, line 92 def get(url) execute :get, {}, {url: url} end
navigation
# File lib/selenium/webdriver/remote/bridge.rb, line 132 def go_back execute :back end
# File lib/selenium/webdriver/remote/bridge.rb, line 136 def go_forward execute :forward end
# File lib/selenium/webdriver/remote/bridge.rb, line 384 def keyboard raise Error::UnsupportedOperationError, '#keyboard is no longer supported, use #action instead' end
HTML 5
# File lib/selenium/webdriver/remote/bridge.rb, line 278 def local_storage_item(key, value = nil) if value execute_script("localStorage.setItem('#{key}', '#{value}')") else execute_script("return localStorage.getItem('#{key}')") end end
# File lib/selenium/webdriver/remote/bridge.rb, line 290 def local_storage_keys execute_script('return Object.keys(localStorage)') end
# File lib/selenium/webdriver/remote/bridge.rb, line 298 def local_storage_size execute_script('return localStorage.length') end
cookies
# File lib/selenium/webdriver/remote/bridge.rb, line 344 def manage @manage ||= WebDriver::Manager.new(self) end
# File lib/selenium/webdriver/remote/bridge.rb, line 233 def maximize_window(handle = :current) unless handle == :current raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size' end execute :maximize_window end
# File lib/selenium/webdriver/remote/bridge.rb, line 229 def minimize_window execute :minimize_window end
# File lib/selenium/webdriver/remote/bridge.rb, line 380 def mouse raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead' end
Create a new top-level browsing context w3c.github.io/webdriver/#new-window @param type [String] Supports two values: ‘tab’ and ‘window’.
Use 'tab' if you'd like the new window to share an OS-level window with the current browsing context. Use 'window' otherwise
@return [Hash] Containing ‘handle’ with the value of the window handle
and 'type' with the value of the created window type
# File lib/selenium/webdriver/remote/bridge.rb, line 164 def new_window(type) execute :new_window, {}, {type: type} end
# File lib/selenium/webdriver/remote/bridge.rb, line 148 def page_source execute_script('var source = document.documentElement.outerHTML;' \ 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \ 'return source;') end
# File lib/selenium/webdriver/remote/bridge.rb, line 396 def print_page(options = {}) execute :print_page, {}, {options: options} end
# File lib/selenium/webdriver/remote/bridge.rb, line 187 def quit execute :delete_session http.close rescue *QUIT_ERRORS end
# File lib/selenium/webdriver/remote/bridge.rb, line 197 def refresh execute :refresh end
# File lib/selenium/webdriver/remote/bridge.rb, line 392 def release_actions execute :release_actions end
# File lib/selenium/webdriver/remote/bridge.rb, line 286 def remove_local_storage_item(key) execute_script("localStorage.removeItem('#{key}')") end
# File lib/selenium/webdriver/remote/bridge.rb, line 310 def remove_session_storage_item(key) execute_script("sessionStorage.removeItem('#{key}')") end
# File lib/selenium/webdriver/remote/bridge.rb, line 246 def reposition_window(x, y) set_window_rect(x: x, y: y) end
# File lib/selenium/webdriver/remote/bridge.rb, line 213 def resize_window(width, height, handle = :current) raise Error::WebDriverError, 'Switch to desired window before changing its size' unless handle == :current set_window_rect(width: width, height: height) end
# File lib/selenium/webdriver/remote/bridge.rb, line 266 def screenshot execute :take_screenshot end
# File lib/selenium/webdriver/remote/bridge.rb, line 388 def send_actions(data) execute :actions, {}, {actions: data} end
# File lib/selenium/webdriver/remote/bridge.rb, line 404 def send_keys_to_element(element, keys) # TODO: rework file detectors before Selenium 4.0 if @file_detector local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact if local_files.any? keys = local_files.map { |local_file| upload(local_file) } keys = Array(keys.join("\n")) end end # Keep .split(//) for backward compatibility for now text = keys.join('') execute :element_send_keys, {id: element}, {value: text.split(//), text: text} end
Returns the current session ID.
# File lib/selenium/webdriver/remote/bridge.rb, line 77 def session_id @session_id || raise(Error::WebDriverError, 'no current session exists') end
# File lib/selenium/webdriver/remote/bridge.rb, line 302 def session_storage_item(key, value = nil) if value execute_script("sessionStorage.setItem('#{key}', '#{value}')") else execute_script("return sessionStorage.getItem('#{key}')") end end
# File lib/selenium/webdriver/remote/bridge.rb, line 314 def session_storage_keys execute_script('return Object.keys(sessionStorage)') end
# File lib/selenium/webdriver/remote/bridge.rb, line 322 def session_storage_size execute_script('return sessionStorage.length') end
# File lib/selenium/webdriver/remote/bridge.rb, line 255 def set_window_rect(x: nil, y: nil, width: nil, height: nil) params = {x: x, y: y, width: width, height: height} params.update(params) { |_k, v| Integer(v) unless v.nil? } execute :set_window_rect, {}, params end
# File lib/selenium/webdriver/remote/bridge.rb, line 562 def shadow_root(element) id = execute :get_element_shadow_root, id: element ShadowRoot.new self, shadow_root_id_from(id) end
# File lib/selenium/webdriver/remote/bridge.rb, line 88 def status execute :status end
# File lib/selenium/webdriver/remote/bridge.rb, line 432 def submit_element(element) form = find_element_by('xpath', "./ancestor-or-self::form", [:element, element]) execute_script("var e = arguments[0].ownerDocument.createEvent('Event');" \ "e.initEvent('submit', true, true);" \ 'if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }', form.as_json) end
# File lib/selenium/webdriver/remote/bridge.rb, line 181 def switch_to_default_content switch_to_frame nil end
# File lib/selenium/webdriver/remote/bridge.rb, line 172 def switch_to_frame(id) id = find_element_by('id', id) if id.is_a? String execute :switch_to_frame, {}, {id: id} end
# File lib/selenium/webdriver/remote/bridge.rb, line 177 def switch_to_parent_frame execute :switch_to_parent_frame end
# File lib/selenium/webdriver/remote/bridge.rb, line 168 def switch_to_window(name) execute :switch_to_window, {}, {handle: name} end
timeouts
# File lib/selenium/webdriver/remote/bridge.rb, line 100 def timeouts execute :get_timeouts, {} end
# File lib/selenium/webdriver/remote/bridge.rb, line 104 def timeouts=(timeouts) execute :set_timeout, {}, timeouts end
# File lib/selenium/webdriver/remote/bridge.rb, line 144 def title execute :get_title end
# File lib/selenium/webdriver/remote/bridge.rb, line 419 def upload(local_file) unless File.file?(local_file) WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!") raise Error::WebDriverError, "You are trying to work with something that isn't a file." end execute :upload_file, {}, {file: Zipper.zip_file(local_file)} end
# File lib/selenium/webdriver/remote/bridge.rb, line 140 def url execute :get_current_url end
# File lib/selenium/webdriver/remote/bridge.rb, line 209 def window_handle execute :get_window_handle end
window handling
# File lib/selenium/webdriver/remote/bridge.rb, line 205 def window_handles execute :get_window_handles end
# File lib/selenium/webdriver/remote/bridge.rb, line 250 def window_position data = execute :get_window_rect Point.new data['x'], data['y'] end
# File lib/selenium/webdriver/remote/bridge.rb, line 261 def window_rect data = execute :get_window_rect Rectangle.new data['x'], data['y'], data['width'], data['height'] end
# File lib/selenium/webdriver/remote/bridge.rb, line 219 def window_size(handle = :current) unless handle == :current raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size' end data = execute :get_window_rect Dimension.new data['width'], data['height'] end
Private Instance Methods
# File lib/selenium/webdriver/remote/bridge.rb, line 595 def commands(command) COMMANDS[command] end
# File lib/selenium/webdriver/remote/bridge.rb, line 629 def convert_locator(how, what) how = SearchContext::FINDERS[how.to_sym] || how case how when 'class name' how = 'css selector' what = ".#{escape_css(what.to_s)}" when 'id' how = 'css selector' what = "##{escape_css(what.to_s)}" when 'name' how = 'css selector' what = "*[name='#{escape_css(what.to_s)}']" when 'tag name' how = 'css selector' end if what.is_a?(Hash) what = what.each_with_object({}) do |(h, w), hash| h, w = convert_locator(h.to_s, w) hash[h] = w end end [how, what] end
# File lib/selenium/webdriver/remote/bridge.rb, line 616 def element_id_from(id) id['ELEMENT'] || id[Element::ELEMENT_KEY] end
Escapes invalid characters in CSS selector. @see mathiasbynens.be/notes/css-escapes
# File lib/selenium/webdriver/remote/bridge.rb, line 661 def escape_css(string) string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" } string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/) string end
# File lib/selenium/webdriver/remote/bridge.rb, line 591 def escaper @escaper ||= defined?(URI::Parser) ? URI::DEFAULT_PARSER : URI end
executes a command on the remote server.
@return [WebDriver::Remote::Response]
# File lib/selenium/webdriver/remote/bridge.rb, line 575 def execute(command, opts = {}, command_hash = nil) verb, path = 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 WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}") http.call(verb, path, command_hash)['value'] end
# File lib/selenium/webdriver/remote/bridge.rb, line 624 def prepare_capabilities_payload(capabilities) capabilities = {alwaysMatch: capabilities} if !capabilities['alwaysMatch'] && !capabilities['firstMatch'] {capabilities: capabilities} end
# File lib/selenium/webdriver/remote/bridge.rb, line 620 def shadow_root_id_from(id) id[ShadowRoot::ROOT_KEY] end
# File lib/selenium/webdriver/remote/bridge.rb, line 599 def unwrap_script_result(arg) case arg when Array arg.map { |e| unwrap_script_result(e) } when Hash element_id = element_id_from(arg) return Element.new(self, element_id) if element_id shadow_root_id = shadow_root_id_from(arg) return ShadowRoot.new self, shadow_root_id if shadow_root_id arg.each { |k, v| arg[k] = unwrap_script_result(v) } else arg end end