selenium-webdriver 4.1.0 → 4.28.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 +446 -1
- data/Gemfile +4 -0
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +3 -3
- 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 +41 -43
- data/lib/selenium/webdriver/atoms/findElements.js +52 -50
- data/lib/selenium/webdriver/atoms/getAttribute.js +6 -100
- data/lib/selenium/webdriver/atoms/isDisplayed.js +24 -96
- 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 +100 -0
- 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_handler.rb +65 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +147 -0
- data/lib/selenium/webdriver/bidi/network.rb +82 -0
- data/lib/selenium/webdriver/bidi/session.rb +51 -0
- data/lib/selenium/webdriver/bidi/struct.rb +42 -0
- data/lib/selenium/webdriver/bidi.rb +67 -0
- data/lib/selenium/webdriver/chrome/driver.rb +9 -29
- data/lib/selenium/webdriver/chrome/features.rb +9 -67
- 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 +5 -19
- data/lib/selenium/webdriver/chrome.rb +0 -16
- data/lib/selenium/webdriver/chromium/driver.rb +61 -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 +60 -22
- data/lib/selenium/webdriver/common/child_process.rb +136 -0
- data/lib/selenium/webdriver/common/driver.rb +54 -89
- 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_remote_status.rb → has_bidi.rb} +10 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
- 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_fedcm_dialog.rb +55 -0
- 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 +9 -3
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +8 -68
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
- data/lib/selenium/webdriver/common/driver_finder.rb +97 -0
- data/lib/selenium/webdriver/common/element.rb +8 -8
- data/lib/selenium/webdriver/common/error.rb +29 -4
- data/lib/selenium/webdriver/common/fedcm/account.rb +49 -0
- data/lib/selenium/webdriver/common/fedcm/dialog.rb +74 -0
- data/lib/selenium/webdriver/common/fedcm.rb +27 -0
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
- data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
- data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
- data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
- data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
- data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
- data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -71
- data/lib/selenium/webdriver/common/{driver_extensions/has_network_connection.rb → interactions/pointer_cancel.rb} +19 -11
- data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
- data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
- data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
- data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
- data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
- data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +114 -0
- data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
- data/lib/selenium/webdriver/common/keys.rb +1 -0
- data/lib/selenium/webdriver/common/local_driver.rb +53 -0
- data/lib/selenium/webdriver/common/logger.rb +93 -28
- data/lib/selenium/webdriver/common/manager.rb +2 -29
- data/lib/selenium/webdriver/common/network.rb +64 -0
- data/lib/selenium/webdriver/common/options.rb +19 -19
- data/lib/selenium/webdriver/common/platform.rb +12 -52
- 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 +4 -4
- data/lib/selenium/webdriver/common/script.rb +45 -0
- data/lib/selenium/webdriver/common/search_context.rb +10 -8
- data/lib/selenium/webdriver/common/selenium_manager.rb +104 -0
- data/lib/selenium/webdriver/common/service.rb +24 -26
- data/lib/selenium/webdriver/common/service_manager.rb +9 -15
- data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
- data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
- data/lib/selenium/webdriver/common/socket_poller.rb +3 -3
- data/lib/selenium/webdriver/common/takes_screenshot.rb +6 -5
- data/lib/selenium/webdriver/common/target_locator.rb +5 -5
- 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/wait.rb +1 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +176 -0
- data/lib/selenium/webdriver/common/window.rb +6 -6
- data/lib/selenium/webdriver/common/zipper.rb +1 -1
- data/lib/selenium/webdriver/common.rb +27 -5
- 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 +1 -3
- data/lib/selenium/webdriver/devtools/response.rb +1 -3
- data/lib/selenium/webdriver/devtools.rb +17 -114
- data/lib/selenium/webdriver/edge/driver.rb +9 -3
- data/lib/selenium/webdriver/edge/features.rb +8 -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 +9 -2
- data/lib/selenium/webdriver/firefox/features.rb +11 -7
- data/lib/selenium/webdriver/firefox/options.rb +10 -16
- data/lib/selenium/webdriver/firefox/profile.rb +21 -17
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +1 -1
- data/lib/selenium/webdriver/firefox/service.rb +1 -18
- data/lib/selenium/webdriver/firefox/util.rb +46 -0
- data/lib/selenium/webdriver/firefox.rb +1 -14
- data/lib/selenium/webdriver/ie/driver.rb +7 -1
- data/lib/selenium/webdriver/ie/features.rb +34 -0
- data/lib/selenium/webdriver/ie/options.rb +6 -4
- data/lib/selenium/webdriver/ie/service.rb +1 -22
- data/lib/selenium/webdriver/ie.rb +4 -17
- data/lib/selenium/webdriver/remote/bidi_bridge.rb +66 -0
- data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +22 -9
- data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
- data/lib/selenium/webdriver/remote/bridge.rb +158 -100
- data/lib/selenium/webdriver/remote/capabilities.rb +5 -55
- 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 +26 -6
- data/lib/selenium/webdriver/remote/http/curb.rb +10 -6
- data/lib/selenium/webdriver/remote/http/default.rb +8 -14
- data/lib/selenium/webdriver/remote/response.rb +14 -22
- data/lib/selenium/webdriver/remote/server_error.rb +2 -2
- data/lib/selenium/webdriver/remote.rb +3 -2
- 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 +22 -22
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +14 -14
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
- data/lib/selenium/webdriver/support/guards.rb +4 -4
- 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 +7 -5
- data/selenium-webdriver.gemspec +22 -16
- metadata +137 -47
- 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
@@ -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
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module Remote
|
23
|
+
module Features
|
24
|
+
REMOTE_COMMANDS = {
|
25
|
+
upload_file: [:post, 'session/:session_id/se/file'],
|
26
|
+
get_downloadable_files: [:get, 'session/:session_id/se/files'],
|
27
|
+
download_file: [:post, 'session/:session_id/se/files'],
|
28
|
+
delete_downloadable_files: [:delete, 'session/:session_id/se/files']
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
def add_commands(commands)
|
32
|
+
@command_list = command_list.merge(commands)
|
33
|
+
end
|
34
|
+
|
35
|
+
def command_list
|
36
|
+
@command_list ||= REMOTE_COMMANDS
|
37
|
+
end
|
38
|
+
|
39
|
+
def commands(command)
|
40
|
+
command_list[command]
|
41
|
+
end
|
42
|
+
|
43
|
+
def upload(local_file)
|
44
|
+
unless File.file?(local_file)
|
45
|
+
WebDriver.logger.error("File detector only works with files. #{local_file.inspect} isn`t a file!",
|
46
|
+
id: :file_detector)
|
47
|
+
raise Error::WebDriverError, "You are trying to upload something that isn't a file."
|
48
|
+
end
|
49
|
+
|
50
|
+
execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
|
51
|
+
end
|
52
|
+
|
53
|
+
def upload_if_necessary(keys)
|
54
|
+
local_files = keys.first&.split("\n")&.filter_map { |key| @file_detector.call(Array(key)) }
|
55
|
+
return keys unless local_files&.any?
|
56
|
+
|
57
|
+
keys = local_files.map { |local_file| upload(local_file) }
|
58
|
+
Array(keys.join("\n"))
|
59
|
+
end
|
60
|
+
|
61
|
+
def downloadable_files
|
62
|
+
execute :get_downloadable_files
|
63
|
+
end
|
64
|
+
|
65
|
+
def download_file(name)
|
66
|
+
execute :download_file, {}, {name: name}
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete_downloadable_files
|
70
|
+
execute :delete_downloadable_files
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end # Remote
|
74
|
+
end # WebDriver
|
75
|
+
end # Selenium
|
@@ -26,10 +26,18 @@ module Selenium
|
|
26
26
|
CONTENT_TYPE = 'application/json'
|
27
27
|
DEFAULT_HEADERS = {
|
28
28
|
'Accept' => CONTENT_TYPE,
|
29
|
-
'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8"
|
30
|
-
'User-Agent' => "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
|
29
|
+
'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8"
|
31
30
|
}.freeze
|
32
31
|
|
32
|
+
class << self
|
33
|
+
attr_accessor :extra_headers
|
34
|
+
attr_writer :user_agent
|
35
|
+
|
36
|
+
def user_agent
|
37
|
+
@user_agent ||= "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
33
41
|
attr_writer :server_url
|
34
42
|
|
35
43
|
def quit_errors
|
@@ -40,17 +48,18 @@ module Selenium
|
|
40
48
|
# hook for subclasses - will be called on Driver#quit
|
41
49
|
end
|
42
50
|
|
51
|
+
# steep:ignore:start
|
43
52
|
def call(verb, url, command_hash)
|
44
53
|
url = server_url.merge(url) unless url.is_a?(URI)
|
45
|
-
headers =
|
54
|
+
headers = common_headers.dup
|
46
55
|
headers['Cache-Control'] = 'no-cache' if verb == :get
|
47
56
|
|
48
57
|
if command_hash
|
49
58
|
payload = JSON.generate(command_hash)
|
50
59
|
headers['Content-Length'] = payload.bytesize.to_s if %i[post put].include?(verb)
|
51
60
|
|
52
|
-
WebDriver.logger.
|
53
|
-
WebDriver.logger.debug(" > #{headers.inspect}")
|
61
|
+
WebDriver.logger.debug(" >>> #{url} | #{payload}", id: :command)
|
62
|
+
WebDriver.logger.debug(" > #{headers.inspect}", id: :header)
|
54
63
|
elsif verb == :post
|
55
64
|
payload = '{}'
|
56
65
|
headers['Content-Length'] = '2'
|
@@ -58,9 +67,20 @@ module Selenium
|
|
58
67
|
|
59
68
|
request verb, url, headers, payload
|
60
69
|
end
|
70
|
+
# steep:ignore:end
|
61
71
|
|
62
72
|
private
|
63
73
|
|
74
|
+
def common_headers
|
75
|
+
@common_headers ||= begin
|
76
|
+
headers = DEFAULT_HEADERS.dup
|
77
|
+
headers['User-Agent'] = Common.user_agent
|
78
|
+
headers = headers.merge(Common.extra_headers || {})
|
79
|
+
|
80
|
+
headers
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
64
84
|
def server_url
|
65
85
|
return @server_url if @server_url
|
66
86
|
|
@@ -75,7 +95,7 @@ module Selenium
|
|
75
95
|
code = code.to_i
|
76
96
|
body = body.to_s.strip
|
77
97
|
content_type = content_type.to_s
|
78
|
-
WebDriver.logger.
|
98
|
+
WebDriver.logger.debug("<- #{body}", id: :command)
|
79
99
|
|
80
100
|
if content_type.include? CONTENT_TYPE
|
81
101
|
raise Error::WebDriverError, "empty body: #{content_type.inspect} (#{code})\n#{body}" if body.empty?
|
@@ -22,7 +22,6 @@ require 'curb'
|
|
22
22
|
module Selenium
|
23
23
|
module WebDriver
|
24
24
|
module Remote
|
25
|
-
|
26
25
|
module Http
|
27
26
|
#
|
28
27
|
# An alternative to the default Net::HTTP client.
|
@@ -38,6 +37,12 @@ module Selenium
|
|
38
37
|
#
|
39
38
|
|
40
39
|
class Curb < Common
|
40
|
+
attr_accessor :timeout
|
41
|
+
|
42
|
+
def initialize(timeout: nil)
|
43
|
+
@timeout = timeout
|
44
|
+
super()
|
45
|
+
end
|
41
46
|
|
42
47
|
def quit_errors
|
43
48
|
[Curl::Err::RecvError] + super
|
@@ -55,7 +60,7 @@ module Selenium
|
|
55
60
|
client.headers = headers
|
56
61
|
|
57
62
|
# http://github.com/taf2/curb/issues/issue/33
|
58
|
-
client.head
|
63
|
+
client.head = false
|
59
64
|
client.delete = false
|
60
65
|
|
61
66
|
case verb
|
@@ -82,11 +87,10 @@ module Selenium
|
|
82
87
|
@client ||= begin
|
83
88
|
c = Curl::Easy.new
|
84
89
|
|
85
|
-
c.max_redirects
|
90
|
+
c.max_redirects = MAX_REDIRECTS
|
86
91
|
c.follow_location = true
|
87
|
-
c.timeout
|
88
|
-
c.verbose
|
89
|
-
|
92
|
+
c.timeout = timeout if timeout
|
93
|
+
c.verbose = WebDriver.logger.debug?
|
90
94
|
c
|
91
95
|
end
|
92
96
|
end
|
@@ -16,8 +16,6 @@
|
|
16
16
|
# KIND, either express or implied. See the License for the
|
17
17
|
# specific language governing permissions and limitations
|
18
18
|
# under the License.
|
19
|
-
|
20
|
-
require 'net/https'
|
21
19
|
require 'ipaddr'
|
22
20
|
|
23
21
|
module Selenium
|
@@ -75,9 +73,10 @@ module Selenium
|
|
75
73
|
begin
|
76
74
|
request = new_request_for(verb, url, headers, payload)
|
77
75
|
response = response_for(request)
|
78
|
-
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE
|
79
|
-
# a retry is sometimes needed
|
80
|
-
# run out of ephemeral ports
|
76
|
+
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE, Errno::EADDRNOTAVAIL
|
77
|
+
# a retry is sometimes needed:
|
78
|
+
# on Windows XP where we may quickly run out of ephemeral ports
|
79
|
+
# when the port becomes temporarily unavailable
|
81
80
|
#
|
82
81
|
# A more robust solution is bumping the MaxUserPort setting
|
83
82
|
# as described here:
|
@@ -85,13 +84,6 @@ module Selenium
|
|
85
84
|
# http://msdn.microsoft.com/en-us/library/aa560610%28v=bts.20%29.aspx
|
86
85
|
raise if retries >= MAX_RETRIES
|
87
86
|
|
88
|
-
retries += 1
|
89
|
-
sleep 2
|
90
|
-
retry
|
91
|
-
rescue Errno::EADDRNOTAVAIL => e
|
92
|
-
# a retry is sometimes needed when the port becomes temporarily unavailable
|
93
|
-
raise if retries >= MAX_RETRIES
|
94
|
-
|
95
87
|
retries += 1
|
96
88
|
sleep 2
|
97
89
|
retry
|
@@ -102,10 +94,12 @@ module Selenium
|
|
102
94
|
end
|
103
95
|
|
104
96
|
if response.is_a? Net::HTTPRedirection
|
97
|
+
WebDriver.logger.debug("Redirect to #{response['Location']}; times: #{redirects}")
|
105
98
|
raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
|
106
99
|
|
107
100
|
request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
|
108
101
|
else
|
102
|
+
WebDriver.logger.debug(" <<< #{response.instance_variable_get(:@header).inspect}", id: :header)
|
109
103
|
create_response response.code, response.body, response.content_type
|
110
104
|
end
|
111
105
|
end
|
@@ -142,8 +136,8 @@ module Selenium
|
|
142
136
|
|
143
137
|
def proxy
|
144
138
|
@proxy ||= begin
|
145
|
-
proxy = ENV
|
146
|
-
no_proxy = ENV
|
139
|
+
proxy = ENV.fetch('http_proxy', nil) || ENV.fetch('HTTP_PROXY', nil)
|
140
|
+
no_proxy = ENV.fetch('no_proxy', nil) || ENV.fetch('NO_PROXY', nil)
|
147
141
|
|
148
142
|
if proxy
|
149
143
|
proxy = "http://#{proxy}" unless proxy.start_with?('http://')
|
@@ -20,7 +20,6 @@
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
22
|
module Remote
|
23
|
-
|
24
23
|
#
|
25
24
|
# @api private
|
26
25
|
#
|
@@ -29,7 +28,7 @@ module Selenium
|
|
29
28
|
attr_reader :code, :payload
|
30
29
|
|
31
30
|
def initialize(code, payload = nil)
|
32
|
-
@code
|
31
|
+
@code = code
|
33
32
|
@payload = payload || {}
|
34
33
|
|
35
34
|
assert_ok
|
@@ -38,11 +37,8 @@ module Selenium
|
|
38
37
|
def error
|
39
38
|
error, message, backtrace = process_error
|
40
39
|
klass = Error.for_error(error) || return
|
41
|
-
|
42
40
|
ex = klass.new(message)
|
43
|
-
ex
|
44
|
-
add_backtrace ex, backtrace
|
45
|
-
|
41
|
+
add_cause(ex, error, backtrace)
|
46
42
|
ex
|
47
43
|
end
|
48
44
|
|
@@ -60,34 +56,30 @@ module Selenium
|
|
60
56
|
raise Error::ServerError, self
|
61
57
|
end
|
62
58
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
backtrace
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
server_trace.split("\n")
|
71
|
-
end
|
72
|
-
|
73
|
-
ex.set_backtrace(backtrace + ex.backtrace)
|
59
|
+
def add_cause(ex, error, backtrace)
|
60
|
+
cause = Error::WebDriverError.new
|
61
|
+
backtrace = backtrace_from_remote(backtrace) if backtrace.is_a?(Array)
|
62
|
+
cause.set_backtrace(backtrace)
|
63
|
+
raise ex, cause: cause
|
64
|
+
rescue Error.for_error(error)
|
65
|
+
ex
|
74
66
|
end
|
75
67
|
|
76
68
|
def backtrace_from_remote(server_trace)
|
77
|
-
server_trace.
|
69
|
+
server_trace.filter_map do |frame|
|
78
70
|
next unless frame.is_a?(Hash)
|
79
71
|
|
80
72
|
file = frame['fileName']
|
81
73
|
line = frame['lineNumber']
|
82
|
-
|
74
|
+
method = frame['methodName']
|
83
75
|
|
84
76
|
class_name = frame['className']
|
85
77
|
file = "#{class_name}(#{file})" if class_name
|
86
78
|
|
87
|
-
|
79
|
+
method = 'unknown' if method.nil? || method.empty?
|
88
80
|
|
89
|
-
"[remote server] #{file}:#{line}:in `#{
|
90
|
-
|
81
|
+
"[remote server] #{file}:#{line}:in `#{method}'"
|
82
|
+
end
|
91
83
|
end
|
92
84
|
|
93
85
|
def process_error
|
@@ -23,9 +23,9 @@ module Selenium
|
|
23
23
|
class ServerError < StandardError
|
24
24
|
def initialize(response)
|
25
25
|
if response.is_a? String
|
26
|
-
super
|
26
|
+
super
|
27
27
|
else
|
28
|
-
super("status code #{response.code}")
|
28
|
+
super("status code #{response.code}; payload #{response.payload}")
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end # ServerError
|
@@ -23,14 +23,15 @@ require 'selenium/webdriver/remote/server_error'
|
|
23
23
|
module Selenium
|
24
24
|
module WebDriver
|
25
25
|
module Remote
|
26
|
+
autoload :Features, 'selenium/webdriver/remote/features'
|
26
27
|
autoload :Bridge, 'selenium/webdriver/remote/bridge'
|
28
|
+
autoload :BiDiBridge, 'selenium/webdriver/remote/bidi_bridge'
|
27
29
|
autoload :Driver, 'selenium/webdriver/remote/driver'
|
28
30
|
autoload :Response, 'selenium/webdriver/remote/response'
|
29
31
|
autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
|
30
|
-
autoload :COMMANDS, 'selenium/webdriver/remote/commands'
|
31
32
|
|
32
33
|
module Http
|
33
|
-
autoload :Common,
|
34
|
+
autoload :Common, 'selenium/webdriver/remote/http/common'
|
34
35
|
autoload :Default, 'selenium/webdriver/remote/http/default'
|
35
36
|
end
|
36
37
|
end
|
@@ -20,7 +20,6 @@
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
22
|
module Safari
|
23
|
-
|
24
23
|
#
|
25
24
|
# Driver implementation for Safari.
|
26
25
|
# @api private
|
@@ -31,6 +30,13 @@ module Selenium
|
|
31
30
|
DriverExtensions::HasApplePermissions,
|
32
31
|
DriverExtensions::HasWebStorage].freeze
|
33
32
|
|
33
|
+
include LocalDriver
|
34
|
+
|
35
|
+
def initialize(options: nil, service: nil, url: nil, **opts)
|
36
|
+
caps, url = initialize_local_driver(options, service, url)
|
37
|
+
super(caps: caps, url: url, **opts)
|
38
|
+
end
|
39
|
+
|
34
40
|
def browser
|
35
41
|
:safari
|
36
42
|
end
|
@@ -21,7 +21,6 @@ module Selenium
|
|
21
21
|
module WebDriver
|
22
22
|
module Safari
|
23
23
|
module Features
|
24
|
-
|
25
24
|
# https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/WebDriverEndpointDoc/Commands/Commands.html
|
26
25
|
SAFARI_COMMANDS = {
|
27
26
|
get_permissions: [:get, 'session/:session_id/apple/permissions'],
|
@@ -29,8 +28,12 @@ module Selenium
|
|
29
28
|
attach_debugger: [:post, 'session/:session_id/apple/attach_debugger']
|
30
29
|
}.freeze
|
31
30
|
|
31
|
+
def command_list
|
32
|
+
SAFARI_COMMANDS.merge(self.class::COMMANDS)
|
33
|
+
end
|
34
|
+
|
32
35
|
def commands(command)
|
33
|
-
|
36
|
+
command_list[command]
|
34
37
|
end
|
35
38
|
|
36
39
|
def permissions
|
@@ -44,7 +47,6 @@ module Selenium
|
|
44
47
|
def attach_debugger
|
45
48
|
execute :attach_debugger, {}, {}
|
46
49
|
end
|
47
|
-
|
48
50
|
end # Bridge
|
49
51
|
end # Safari
|
50
52
|
end # WebDriver
|
@@ -26,7 +26,7 @@ module Selenium
|
|
26
26
|
# @see https://developer.apple.com/documentation/webkit/about_webdriver_for_safari
|
27
27
|
CAPABILITIES = {automatic_inspection: 'safari:automaticInspection',
|
28
28
|
automatic_profiling: 'safari:automaticProfiling'}.freeze
|
29
|
-
BROWSER = 'safari'
|
29
|
+
BROWSER = Selenium::WebDriver::Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
|
30
30
|
|
31
31
|
def add_option(name, value = nil)
|
32
32
|
key = name.is_a?(Hash) ? name.keys.first : name
|
@@ -35,6 +35,10 @@ module Selenium
|
|
35
35
|
super
|
36
36
|
end
|
37
37
|
|
38
|
+
def as_json(*)
|
39
|
+
@options[:browser_name] = Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
|
40
|
+
super
|
41
|
+
end
|
38
42
|
end # Options
|
39
43
|
end # Safari
|
40
44
|
end # WebDriver
|
@@ -23,11 +23,17 @@ module Selenium
|
|
23
23
|
class Service < WebDriver::Service
|
24
24
|
DEFAULT_PORT = 7050
|
25
25
|
EXECUTABLE = 'safaridriver'
|
26
|
-
MISSING_TEXT = <<~ERROR
|
27
|
-
Unable to find Apple's safaridriver which comes with Safari 10.
|
28
|
-
More info at https://webkit.org/blog/6900/webdriver-support-in-safari-10/
|
29
|
-
ERROR
|
30
26
|
SHUTDOWN_SUPPORTED = false
|
27
|
+
DRIVER_PATH_ENV_KEY = 'SE_SAFARIDRIVER'
|
28
|
+
def initialize(path: nil, port: nil, log: nil, args: nil)
|
29
|
+
raise Error::WebDriverError, 'Safari Service does not support setting log output' if log
|
30
|
+
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def log=(*)
|
35
|
+
raise Error::WebDriverError, 'Safari Service does not support setting log output'
|
36
|
+
end
|
31
37
|
end # Service
|
32
38
|
end # Safari
|
33
39
|
end # WebDriver
|
@@ -29,7 +29,7 @@ module Selenium
|
|
29
29
|
attr_accessor :use_technology_preview
|
30
30
|
|
31
31
|
def technology_preview
|
32
|
-
|
32
|
+
'/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
|
33
33
|
end
|
34
34
|
|
35
35
|
def technology_preview!
|
@@ -53,20 +53,6 @@ module Selenium
|
|
53
53
|
|
54
54
|
raise Error::WebDriverError, 'Unable to find Safari'
|
55
55
|
end
|
56
|
-
|
57
|
-
def driver_path=(path)
|
58
|
-
WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path=',
|
59
|
-
'Selenium::WebDriver::Safari::Service#driver_path=',
|
60
|
-
id: :driver_path
|
61
|
-
Selenium::WebDriver::Safari::Service.driver_path = path
|
62
|
-
end
|
63
|
-
|
64
|
-
def driver_path
|
65
|
-
WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path',
|
66
|
-
'Selenium::WebDriver::Safari::Service#driver_path',
|
67
|
-
id: :driver_path
|
68
|
-
Selenium::WebDriver::Safari::Service.driver_path
|
69
|
-
end
|
70
56
|
end
|
71
57
|
end # Safari
|
72
58
|
end # WebDriver
|
@@ -21,29 +21,29 @@ module Selenium
|
|
21
21
|
module WebDriver
|
22
22
|
module Support
|
23
23
|
class Color
|
24
|
-
RGB_PATTERN =
|
24
|
+
RGB_PATTERN = /^\s*rgb\(\s*(\d{1,3})\s*,
|
25
25
|
\s*(\d{1,3})\s*,
|
26
|
-
\s*(\d{1,3})\s*\)\s
|
27
|
-
RGB_PCT_PATTERN =
|
26
|
+
\s*(\d{1,3})\s*\)\s*$/x
|
27
|
+
RGB_PCT_PATTERN = /^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
|
28
28
|
\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
|
29
|
-
\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s
|
30
|
-
RGBA_PATTERN =
|
29
|
+
\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$/x
|
30
|
+
RGBA_PATTERN = /^\s*rgba\(\s*(\d{1,3})\s*,
|
31
31
|
\s*(\d{1,3})\s*,
|
32
32
|
\s*(\d{1,3})\s*,
|
33
|
-
\s*(0|1|0\.\d+)\s*\)\s
|
34
|
-
RGBA_PCT_PATTERN =
|
33
|
+
\s*(0|1|0\.\d+)\s*\)\s*$/x
|
34
|
+
RGBA_PCT_PATTERN = /^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)
|
35
35
|
%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)
|
36
36
|
%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)
|
37
|
-
%\s*,\s*(0|1|0\.\d+)\s*\)\s
|
38
|
-
HEX_PATTERN = /#(\h{2})(\h{2})(\h{2})
|
39
|
-
HEX3_PATTERN = /#(\h)(\h)(\h)
|
40
|
-
HSL_PATTERN =
|
37
|
+
%\s*,\s*(0|1|0\.\d+)\s*\)\s*$/x
|
38
|
+
HEX_PATTERN = /#(\h{2})(\h{2})(\h{2})/
|
39
|
+
HEX3_PATTERN = /#(\h)(\h)(\h)/
|
40
|
+
HSL_PATTERN = /^\s*hsl\(\s*(\d{1,3})\s*,
|
41
41
|
\s*(\d{1,3})%\s*,
|
42
|
-
\s*(\d{1,3})%\s*\)\s
|
43
|
-
HSLA_PATTERN =
|
42
|
+
\s*(\d{1,3})%\s*\)\s*$/x
|
43
|
+
HSLA_PATTERN = /^\s*hsla\(\s*(\d{1,3})\s*,
|
44
44
|
\s*(\d{1,3})%\s*,
|
45
45
|
\s*(\d{1,3})%\s*,
|
46
|
-
\s*(0|1|0\.\d+)\s*\)\s
|
46
|
+
\s*(0|1|0\.\d+)\s*\)\s*$/x
|
47
47
|
|
48
48
|
attr_reader :red, :green, :blue, :alpha
|
49
49
|
|
@@ -83,12 +83,12 @@ module Selenium
|
|
83
83
|
g = r
|
84
84
|
b = r
|
85
85
|
else
|
86
|
-
luminocity2 = l < 0.5 ? l * (
|
87
|
-
luminocity1 =
|
86
|
+
luminocity2 = l < 0.5 ? l * (s + 1) : l + s - (l * s)
|
87
|
+
luminocity1 = (l * 2) - luminocity2
|
88
88
|
|
89
|
-
r = hue_to_rgb(luminocity1, luminocity2, h + 1.0 / 3.0)
|
89
|
+
r = hue_to_rgb(luminocity1, luminocity2, h + (1.0 / 3.0))
|
90
90
|
g = hue_to_rgb(luminocity1, luminocity2, h)
|
91
|
-
b = hue_to_rgb(luminocity1, luminocity2, h - 1.0 / 3.0)
|
91
|
+
b = hue_to_rgb(luminocity1, luminocity2, h - (1.0 / 3.0))
|
92
92
|
end
|
93
93
|
|
94
94
|
new (r * 255).round, (g * 255).round, (b * 255).round, a
|
@@ -99,11 +99,11 @@ module Selenium
|
|
99
99
|
hue -= 1 if hue > 1.0
|
100
100
|
|
101
101
|
if hue < 1.0 / 6.0
|
102
|
-
(lum1 + (lum2 - lum1) * 6.0 * hue)
|
102
|
+
(lum1 + ((lum2 - lum1) * 6.0 * hue))
|
103
103
|
elsif hue < 1.0 / 2.0
|
104
104
|
lum2
|
105
105
|
elsif hue < 2.0 / 3.0
|
106
|
-
lum1 + (lum2 - lum1) * ((2.0 / 3.0) - hue) * 6.0
|
106
|
+
lum1 + ((lum2 - lum1) * ((2.0 / 3.0) - hue) * 6.0)
|
107
107
|
else
|
108
108
|
lum1
|
109
109
|
end
|
@@ -122,10 +122,10 @@ module Selenium
|
|
122
122
|
|
123
123
|
[red, green, blue, alpha] == [other.red, other.green, other.blue, other.alpha]
|
124
124
|
end
|
125
|
-
|
125
|
+
alias eql? ==
|
126
126
|
|
127
127
|
def hash
|
128
|
-
[red, green, blue, alpha
|
128
|
+
[red, green, blue, alpha, self.class].hash
|
129
129
|
end
|
130
130
|
|
131
131
|
def rgb
|
@@ -113,15 +113,15 @@ module Selenium
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def dispatch(name, *args)
|
116
|
-
@listener.__send__("before_#{name}", *args)
|
116
|
+
@listener.__send__(:"before_#{name}", *args)
|
117
117
|
returned = yield
|
118
|
-
@listener.__send__("after_#{name}", *args)
|
118
|
+
@listener.__send__(:"after_#{name}", *args)
|
119
119
|
|
120
120
|
returned
|
121
121
|
end
|
122
122
|
|
123
|
-
def method_missing(meth,
|
124
|
-
@delegate.__send__(meth,
|
123
|
+
def method_missing(meth, ...) # rubocop:disable Style/MissingRespondToMissing
|
124
|
+
@delegate.__send__(meth, ...)
|
125
125
|
end
|
126
126
|
end # EventFiringBridge
|
127
127
|
end # Support
|