Path: blob/trunk/rb/lib/selenium/webdriver/common/driver.rb
1865 views
# frozen_string_literal: true12# Licensed to the Software Freedom Conservancy (SFC) under one3# or more contributor license agreements. See the NOTICE file4# distributed with this work for additional information5# regarding copyright ownership. The SFC licenses this file6# to you under the Apache License, Version 2.0 (the7# "License"); you may not use this file except in compliance8# with the License. You may obtain a copy of the License at9#10# http://www.apache.org/licenses/LICENSE-2.011#12# Unless required by applicable law or agreed to in writing,13# software distributed under the License is distributed on an14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY15# KIND, either express or implied. See the License for the16# specific language governing permissions and limitations17# under the License.1819module Selenium20module WebDriver21#22# The main class through which you control the browser.23#24# @see SearchContext25# @see Navigation26# @see TargetLocator27# @see Options28#2930class Driver31include SearchContext32include TakesScreenshot3334class << self35#36# @api private37#38# @see Selenium::WebDriver.for39#40# @return [Driver]41#4243def for(browser, opts = {})44case browser45when :chrome, :chrome_headless_shell46Chrome::Driver.new(**opts)47when :internet_explorer, :ie48IE::Driver.new(**opts)49when :safari50Safari::Driver.new(**opts)51when :firefox, :ff52Firefox::Driver.new(**opts)53when :edge, :microsoftedge, :msedge54Edge::Driver.new(**opts)55when :remote56Remote::Driver.new(**opts)57else58raise ArgumentError, "unknown driver: #{browser.inspect}"59end60end61end6263#64# A new Driver instance with the given bridge.65# End users should use Selenium::WebDriver.for instead of using this directly.66#67# @api private68#6970def initialize(bridge: nil, listener: nil, **)71@devtools = nil72bridge ||= create_bridge(**)73@bridge = listener ? Support::EventFiringBridge.new(bridge, listener) : bridge74add_extensions(@bridge.browser)75end7677def inspect78format '#<%<class>s:0x%<hash>x browser=%<browser>s>', class: self.class, hash: hash * 2,79browser: bridge.browser.inspect80end8182#83# information about whether a remote end is in a state in which it can create new sessions,84# and may include additional meta information.85#86# @return [Hash]87#88def status89@bridge.status90end9192#93# @return [Navigation]94# @see Navigation95#9697def navigate98@navigate ||= WebDriver::Navigation.new(bridge)99end100101#102# @return [Script]103# @see Script104#105106def script107@script ||= WebDriver::Script.new(bridge)108end109110#111# @return [TargetLocator]112# @see TargetLocator113#114115def switch_to116@switch_to ||= WebDriver::TargetLocator.new(bridge)117end118119#120# @return [Manager]121# @see Manager122#123124def manage125bridge.manage126end127128#129# @return [ActionBuilder]130# @see ActionBuilder131#132133def action(**)134bridge.action(**)135end136137#138# Opens the specified URL in the browser.139#140141def get(url)142navigate.to(url)143end144145#146# Get the URL of the current page147#148# @return [String]149#150151def current_url152bridge.url153end154155#156# Get the title of the current page157#158# @return [String]159#160161def title162bridge.title163end164165#166# Get the source of the current page167#168# @return [String]169#170171def page_source172bridge.page_source173end174175#176# Quit the browser177#178179def quit180bridge.quit181ensure182@service_manager&.stop183@devtools&.each_value(&:close)184end185186#187# Close the current window, or the browser if no windows are left.188#189190def close191bridge&.close192end193194#195# Get the window handles of open browser windows.196#197# @return [Array]198# @see TargetLocator#window199#200201def window_handles202bridge.window_handles203end204205#206# Get the current window handle207#208# @return [String]209#210211def window_handle212bridge.window_handle213end214215#216# Execute the given JavaScript217#218# @param [String] script219# JavaScript source to execute220# @param [WebDriver::Element, Integer, Float, Boolean, NilClass, String, Array] args221# Arguments will be available in the given script in the 'arguments' pseudo-array.222#223# @return [WebDriver::Element,Integer,Float,Boolean,NilClass,String,Array]224# The value returned from the script.225#226227def execute_script(script, *)228bridge.execute_script(script, *)229end230231# Execute an asynchronous piece of JavaScript in the context of the232# currently selected frame or window. Unlike executing233# execute_script (synchronous JavaScript), scripts234# executed with this method must explicitly signal they are finished by235# invoking the provided callback. This callback is always injected into the236# executed function as the last argument.237#238# @param [String] script239# JavaScript source to execute240# @param [WebDriver::Element,Integer, Float, Boolean, NilClass, String, Array] args241# Arguments to the script. May be empty.242#243# @return [WebDriver::Element,Integer,Float,Boolean,NilClass,String,Array]244#245246def execute_async_script(script, *)247bridge.execute_async_script(script, *)248end249250#251# @return [VirtualAuthenticator]252# @see VirtualAuthenticator253#254255def add_virtual_authenticator(options)256bridge.add_virtual_authenticator(options)257end258259#260# @return [Network]261# @see Network262#263264def network265@network ||= WebDriver::Network.new(bridge)266end267268#-------------------------------- sugar --------------------------------269270#271# driver.first(id: 'foo')272#273274alias first find_element275276#277# driver.all(class: 'bar') #=> [#<WebDriver::Element:0x1011c3b88, ...]278#279280alias all find_elements281282# Get the first element matching the given selector. If given a283# String or Symbol, it will be used as the id of the element.284#285# @param [String,Hash] sel id or selector286# @return [WebDriver::Element]287#288# Examples:289#290# driver['someElementId'] #=> #<WebDriver::Element:0x1011c3b88>291# driver[:tag_name => 'div'] #=> #<WebDriver::Element:0x1011c3b88>292#293294def [](sel)295sel = {id: sel} if sel.is_a?(String) || sel.is_a?(Symbol)296297find_element sel298end299300def browser301bridge.browser302end303304def capabilities305bridge.capabilities306end307308#309# @api private310# @see SearchContext311#312313def ref314[:driver, nil]315end316317private318319attr_reader :bridge320321def create_bridge(caps:, url:, http_client: nil)322klass = caps['webSocketUrl'] ? Remote::BiDiBridge : Remote::Bridge323klass.new(http_client: http_client, url: url).tap do |bridge|324bridge.create_session(caps)325end326end327328def service_url(service)329@service_manager = service.launch330@service_manager.uri331end332333def screenshot334bridge.screenshot335end336337def add_extensions(browser)338extensions = case browser339when :chrome, :chrome_headless_shell, :msedge, :microsoftedge340Chromium::Driver::EXTENSIONS341when :firefox342Firefox::Driver::EXTENSIONS343when :safari, :safari_technology_preview344Safari::Driver::EXTENSIONS345when :ie, :internet_explorer346IE::Driver::EXTENSIONS347else348[]349end350extensions.each { |extension| extend extension }351end352end # Driver353end # WebDriver354end # Selenium355356357