selenium-webdriver 4.40.0 → 4.41.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 +10 -0
- 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/webdriver/bidi/network/cookies.rb +7 -4
- data/lib/selenium/webdriver/chrome/service.rb +10 -0
- data/lib/selenium/webdriver/common/child_process.rb +2 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_session_events.rb +48 -0
- data/lib/selenium/webdriver/common/logger.rb +28 -0
- data/lib/selenium/webdriver/common/service.rb +6 -0
- data/lib/selenium/webdriver/common/service_manager.rb +7 -1
- data/lib/selenium/webdriver/common.rb +1 -0
- data/lib/selenium/webdriver/edge/service.rb +11 -0
- data/lib/selenium/webdriver/firefox/service.rb +21 -2
- data/lib/selenium/webdriver/ie/service.rb +10 -0
- data/lib/selenium/webdriver/remote/driver.rb +1 -0
- data/lib/selenium/webdriver/remote/features.rb +26 -1
- data/lib/selenium/webdriver/support/block_event_listener.rb +5 -1
- data/lib/selenium/webdriver/support/color.rb +14 -14
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +5 -1
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +6 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3f3769c3f06d18f04b2c853d6d8bbce6a8f5a65dc125cf6e6e654255165ae4d
|
|
4
|
+
data.tar.gz: e410cd9baf19d27129da632a1ca7056ec286ed887dae207c9d20b8ec0c98dc61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ffadd3dd7dd1be1746c0577c6ffe335637b6e9ff34ae8d81b07edad4cb5a6c279d4a05ffe9aeadf0ef6cb3d68da8469213fe2163a00d896c49bb0bf8e05bf6c
|
|
7
|
+
data.tar.gz: a703ea20b011cd8c3ee5016e58ea4671a88698d434f5f7dc6a32b3cdcc55c3e9a25425c379194e4577873a316626cab8487d40077a372fa9d78759939c1e70ce
|
data/CHANGES
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
4.41.0 (2026-02-19)
|
|
2
|
+
=========================
|
|
3
|
+
* Support CDP versions: v143, v144, v145
|
|
4
|
+
* remove stored atoms these get generated by build (#16971)
|
|
5
|
+
* output driver logs when SE_DEBUG is enabled (#16901)
|
|
6
|
+
* Update lint configuration and fix rubocop offenses (#17008)
|
|
7
|
+
* add missing unit tests (#17025)
|
|
8
|
+
* [grid] Add session event API for server-side event bus integration (#17015)
|
|
9
|
+
* Update dependencies (#17111)
|
|
10
|
+
|
|
1
11
|
4.40.0 (2026-01-18)
|
|
2
12
|
=========================
|
|
3
13
|
* add synchronization and error handling for socket interactions (#16487)
|
data/bin/linux/selenium-manager
CHANGED
|
Binary file
|
data/bin/macos/selenium-manager
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -27,10 +27,13 @@ module Selenium
|
|
|
27
27
|
class Cookies < Hash
|
|
28
28
|
def as_json
|
|
29
29
|
map do |name, val|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
{
|
|
31
|
+
name: name.to_s,
|
|
32
|
+
value: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
value: val.to_s
|
|
35
|
+
}
|
|
36
|
+
}
|
|
34
37
|
end
|
|
35
38
|
end
|
|
36
39
|
end
|
|
@@ -26,6 +26,16 @@ module Selenium
|
|
|
26
26
|
SHUTDOWN_SUPPORTED = true
|
|
27
27
|
DRIVER_PATH_ENV_KEY = 'SE_CHROMEDRIVER'
|
|
28
28
|
|
|
29
|
+
def initialize(args: nil, **)
|
|
30
|
+
if ENV.key?('SE_DEBUG')
|
|
31
|
+
args = Array(args.dup)
|
|
32
|
+
warn_driver_log_override if args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
|
|
33
|
+
args << '--verbose'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
|
|
29
39
|
def log
|
|
30
40
|
return @log unless @log.is_a? String
|
|
31
41
|
|
|
@@ -0,0 +1,48 @@
|
|
|
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 DriverExtensions
|
|
23
|
+
module HasSessionEvents
|
|
24
|
+
#
|
|
25
|
+
# Fires a custom session event to the remote server event bus.
|
|
26
|
+
# This allows test code to trigger server-side utilities that subscribe to
|
|
27
|
+
# the event bus.
|
|
28
|
+
#
|
|
29
|
+
# @param [String] event_type The type of event (e.g., "test:failed", "log:collect")
|
|
30
|
+
# @param [Hash] payload Optional data to include with the event
|
|
31
|
+
# @return [Hash] Response data including success status, event type, and timestamp
|
|
32
|
+
#
|
|
33
|
+
# @example Fire a simple event
|
|
34
|
+
# driver.fire_session_event("test:started")
|
|
35
|
+
#
|
|
36
|
+
# @example Fire an event with payload
|
|
37
|
+
# driver.fire_session_event("test:failed", {
|
|
38
|
+
# testName: "LoginTest",
|
|
39
|
+
# error: "Element not found"
|
|
40
|
+
# })
|
|
41
|
+
#
|
|
42
|
+
def fire_session_event(event_type, payload = nil)
|
|
43
|
+
@bridge.fire_session_event(event_type, payload)
|
|
44
|
+
end
|
|
45
|
+
end # HasSessionEvents
|
|
46
|
+
end # DriverExtensions
|
|
47
|
+
end # WebDriver
|
|
48
|
+
end # Selenium
|
|
@@ -55,9 +55,32 @@ module Selenium
|
|
|
55
55
|
@ignored = Array(ignored)
|
|
56
56
|
@allowed = Array(allowed)
|
|
57
57
|
@first_warning = false
|
|
58
|
+
@level_forced = false
|
|
59
|
+
@output_forced = false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# Forces debug level and prevents it from being overridden.
|
|
64
|
+
#
|
|
65
|
+
def debug!
|
|
66
|
+
@level_forced = true
|
|
67
|
+
@logger.level = :debug
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
#
|
|
71
|
+
# Forces output to stderr and prevents it from being overridden.
|
|
72
|
+
#
|
|
73
|
+
def stderr!
|
|
74
|
+
@output_forced = true
|
|
75
|
+
@logger.reopen($stderr)
|
|
58
76
|
end
|
|
59
77
|
|
|
60
78
|
def level=(level)
|
|
79
|
+
if @level_forced
|
|
80
|
+
warn('Logger level is forced; ignoring override', id: :logger)
|
|
81
|
+
return
|
|
82
|
+
end
|
|
83
|
+
|
|
61
84
|
if level == :info && @logger.level == :info
|
|
62
85
|
info(':info is now the default log level, to see additional logging, set log level to :debug')
|
|
63
86
|
end
|
|
@@ -71,6 +94,11 @@ module Selenium
|
|
|
71
94
|
# @param [String] io
|
|
72
95
|
#
|
|
73
96
|
def output=(io)
|
|
97
|
+
if @output_forced
|
|
98
|
+
warn('Logger output is forced; ignoring override', id: :logger)
|
|
99
|
+
return
|
|
100
|
+
end
|
|
101
|
+
|
|
74
102
|
@logger.reopen(io)
|
|
75
103
|
end
|
|
76
104
|
|
|
@@ -104,6 +104,12 @@ module Selenium
|
|
|
104
104
|
def env_path
|
|
105
105
|
ENV.fetch(self.class::DRIVER_PATH_ENV_KEY, nil)
|
|
106
106
|
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def warn_driver_log_override
|
|
111
|
+
WebDriver.logger.warn('SE_DEBUG is set; overriding user-specified driver logging settings', id: :se_debug)
|
|
112
|
+
end
|
|
107
113
|
end # Service
|
|
108
114
|
end # WebDriver
|
|
109
115
|
end # Selenium
|
|
@@ -80,7 +80,13 @@ module Selenium
|
|
|
80
80
|
def build_process(*command)
|
|
81
81
|
WebDriver.logger.debug("Executing Process #{command}", id: :driver_service)
|
|
82
82
|
@process = ChildProcess.build(*command)
|
|
83
|
-
|
|
83
|
+
if ENV.key?('SE_DEBUG')
|
|
84
|
+
if @io && @io != WebDriver.logger.io
|
|
85
|
+
WebDriver.logger.warn('SE_DEBUG is set; overriding user-specified driver log output to use stderr',
|
|
86
|
+
id: :se_debug)
|
|
87
|
+
end
|
|
88
|
+
@io = WebDriver.logger.io
|
|
89
|
+
end
|
|
84
90
|
@process.io = @io if @io
|
|
85
91
|
|
|
86
92
|
@process
|
|
@@ -78,6 +78,7 @@ require 'selenium/webdriver/common/driver_extensions/has_addons'
|
|
|
78
78
|
require 'selenium/webdriver/common/driver_extensions/has_bidi'
|
|
79
79
|
require 'selenium/webdriver/common/driver_extensions/has_devtools'
|
|
80
80
|
require 'selenium/webdriver/common/driver_extensions/has_file_downloads'
|
|
81
|
+
require 'selenium/webdriver/common/driver_extensions/has_session_events'
|
|
81
82
|
require 'selenium/webdriver/common/driver_extensions/has_authentication'
|
|
82
83
|
require 'selenium/webdriver/common/driver_extensions/has_logs'
|
|
83
84
|
require 'selenium/webdriver/common/driver_extensions/has_log_events'
|
|
@@ -25,6 +25,17 @@ module Selenium
|
|
|
25
25
|
EXECUTABLE = 'msedgedriver'
|
|
26
26
|
SHUTDOWN_SUPPORTED = true
|
|
27
27
|
DRIVER_PATH_ENV_KEY = 'SE_EDGEDRIVER'
|
|
28
|
+
|
|
29
|
+
def initialize(args: nil, **)
|
|
30
|
+
if ENV.key?('SE_DEBUG')
|
|
31
|
+
args = Array(args.dup)
|
|
32
|
+
warn_driver_log_override if args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
|
|
33
|
+
args << '--verbose'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
|
|
28
39
|
def log
|
|
29
40
|
return @log unless @log.is_a? String
|
|
30
41
|
|
|
@@ -26,14 +26,33 @@ module Selenium
|
|
|
26
26
|
SHUTDOWN_SUPPORTED = false
|
|
27
27
|
DRIVER_PATH_ENV_KEY = 'SE_GECKODRIVER'
|
|
28
28
|
|
|
29
|
-
def initialize(
|
|
30
|
-
args
|
|
29
|
+
def initialize(args: nil, **)
|
|
30
|
+
args = Array(args.dup)
|
|
31
31
|
unless args.any? { |arg| arg.include?('--connect-existing') || arg.include?('--websocket-port') }
|
|
32
32
|
args << '--websocket-port'
|
|
33
33
|
args << '0'
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
if ENV.key?('SE_DEBUG')
|
|
37
|
+
remove_log_args(args)
|
|
38
|
+
args << '-v'
|
|
39
|
+
end
|
|
40
|
+
|
|
35
41
|
super
|
|
36
42
|
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def remove_log_args(args)
|
|
47
|
+
if (index = args.index('--log'))
|
|
48
|
+
args.delete_at(index) # delete '--log'
|
|
49
|
+
args.delete_at(index) if args[index] && !args[index].start_with?('-') # delete value if present
|
|
50
|
+
warn_driver_log_override
|
|
51
|
+
elsif (index = args.index { |arg| arg.start_with?('--log=') })
|
|
52
|
+
args.delete_at(index)
|
|
53
|
+
warn_driver_log_override
|
|
54
|
+
end
|
|
55
|
+
end
|
|
37
56
|
end # Service
|
|
38
57
|
end # Firefox
|
|
39
58
|
end # WebDriver
|
|
@@ -25,6 +25,16 @@ module Selenium
|
|
|
25
25
|
EXECUTABLE = 'IEDriverServer'
|
|
26
26
|
SHUTDOWN_SUPPORTED = true
|
|
27
27
|
DRIVER_PATH_ENV_KEY = 'SE_IEDRIVER'
|
|
28
|
+
|
|
29
|
+
def initialize(args: nil, **)
|
|
30
|
+
if ENV.key?('SE_DEBUG')
|
|
31
|
+
args = Array(args.dup)
|
|
32
|
+
warn_driver_log_override if args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
|
|
33
|
+
args << '--log-level=DEBUG'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
super
|
|
37
|
+
end
|
|
28
38
|
end # Server
|
|
29
39
|
end # IE
|
|
30
40
|
end # WebDriver
|
|
@@ -29,6 +29,7 @@ module Selenium
|
|
|
29
29
|
include DriverExtensions::UploadsFiles
|
|
30
30
|
include DriverExtensions::HasSessionId
|
|
31
31
|
include DriverExtensions::HasFileDownloads
|
|
32
|
+
include DriverExtensions::HasSessionEvents
|
|
32
33
|
|
|
33
34
|
def initialize(capabilities: nil, options: nil, service: nil, url: nil, **)
|
|
34
35
|
raise ArgumentError, "Can not set :service object on #{self.class}" if service
|
|
@@ -25,7 +25,8 @@ module Selenium
|
|
|
25
25
|
upload_file: [:post, 'session/:session_id/se/file'],
|
|
26
26
|
get_downloadable_files: [:get, 'session/:session_id/se/files'],
|
|
27
27
|
download_file: [:post, 'session/:session_id/se/files'],
|
|
28
|
-
delete_downloadable_files: [:delete, 'session/:session_id/se/files']
|
|
28
|
+
delete_downloadable_files: [:delete, 'session/:session_id/se/files'],
|
|
29
|
+
fire_session_event: [:post, 'session/:session_id/se/event']
|
|
29
30
|
}.freeze
|
|
30
31
|
|
|
31
32
|
def add_commands(commands)
|
|
@@ -69,6 +70,30 @@ module Selenium
|
|
|
69
70
|
def delete_downloadable_files
|
|
70
71
|
execute :delete_downloadable_files
|
|
71
72
|
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Fires a custom session event to the remote server event bus.
|
|
76
|
+
# This allows test code to trigger server-side utilities that subscribe to
|
|
77
|
+
# the event bus.
|
|
78
|
+
#
|
|
79
|
+
# @param [String] event_type The type of event (e.g., "test:failed", "log:collect")
|
|
80
|
+
# @param [Hash] payload Optional data to include with the event
|
|
81
|
+
# @return [Hash] Response data including success status, event type, and timestamp
|
|
82
|
+
#
|
|
83
|
+
# @example Fire a simple event
|
|
84
|
+
# driver.fire_session_event("test:started")
|
|
85
|
+
#
|
|
86
|
+
# @example Fire an event with payload
|
|
87
|
+
# driver.fire_session_event("test:failed", {
|
|
88
|
+
# testName: "LoginTest",
|
|
89
|
+
# error: "Element not found"
|
|
90
|
+
# })
|
|
91
|
+
#
|
|
92
|
+
def fire_session_event(event_type, payload = nil)
|
|
93
|
+
params = {eventType: event_type}
|
|
94
|
+
params[:payload] = payload if payload
|
|
95
|
+
execute :fire_session_event, {}, params
|
|
96
|
+
end
|
|
72
97
|
end
|
|
73
98
|
end # Remote
|
|
74
99
|
end # WebDriver
|
|
@@ -25,9 +25,13 @@ module Selenium
|
|
|
25
25
|
@callback = callback
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def method_missing(meth, *)
|
|
28
|
+
def method_missing(meth, *)
|
|
29
29
|
@callback.call(meth, *)
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
def respond_to_missing?(_meth, _include_private = false)
|
|
33
|
+
true
|
|
34
|
+
end
|
|
31
35
|
end # BlockEventListener
|
|
32
36
|
end # Support
|
|
33
37
|
end # WebDriver
|
|
@@ -72,26 +72,26 @@ module Selenium
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
def self.from_hsl(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if
|
|
82
|
-
r =
|
|
75
|
+
def self.from_hsl(hue, sat, light, alpha)
|
|
76
|
+
hue = Float(hue) / 360
|
|
77
|
+
sat = Float(sat) / 100
|
|
78
|
+
light = Float(light) / 100
|
|
79
|
+
alpha = Float(alpha || 1)
|
|
80
|
+
|
|
81
|
+
if sat.zero?
|
|
82
|
+
r = light
|
|
83
83
|
g = r
|
|
84
84
|
b = r
|
|
85
85
|
else
|
|
86
|
-
luminocity2 =
|
|
87
|
-
luminocity1 = (
|
|
86
|
+
luminocity2 = light < 0.5 ? light * (sat + 1) : light + sat - (light * sat)
|
|
87
|
+
luminocity1 = (light * 2) - luminocity2
|
|
88
88
|
|
|
89
|
-
r = hue_to_rgb(luminocity1, luminocity2,
|
|
90
|
-
g = hue_to_rgb(luminocity1, luminocity2,
|
|
91
|
-
b = hue_to_rgb(luminocity1, luminocity2,
|
|
89
|
+
r = hue_to_rgb(luminocity1, luminocity2, hue + (1.0 / 3.0))
|
|
90
|
+
g = hue_to_rgb(luminocity1, luminocity2, hue)
|
|
91
|
+
b = hue_to_rgb(luminocity1, luminocity2, hue - (1.0 / 3.0))
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
new (r * 255).round, (g * 255).round, (b * 255).round,
|
|
94
|
+
new (r * 255).round, (g * 255).round, (b * 255).round, alpha
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
def self.hue_to_rgb(lum1, lum2, hue)
|
|
@@ -120,9 +120,13 @@ module Selenium
|
|
|
120
120
|
returned
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
-
def method_missing(meth, ...)
|
|
123
|
+
def method_missing(meth, ...)
|
|
124
124
|
@delegate.__send__(meth, ...)
|
|
125
125
|
end
|
|
126
|
+
|
|
127
|
+
def respond_to_missing?(meth, include_private = false)
|
|
128
|
+
@delegate.respond_to?(meth, include_private) || super
|
|
129
|
+
end
|
|
126
130
|
end # EventFiringBridge
|
|
127
131
|
end # Support
|
|
128
132
|
end # WebDriver
|
data/lib/selenium/webdriver.rb
CHANGED
|
@@ -96,7 +96,12 @@ module Selenium
|
|
|
96
96
|
|
|
97
97
|
def self.logger(**)
|
|
98
98
|
level = $DEBUG || ENV.key?('DEBUG') || ENV.key?('SE_DEBUG') ? :debug : :info
|
|
99
|
-
@logger ||= WebDriver::Logger.new('Selenium', default_level: level, **)
|
|
99
|
+
@logger ||= WebDriver::Logger.new('Selenium', default_level: level, **).tap do |logger|
|
|
100
|
+
if ENV.key?('SE_DEBUG')
|
|
101
|
+
logger.debug!
|
|
102
|
+
logger.stderr!
|
|
103
|
+
end
|
|
104
|
+
end
|
|
100
105
|
end
|
|
101
106
|
end # WebDriver
|
|
102
107
|
end # Selenium
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: selenium-webdriver
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.41.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex Rodionov
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2026-
|
|
13
|
+
date: 2026-02-20 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: base64
|
|
@@ -333,6 +333,7 @@ files:
|
|
|
333
333
|
- lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb
|
|
334
334
|
- lib/selenium/webdriver/common/driver_extensions/has_permissions.rb
|
|
335
335
|
- lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb
|
|
336
|
+
- lib/selenium/webdriver/common/driver_extensions/has_session_events.rb
|
|
336
337
|
- lib/selenium/webdriver/common/driver_extensions/has_session_id.rb
|
|
337
338
|
- lib/selenium/webdriver/common/driver_extensions/prints_page.rb
|
|
338
339
|
- lib/selenium/webdriver/common/driver_extensions/uploads_files.rb
|