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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ba40ae3f831d1c9a379d4799c59226f2edf5a0c6429b8cb55a8e95daed84231
4
- data.tar.gz: b03c61460a257c5d028575607a59e41819b17e2baf47308e19086cd7194b70d5
3
+ metadata.gz: d3f3769c3f06d18f04b2c853d6d8bbce6a8f5a65dc125cf6e6e654255165ae4d
4
+ data.tar.gz: e410cd9baf19d27129da632a1ca7056ec286ed887dae207c9d20b8ec0c98dc61
5
5
  SHA512:
6
- metadata.gz: 0ac2c28f5f6c9006fee5bd5f59f8099596cb9773c42f40498ffa03bf9ede46bc1255cd1cdbdbb72ed6af9721c3e68987feb39859732ade34bed6f3dd94251d4c
7
- data.tar.gz: f98a8768f75757c2b35a296b5c4f2e4dd4e64d864c4e05b1399695246919047c2cd5cfb8baf4f668efae584afafeda948db17743f9c6baecf5b9959bb6ff6df7
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)
Binary file
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
- self[:name] = name.to_s
31
- self[:value] = {type: 'string', value: val.to_s}
32
-
33
- [compact]
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
 
@@ -24,7 +24,8 @@ module Selenium
24
24
  #
25
25
 
26
26
  class ChildProcess
27
- TimeoutError = Class.new(StandardError)
27
+ class TimeoutError < StandardError
28
+ end
28
29
 
29
30
  SIGTERM = 'TERM'
30
31
  SIGKILL = 'KILL'
@@ -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
- @io ||= WebDriver.logger.io if WebDriver.logger.debug?
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(path: nil, port: nil, log: nil, args: nil)
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, *) # rubocop:disable Style/MissingRespondToMissing
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(h, s, l, a) # rubocop:disable Naming/MethodParameterName
76
- h = Float(h) / 360
77
- s = Float(s) / 100
78
- l = Float(l) / 100
79
- a = Float(a || 1)
80
-
81
- if s.zero?
82
- r = l
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 = l < 0.5 ? l * (s + 1) : l + s - (l * s)
87
- luminocity1 = (l * 2) - luminocity2
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, h + (1.0 / 3.0))
90
- g = hue_to_rgb(luminocity1, luminocity2, h)
91
- b = hue_to_rgb(luminocity1, luminocity2, h - (1.0 / 3.0))
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, a
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, ...) # rubocop:disable Style/MissingRespondToMissing
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
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.40.0'
22
+ VERSION = '4.41.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -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.40.0
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-01-18 00:00:00.000000000 Z
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