selenium-webdriver 4.2.1 → 4.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +252 -0
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +2 -2
- data/bin/linux/selenium-manager +0 -0
- data/bin/macos/selenium-manager +0 -0
- data/bin/windows/selenium-manager.exe +0 -0
- data/lib/selenium/server.rb +22 -30
- data/lib/selenium/webdriver/atoms/findElements.js +3 -4
- data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
- data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
- data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
- data/lib/selenium/webdriver/atoms.rb +5 -3
- data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
- data/lib/selenium/webdriver/{common/driver_extensions/has_network_connection.rb → bidi/browsing_context_info.rb} +10 -12
- data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
- data/lib/selenium/webdriver/{common/driver_extensions/has_location.rb → bidi/log/filter_by.rb} +14 -11
- data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
- data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
- data/lib/selenium/webdriver/bidi/session.rb +13 -0
- data/lib/selenium/webdriver/bidi.rb +3 -2
- data/lib/selenium/webdriver/chrome/driver.rb +9 -29
- data/lib/selenium/webdriver/chrome/features.rb +8 -71
- data/lib/selenium/webdriver/chrome/options.rb +3 -223
- data/lib/selenium/webdriver/chrome/profile.rb +3 -83
- data/lib/selenium/webdriver/chrome/service.rb +4 -19
- data/lib/selenium/webdriver/chrome.rb +0 -16
- data/lib/selenium/webdriver/chromium/driver.rb +60 -0
- data/lib/selenium/webdriver/chromium/features.rb +99 -0
- data/lib/selenium/webdriver/chromium/options.rb +243 -0
- data/lib/selenium/webdriver/chromium/profile.rb +113 -0
- data/lib/selenium/webdriver/chromium.rb +29 -0
- data/lib/selenium/webdriver/common/action_builder.rb +11 -58
- data/lib/selenium/webdriver/common/child_process.rb +124 -0
- data/lib/selenium/webdriver/common/driver.rb +29 -79
- data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +0 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb +65 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +0 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -69
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +0 -2
- data/lib/selenium/webdriver/common/driver_finder.rb +45 -0
- data/lib/selenium/webdriver/common/element.rb +7 -7
- data/lib/selenium/webdriver/common/error.rb +27 -4
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +19 -36
- data/lib/selenium/webdriver/common/interactions/pointer_move.rb +2 -2
- data/lib/selenium/webdriver/common/interactions/scroll.rb +7 -5
- data/lib/selenium/webdriver/common/local_driver.rb +46 -0
- data/lib/selenium/webdriver/common/logger.rb +90 -25
- data/lib/selenium/webdriver/common/manager.rb +0 -27
- data/lib/selenium/webdriver/common/options.rb +17 -17
- data/lib/selenium/webdriver/common/platform.rb +4 -50
- data/lib/selenium/webdriver/common/port_prober.rb +1 -1
- data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
- data/lib/selenium/webdriver/common/proxy.rb +2 -2
- data/lib/selenium/webdriver/common/selenium_manager.rb +134 -0
- data/lib/selenium/webdriver/common/service.rb +21 -30
- data/lib/selenium/webdriver/common/service_manager.rb +6 -12
- data/lib/selenium/webdriver/common/shadow_root.rb +1 -2
- data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
- data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
- data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
- data/lib/selenium/webdriver/common/target_locator.rb +2 -3
- data/lib/selenium/webdriver/common/timeouts.rb +2 -2
- data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
- data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
- data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
- data/lib/selenium/webdriver/common/websocket_connection.rb +22 -7
- data/lib/selenium/webdriver/common/window.rb +6 -6
- data/lib/selenium/webdriver/common/zipper.rb +1 -1
- data/lib/selenium/webdriver/common.rb +8 -3
- data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
- data/lib/selenium/webdriver/devtools/request.rb +0 -2
- data/lib/selenium/webdriver/devtools/response.rb +0 -2
- data/lib/selenium/webdriver/devtools.rb +12 -2
- data/lib/selenium/webdriver/edge/driver.rb +9 -3
- data/lib/selenium/webdriver/edge/features.rb +7 -4
- data/lib/selenium/webdriver/edge/options.rb +17 -5
- data/lib/selenium/webdriver/edge/profile.rb +2 -2
- data/lib/selenium/webdriver/edge/service.rb +8 -7
- data/lib/selenium/webdriver/edge.rb +0 -2
- data/lib/selenium/webdriver/firefox/driver.rb +8 -2
- data/lib/selenium/webdriver/firefox/features.rb +10 -3
- data/lib/selenium/webdriver/firefox/options.rb +4 -15
- data/lib/selenium/webdriver/firefox/profile.rb +7 -7
- data/lib/selenium/webdriver/firefox/service.rb +0 -18
- data/lib/selenium/webdriver/firefox.rb +0 -14
- data/lib/selenium/webdriver/ie/driver.rb +7 -1
- data/lib/selenium/webdriver/{common/driver_extensions/has_remote_status.rb → ie/features.rb} +10 -7
- data/lib/selenium/webdriver/ie/options.rb +4 -3
- data/lib/selenium/webdriver/ie/service.rb +0 -22
- data/lib/selenium/webdriver/ie.rb +4 -17
- data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +10 -4
- data/lib/selenium/webdriver/remote/bridge.rb +48 -39
- data/lib/selenium/webdriver/remote/capabilities.rb +3 -53
- data/lib/selenium/webdriver/remote/driver.rb +35 -14
- data/lib/selenium/webdriver/remote/features.rb +75 -0
- data/lib/selenium/webdriver/remote/http/common.rb +3 -3
- data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
- data/lib/selenium/webdriver/remote/http/default.rb +2 -2
- data/lib/selenium/webdriver/remote/response.rb +0 -1
- data/lib/selenium/webdriver/remote/server_error.rb +1 -1
- data/lib/selenium/webdriver/remote.rb +1 -1
- data/lib/selenium/webdriver/safari/driver.rb +7 -1
- data/lib/selenium/webdriver/safari/features.rb +5 -3
- data/lib/selenium/webdriver/safari/options.rb +5 -1
- data/lib/selenium/webdriver/safari/service.rb +10 -4
- data/lib/selenium/webdriver/safari.rb +1 -15
- data/lib/selenium/webdriver/support/color.rb +17 -17
- data/lib/selenium/webdriver/support/guards/guard.rb +6 -5
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +0 -2
- data/lib/selenium/webdriver/support/guards.rb +1 -1
- data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
- data/lib/selenium/webdriver/support/select.rb +3 -1
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +5 -4
- data/selenium-webdriver.gemspec +10 -11
- metadata +51 -90
- data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Firefox
|
|
23
23
|
module Features
|
|
24
|
-
|
|
25
24
|
FIREFOX_COMMANDS = {
|
|
26
25
|
get_context: [:get, 'session/:session_id/moz/context'],
|
|
27
26
|
set_context: [:post, 'session/:session_id/moz/context'],
|
|
@@ -30,12 +29,20 @@ module Selenium
|
|
|
30
29
|
full_page_screenshot: [:get, 'session/:session_id/moz/screenshot/full']
|
|
31
30
|
}.freeze
|
|
32
31
|
|
|
32
|
+
def command_list
|
|
33
|
+
FIREFOX_COMMANDS.merge(self.class::COMMANDS)
|
|
34
|
+
end
|
|
35
|
+
|
|
33
36
|
def commands(command)
|
|
34
|
-
|
|
37
|
+
command_list[command]
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
def install_addon(path, temporary)
|
|
38
|
-
addon = File.
|
|
41
|
+
addon = if File.directory?(path)
|
|
42
|
+
Zipper.zip(path)
|
|
43
|
+
else
|
|
44
|
+
File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
|
|
45
|
+
end
|
|
39
46
|
|
|
40
47
|
payload = {addon: addon}
|
|
41
48
|
payload[:temporary] = temporary unless temporary.nil?
|
|
@@ -45,7 +45,7 @@ module Selenium
|
|
|
45
45
|
#
|
|
46
46
|
# @example
|
|
47
47
|
# options = Selenium::WebDriver::Firefox::Options.new(args: ['--host=127.0.0.1'])
|
|
48
|
-
# driver = Selenium::WebDriver.for :firefox,
|
|
48
|
+
# driver = Selenium::WebDriver.for :firefox, options: options
|
|
49
49
|
#
|
|
50
50
|
# @param [Hash] opts the pre-defined options to create the Firefox::Options with
|
|
51
51
|
# @option opts [String] :binary Path to the Firefox executable to use
|
|
@@ -57,7 +57,8 @@ module Selenium
|
|
|
57
57
|
#
|
|
58
58
|
|
|
59
59
|
def initialize(log_level: nil, **opts)
|
|
60
|
-
@debugger_address = opts.delete(:debugger_address)
|
|
60
|
+
@debugger_address = opts.delete(:debugger_address) { true }
|
|
61
|
+
opts[:accept_insecure_certs] = true unless opts.key?(:accept_insecure_certs)
|
|
61
62
|
|
|
62
63
|
super(**opts)
|
|
63
64
|
|
|
@@ -98,18 +99,6 @@ module Selenium
|
|
|
98
99
|
@options[:prefs][name] = value
|
|
99
100
|
end
|
|
100
101
|
|
|
101
|
-
#
|
|
102
|
-
# Run Firefox in headless mode.
|
|
103
|
-
#
|
|
104
|
-
# @example Enable headless mode
|
|
105
|
-
# options = Selenium::WebDriver::Firefox::Options.new
|
|
106
|
-
# options.headless!
|
|
107
|
-
#
|
|
108
|
-
|
|
109
|
-
def headless!
|
|
110
|
-
add_argument '-headless'
|
|
111
|
-
end
|
|
112
|
-
|
|
113
102
|
#
|
|
114
103
|
# Sets Firefox profile.
|
|
115
104
|
#
|
|
@@ -177,7 +166,7 @@ module Selenium
|
|
|
177
166
|
end
|
|
178
167
|
|
|
179
168
|
def camelize?(key)
|
|
180
|
-
key !=
|
|
169
|
+
key != 'prefs'
|
|
181
170
|
end
|
|
182
171
|
end # Options
|
|
183
172
|
end # Firefox
|
|
@@ -26,11 +26,11 @@ module Selenium
|
|
|
26
26
|
VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String].freeze
|
|
27
27
|
|
|
28
28
|
DEFAULT_PREFERENCES = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
'browser.newtabpage.enabled' => false,
|
|
30
|
+
'browser.startup.homepage' => 'about:blank',
|
|
31
|
+
'browser.usedOnWindows10.introURL' => 'about:blank',
|
|
32
|
+
'network.captive-portal-service.enabled' => false,
|
|
33
|
+
'security.csp.enable' => false
|
|
34
34
|
}.freeze
|
|
35
35
|
|
|
36
36
|
attr_reader :name, :log_file
|
|
@@ -143,7 +143,7 @@ module Selenium
|
|
|
143
143
|
end
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
alias as_json encoded
|
|
147
147
|
|
|
148
148
|
private
|
|
149
149
|
|
|
@@ -160,7 +160,7 @@ module Selenium
|
|
|
160
160
|
destination = File.join(directory, 'extensions')
|
|
161
161
|
|
|
162
162
|
@extensions.each do |name, extension|
|
|
163
|
-
WebDriver.logger.debug({
|
|
163
|
+
WebDriver.logger.debug({extension: name}.inspect, id: :firefox_profile)
|
|
164
164
|
extension.write_to(destination)
|
|
165
165
|
end
|
|
166
166
|
end
|
|
@@ -23,25 +23,7 @@ module Selenium
|
|
|
23
23
|
class Service < WebDriver::Service
|
|
24
24
|
DEFAULT_PORT = 4444
|
|
25
25
|
EXECUTABLE = 'geckodriver'
|
|
26
|
-
MISSING_TEXT = <<~ERROR
|
|
27
|
-
Unable to find Mozilla geckodriver. Please download the server from
|
|
28
|
-
https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
|
|
29
|
-
More info at https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver.
|
|
30
|
-
ERROR
|
|
31
26
|
SHUTDOWN_SUPPORTED = false
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
# NOTE: This processing is deprecated
|
|
36
|
-
def extract_service_args(driver_opts)
|
|
37
|
-
driver_args = super
|
|
38
|
-
driver_opts = driver_opts.dup
|
|
39
|
-
driver_args << "--binary=#{driver_opts[:binary]}" if driver_opts.key?(:binary)
|
|
40
|
-
driver_args << "--log=#{driver_opts[:log]}" if driver_opts.key?(:log)
|
|
41
|
-
driver_args << "--marionette-port=#{driver_opts[:marionette_port]}" if driver_opts.key?(:marionette_port)
|
|
42
|
-
driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
|
|
43
|
-
driver_args
|
|
44
|
-
end
|
|
45
27
|
end # Service
|
|
46
28
|
end # Firefox
|
|
47
29
|
end # WebDriver
|
|
@@ -42,20 +42,6 @@ module Selenium
|
|
|
42
42
|
# until WebDriver Bidi is available.
|
|
43
43
|
DEVTOOLS_VERSION = 85
|
|
44
44
|
|
|
45
|
-
def self.driver_path=(path)
|
|
46
|
-
WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path=',
|
|
47
|
-
'Selenium::WebDriver::Firefox::Service#driver_path=',
|
|
48
|
-
id: :driver_path
|
|
49
|
-
Selenium::WebDriver::Firefox::Service.driver_path = path
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def self.driver_path
|
|
53
|
-
WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path',
|
|
54
|
-
'Selenium::WebDriver::Firefox::Service#driver_path',
|
|
55
|
-
id: :driver_path
|
|
56
|
-
Selenium::WebDriver::Firefox::Service.driver_path
|
|
57
|
-
end
|
|
58
|
-
|
|
59
45
|
def self.path=(path)
|
|
60
46
|
Platform.assert_executable path
|
|
61
47
|
@path = path
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module IE
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# Driver implementation for Internet Explorer supporting
|
|
26
25
|
# both OSS and W3C dialects of JSON wire protocol.
|
|
@@ -30,6 +29,13 @@ module Selenium
|
|
|
30
29
|
class Driver < WebDriver::Driver
|
|
31
30
|
EXTENSIONS = [DriverExtensions::HasWebStorage].freeze
|
|
32
31
|
|
|
32
|
+
include LocalDriver
|
|
33
|
+
|
|
34
|
+
def initialize(options: nil, service: nil, url: nil, **opts)
|
|
35
|
+
caps, url = initialize_local_driver(options, service, url)
|
|
36
|
+
super(caps: caps, url: url, **opts)
|
|
37
|
+
end
|
|
38
|
+
|
|
33
39
|
def browser
|
|
34
40
|
:internet_explorer
|
|
35
41
|
end
|
data/lib/selenium/webdriver/{common/driver_extensions/has_remote_status.rb → ie/features.rb}
RENAMED
|
@@ -19,13 +19,16 @@
|
|
|
19
19
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
|
-
module
|
|
23
|
-
module
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
@bridge.status
|
|
22
|
+
module IE
|
|
23
|
+
module Features
|
|
24
|
+
def command_list
|
|
25
|
+
self.class::COMMANDS
|
|
27
26
|
end
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
|
|
28
|
+
def commands(command)
|
|
29
|
+
command_list[command]
|
|
30
|
+
end
|
|
31
|
+
end # Bridge
|
|
32
|
+
end # Ie
|
|
30
33
|
end # WebDriver
|
|
31
34
|
end # Selenium
|
|
@@ -41,7 +41,8 @@ module Selenium
|
|
|
41
41
|
use_per_process_proxy: 'ie.usePerProcessProxy',
|
|
42
42
|
use_legacy_file_upload_dialog_handling: 'ie.useLegacyFileUploadDialogHandling',
|
|
43
43
|
attach_to_edge_chrome: 'ie.edgechromium',
|
|
44
|
-
edge_executable_path: 'ie.edgepath'
|
|
44
|
+
edge_executable_path: 'ie.edgepath',
|
|
45
|
+
ignore_process_match: 'ie.ignoreprocessmatch'
|
|
45
46
|
}.freeze
|
|
46
47
|
BROWSER = 'internet explorer'
|
|
47
48
|
|
|
@@ -52,12 +53,12 @@ module Selenium
|
|
|
52
53
|
#
|
|
53
54
|
# @example
|
|
54
55
|
# options = Selenium::WebDriver::IE::Options.new(args: ['--host=127.0.0.1'])
|
|
55
|
-
# driver = Selenium::WebDriver.for(:ie,
|
|
56
|
+
# driver = Selenium::WebDriver.for(:ie, options: options)
|
|
56
57
|
#
|
|
57
58
|
# @example
|
|
58
59
|
# options = Selenium::WebDriver::IE::Options.new
|
|
59
60
|
# options.element_scroll_behavior = Selenium::WebDriver::IE::Options::SCROLL_BOTTOM
|
|
60
|
-
# driver = Selenium::WebDriver.for(:ie,
|
|
61
|
+
# driver = Selenium::WebDriver.for(:ie, options: options)
|
|
61
62
|
#
|
|
62
63
|
# @param [Hash] opts the pre-defined options
|
|
63
64
|
# @option opts [Array<String>] args
|
|
@@ -23,29 +23,7 @@ module Selenium
|
|
|
23
23
|
class Service < WebDriver::Service
|
|
24
24
|
DEFAULT_PORT = 5555
|
|
25
25
|
EXECUTABLE = 'IEDriverServer'
|
|
26
|
-
MISSING_TEXT = <<~ERROR
|
|
27
|
-
Unable to find IEDriverServer. Please download the server from
|
|
28
|
-
https://www.selenium.dev/downloads/ and place it somewhere on your PATH.
|
|
29
|
-
More info at https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver.
|
|
30
|
-
ERROR
|
|
31
26
|
SHUTDOWN_SUPPORTED = true
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
# NOTE: This processing is deprecated
|
|
36
|
-
def extract_service_args(driver_opts)
|
|
37
|
-
driver_args = super
|
|
38
|
-
driver_opts = driver_opts.dup
|
|
39
|
-
driver_args << "--log-level=#{driver_opts[:log_level].to_s.upcase}" if driver_opts.key?(:log_level)
|
|
40
|
-
driver_args << "--log-file=#{driver_opts[:log_file]}" if driver_opts.key?(:log_file)
|
|
41
|
-
if driver_opts.key?(:implementation)
|
|
42
|
-
driver_args << "--implementation=#{driver_opts[:implementation].to_s.upcase}"
|
|
43
|
-
end
|
|
44
|
-
driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
|
|
45
|
-
driver_args << "--extract_path=#{driver_opts[:extract_path]}" if driver_opts.key?(:extract_path)
|
|
46
|
-
driver_args << "--silent" if driver_opts[:silent] == true
|
|
47
|
-
driver_args
|
|
48
|
-
end
|
|
49
27
|
end # Server
|
|
50
28
|
end # IE
|
|
51
29
|
end # WebDriver
|
|
@@ -20,23 +20,10 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module IE
|
|
23
|
-
autoload :
|
|
24
|
-
autoload :
|
|
25
|
-
autoload :
|
|
26
|
-
|
|
27
|
-
def self.driver_path=(path)
|
|
28
|
-
WebDriver.logger.deprecate 'Selenium::WebDriver::IE#driver_path=',
|
|
29
|
-
'Selenium::WebDriver::IE::Service#driver_path=',
|
|
30
|
-
id: :driver_path
|
|
31
|
-
Selenium::WebDriver::IE::Service.driver_path = path
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.driver_path
|
|
35
|
-
WebDriver.logger.deprecate 'Selenium::WebDriver::IE#driver_path',
|
|
36
|
-
'Selenium::WebDriver::IE::Service#driver_path',
|
|
37
|
-
id: :driver_path
|
|
38
|
-
Selenium::WebDriver::IE::Service.driver_path
|
|
39
|
-
end
|
|
23
|
+
autoload :Features, 'selenium/webdriver/ie/features'
|
|
24
|
+
autoload :Driver, 'selenium/webdriver/ie/driver'
|
|
25
|
+
autoload :Options, 'selenium/webdriver/ie/options'
|
|
26
|
+
autoload :Service, 'selenium/webdriver/ie/service'
|
|
40
27
|
end # IE
|
|
41
28
|
end # WebDriver
|
|
42
29
|
end # Selenium
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# https://w3c.github.io/webdriver/#endpoints
|
|
26
25
|
# @api private
|
|
@@ -146,12 +145,19 @@ module Selenium
|
|
|
146
145
|
take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
|
|
147
146
|
|
|
148
147
|
#
|
|
149
|
-
#
|
|
148
|
+
# virtual-authenticator
|
|
150
149
|
#
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
add_virtual_authenticator: [:post, 'session/:session_id/webauthn/authenticator'],
|
|
152
|
+
remove_virtual_authenticator: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId'],
|
|
153
|
+
add_credential: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/credential'],
|
|
154
|
+
get_credentials: [:get, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
|
|
155
|
+
remove_credential: [:delete,
|
|
156
|
+
'session/:session_id/webauthn/authenticator/:authenticatorId/credentials/:credentialId'],
|
|
157
|
+
remove_all_credentials: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
|
|
158
|
+
set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv']
|
|
154
159
|
|
|
160
|
+
}.freeze
|
|
155
161
|
end # Bridge
|
|
156
162
|
end # Remote
|
|
157
163
|
end # WebDriver
|
|
@@ -21,6 +21,7 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
23
|
class Bridge
|
|
24
|
+
autoload :COMMANDS, 'selenium/webdriver/remote/bridge/commands'
|
|
24
25
|
include Atoms
|
|
25
26
|
|
|
26
27
|
PORT = 4444
|
|
@@ -186,6 +187,7 @@ module Selenium
|
|
|
186
187
|
execute :delete_session
|
|
187
188
|
http.close
|
|
188
189
|
rescue *QUIT_ERRORS
|
|
190
|
+
nil
|
|
189
191
|
end
|
|
190
192
|
|
|
191
193
|
def close
|
|
@@ -367,18 +369,10 @@ module Selenium
|
|
|
367
369
|
# actions
|
|
368
370
|
#
|
|
369
371
|
|
|
370
|
-
def action(
|
|
371
|
-
ActionBuilder.new self,
|
|
372
|
-
end
|
|
373
|
-
alias_method :actions, :action
|
|
374
|
-
|
|
375
|
-
def mouse
|
|
376
|
-
raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead'
|
|
377
|
-
end
|
|
378
|
-
|
|
379
|
-
def keyboard
|
|
380
|
-
raise Error::UnsupportedOperationError, '#keyboard is no longer supported, use #action instead'
|
|
372
|
+
def action(async: false, devices: [], duration: 250)
|
|
373
|
+
ActionBuilder.new self, async: async, devices: devices, duration: duration
|
|
381
374
|
end
|
|
375
|
+
alias actions action
|
|
382
376
|
|
|
383
377
|
def send_actions(data)
|
|
384
378
|
execute :actions, {}, {actions: data}
|
|
@@ -397,37 +391,19 @@ module Selenium
|
|
|
397
391
|
end
|
|
398
392
|
|
|
399
393
|
def send_keys_to_element(element, keys)
|
|
400
|
-
|
|
401
|
-
if @file_detector
|
|
402
|
-
local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
|
|
403
|
-
if local_files.any?
|
|
404
|
-
keys = local_files.map { |local_file| upload(local_file) }
|
|
405
|
-
keys = Array(keys.join("\n"))
|
|
406
|
-
end
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
# Keep .split(//) for backward compatibility for now
|
|
394
|
+
keys = upload_if_necessary(keys) if @file_detector
|
|
410
395
|
text = keys.join
|
|
411
396
|
execute :element_send_keys, {id: element}, {value: text.chars, text: text}
|
|
412
397
|
end
|
|
413
398
|
|
|
414
|
-
def upload(local_file)
|
|
415
|
-
unless File.file?(local_file)
|
|
416
|
-
WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
|
|
417
|
-
raise Error::WebDriverError, "You are trying to work with something that isn't a file."
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
|
|
421
|
-
end
|
|
422
|
-
|
|
423
399
|
def clear_element(element)
|
|
424
400
|
execute :element_clear, id: element
|
|
425
401
|
end
|
|
426
402
|
|
|
427
403
|
def submit_element(element)
|
|
428
|
-
script = "var form = arguments[0];\n" \
|
|
429
|
-
"while (form.nodeName != \"FORM\" && form.parentNode) {\n" \
|
|
430
|
-
"
|
|
404
|
+
script = "/* submitForm */ var form = arguments[0];\n" \
|
|
405
|
+
"while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
|
|
406
|
+
"form = form.parentNode;\n" \
|
|
431
407
|
"}\n" \
|
|
432
408
|
"if (!form) { throw Error('Unable to find containing form element'); }\n" \
|
|
433
409
|
"if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" \
|
|
@@ -437,7 +413,7 @@ module Selenium
|
|
|
437
413
|
|
|
438
414
|
execute_script(script, Element::ELEMENT_KEY => element)
|
|
439
415
|
rescue Error::JavascriptError
|
|
440
|
-
raise Error::UnsupportedOperationError,
|
|
416
|
+
raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
|
|
441
417
|
end
|
|
442
418
|
|
|
443
419
|
#
|
|
@@ -449,7 +425,7 @@ module Selenium
|
|
|
449
425
|
end
|
|
450
426
|
|
|
451
427
|
def element_attribute(element, name)
|
|
452
|
-
WebDriver.logger.
|
|
428
|
+
WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
|
|
453
429
|
execute_atom :getAttribute, element, name
|
|
454
430
|
end
|
|
455
431
|
|
|
@@ -509,7 +485,7 @@ module Selenium
|
|
|
509
485
|
end
|
|
510
486
|
|
|
511
487
|
def element_displayed?(element)
|
|
512
|
-
WebDriver.logger.
|
|
488
|
+
WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
|
|
513
489
|
execute_atom :isDisplayed, element
|
|
514
490
|
end
|
|
515
491
|
|
|
@@ -525,7 +501,7 @@ module Selenium
|
|
|
525
501
|
Element.new self, element_id_from(execute(:get_active_element))
|
|
526
502
|
end
|
|
527
503
|
|
|
528
|
-
|
|
504
|
+
alias switch_to_active_element active_element
|
|
529
505
|
|
|
530
506
|
def find_element_by(how, what, parent_ref = [])
|
|
531
507
|
how, what = convert_locator(how, what)
|
|
@@ -568,6 +544,39 @@ module Selenium
|
|
|
568
544
|
ShadowRoot.new self, shadow_root_id_from(id)
|
|
569
545
|
end
|
|
570
546
|
|
|
547
|
+
#
|
|
548
|
+
# virtual-authenticator
|
|
549
|
+
#
|
|
550
|
+
|
|
551
|
+
def add_virtual_authenticator(options)
|
|
552
|
+
authenticator_id = execute :add_virtual_authenticator, {}, options.as_json
|
|
553
|
+
VirtualAuthenticator.new(self, authenticator_id, options)
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def remove_virtual_authenticator(id)
|
|
557
|
+
execute :remove_virtual_authenticator, {authenticatorId: id}
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
def add_credential(credential, id)
|
|
561
|
+
execute :add_credential, {authenticatorId: id}, credential
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def credentials(authenticator_id)
|
|
565
|
+
execute :get_credentials, {authenticatorId: authenticator_id}
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def remove_credential(credential_id, authenticator_id)
|
|
569
|
+
execute :remove_credential, {credentialId: credential_id, authenticatorId: authenticator_id}
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def remove_all_credentials(authenticator_id)
|
|
573
|
+
execute :remove_all_credentials, {authenticatorId: authenticator_id}
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
def user_verified(verified, authenticator_id)
|
|
577
|
+
execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
|
|
578
|
+
end
|
|
579
|
+
|
|
571
580
|
private
|
|
572
581
|
|
|
573
582
|
#
|
|
@@ -588,7 +597,7 @@ module Selenium
|
|
|
588
597
|
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
|
589
598
|
end
|
|
590
599
|
|
|
591
|
-
WebDriver.logger.
|
|
600
|
+
WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
|
|
592
601
|
http.call(verb, path, command_hash)['value']
|
|
593
602
|
end
|
|
594
603
|
|
|
@@ -655,7 +664,7 @@ module Selenium
|
|
|
655
664
|
[how, what]
|
|
656
665
|
end
|
|
657
666
|
|
|
658
|
-
ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])
|
|
667
|
+
ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
|
|
659
668
|
UNICODE_CODE_POINT = 30
|
|
660
669
|
|
|
661
670
|
# Escapes invalid characters in CSS selector.
|
|
@@ -20,14 +20,12 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# Specification of the desired and/or actual capabilities of the browser that the
|
|
26
25
|
# server is being asked to create.
|
|
27
26
|
#
|
|
28
27
|
|
|
29
28
|
class Capabilities
|
|
30
|
-
|
|
31
29
|
KNOWN = [
|
|
32
30
|
:browser_name,
|
|
33
31
|
:browser_version,
|
|
@@ -55,60 +53,11 @@ module Selenium
|
|
|
55
53
|
end
|
|
56
54
|
end
|
|
57
55
|
|
|
58
|
-
#
|
|
59
|
-
# Backward compatibility
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
alias_method :version, :browser_version
|
|
63
|
-
alias_method :version=, :browser_version=
|
|
64
|
-
alias_method :platform, :platform_name
|
|
65
|
-
alias_method :platform=, :platform_name=
|
|
66
|
-
|
|
67
56
|
#
|
|
68
57
|
# Convenience methods for the common choices.
|
|
69
58
|
#
|
|
70
59
|
|
|
71
60
|
class << self
|
|
72
|
-
def chrome(opts = {})
|
|
73
|
-
new({
|
|
74
|
-
browser_name: 'chrome'
|
|
75
|
-
}.merge(opts))
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def edge(opts = {})
|
|
79
|
-
new({
|
|
80
|
-
browser_name: 'MicrosoftEdge'
|
|
81
|
-
}.merge(opts))
|
|
82
|
-
end
|
|
83
|
-
alias_method :microsoftedge, :edge
|
|
84
|
-
|
|
85
|
-
def firefox(opts = {})
|
|
86
|
-
new({
|
|
87
|
-
browser_name: 'firefox'
|
|
88
|
-
}.merge(opts))
|
|
89
|
-
end
|
|
90
|
-
alias_method :ff, :firefox
|
|
91
|
-
|
|
92
|
-
def safari(opts = {})
|
|
93
|
-
new({
|
|
94
|
-
browser_name: Selenium::WebDriver::Safari.technology_preview? ? "Safari Technology Preview" : 'safari'
|
|
95
|
-
}.merge(opts))
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def htmlunit(opts = {})
|
|
99
|
-
new({
|
|
100
|
-
browser_name: 'htmlunit'
|
|
101
|
-
}.merge(opts))
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def internet_explorer(opts = {})
|
|
105
|
-
new({
|
|
106
|
-
browser_name: 'internet explorer',
|
|
107
|
-
platform_name: :windows
|
|
108
|
-
}.merge(opts))
|
|
109
|
-
end
|
|
110
|
-
alias_method :ie, :internet_explorer
|
|
111
|
-
|
|
112
61
|
def always_match(capabilities)
|
|
113
62
|
new(always_match: capabilities)
|
|
114
63
|
end
|
|
@@ -134,7 +83,8 @@ module Selenium
|
|
|
134
83
|
|
|
135
84
|
# Remote Server Specific
|
|
136
85
|
if data.key?('webdriver.remote.sessionid')
|
|
137
|
-
caps[:remote_session_id] =
|
|
86
|
+
caps[:remote_session_id] =
|
|
87
|
+
data.delete('webdriver.remote.sessionid')
|
|
138
88
|
end
|
|
139
89
|
|
|
140
90
|
KNOWN.each do |cap|
|
|
@@ -269,7 +219,7 @@ module Selenium
|
|
|
269
219
|
as_json == other.as_json
|
|
270
220
|
end
|
|
271
221
|
|
|
272
|
-
|
|
222
|
+
alias eql? ==
|
|
273
223
|
|
|
274
224
|
protected
|
|
275
225
|
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# Driver implementation for remote server.
|
|
26
25
|
# @api private
|
|
@@ -29,20 +28,18 @@ module Selenium
|
|
|
29
28
|
class Driver < WebDriver::Driver
|
|
30
29
|
include DriverExtensions::UploadsFiles
|
|
31
30
|
include DriverExtensions::HasSessionId
|
|
32
|
-
include DriverExtensions::
|
|
31
|
+
include DriverExtensions::HasFileDownloads
|
|
33
32
|
|
|
34
|
-
def initialize(
|
|
35
|
-
|
|
36
|
-
if desired_capabilities.is_a?(Symbol)
|
|
37
|
-
unless Remote::Capabilities.respond_to?(desired_capabilities)
|
|
38
|
-
raise Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
|
|
39
|
-
end
|
|
33
|
+
def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
|
|
34
|
+
raise ArgumentError, "Can not set :service object on #{self.class}" if service
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
super
|
|
36
|
+
url ||= "http://#{Platform.localhost}:4444/wd/hub"
|
|
37
|
+
caps = process_options(options, capabilities)
|
|
38
|
+
super(caps: caps, url: url, **opts)
|
|
45
39
|
@bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
|
|
40
|
+
command_list = @bridge.command_list
|
|
41
|
+
@bridge.extend(WebDriver::Remote::Features)
|
|
42
|
+
@bridge.add_commands(command_list)
|
|
46
43
|
end
|
|
47
44
|
|
|
48
45
|
private
|
|
@@ -52,8 +49,32 @@ module Selenium
|
|
|
52
49
|
end
|
|
53
50
|
|
|
54
51
|
def devtools_version
|
|
55
|
-
capabilities['se:cdpVersion']&.split('.')&.first
|
|
56
|
-
|
|
52
|
+
cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
|
|
53
|
+
raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
|
|
54
|
+
|
|
55
|
+
Integer(cdp_version)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def process_options(options, capabilities)
|
|
59
|
+
if options && capabilities
|
|
60
|
+
msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
|
|
61
|
+
raise ArgumentError, msg
|
|
62
|
+
elsif options.nil? && capabilities.nil?
|
|
63
|
+
raise ArgumentError, "#{self.class} needs :options to be set"
|
|
64
|
+
end
|
|
65
|
+
options ? options.as_json : generate_capabilities(capabilities)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def generate_capabilities(capabilities)
|
|
69
|
+
Array(capabilities).map { |cap|
|
|
70
|
+
if cap.is_a? Symbol
|
|
71
|
+
cap = WebDriver::Options.send(cap)
|
|
72
|
+
elsif !cap.respond_to? :as_json
|
|
73
|
+
msg = ":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not"
|
|
74
|
+
raise ArgumentError, msg
|
|
75
|
+
end
|
|
76
|
+
cap.as_json
|
|
77
|
+
}.inject(:merge)
|
|
57
78
|
end
|
|
58
79
|
end # Driver
|
|
59
80
|
end # Remote
|