selenium-webdriver 4.21.0 → 4.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +19 -0
  3. data/README.md +1 -1
  4. data/bin/linux/selenium-manager +0 -0
  5. data/bin/macos/selenium-manager +0 -0
  6. data/bin/windows/selenium-manager.exe +0 -0
  7. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +1 -1
  8. data/lib/selenium/webdriver/bidi/log_handler.rb +63 -0
  9. data/lib/selenium/webdriver/bidi/log_inspector.rb +5 -1
  10. data/lib/selenium/webdriver/bidi/session.rb +7 -7
  11. data/lib/selenium/webdriver/bidi/struct.rb +44 -0
  12. data/lib/selenium/webdriver/bidi.rb +10 -0
  13. data/lib/selenium/webdriver/common/child_process.rb +8 -2
  14. data/lib/selenium/webdriver/common/driver.rb +20 -14
  15. data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +1 -1
  16. data/lib/selenium/webdriver/common/driver_finder.rb +8 -1
  17. data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +1 -1
  18. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +1 -1
  19. data/lib/selenium/webdriver/common/logger.rb +1 -1
  20. data/lib/selenium/webdriver/common/script.rb +45 -0
  21. data/lib/selenium/webdriver/common/websocket_connection.rb +12 -0
  22. data/lib/selenium/webdriver/common.rb +1 -0
  23. data/lib/selenium/webdriver/firefox/options.rb +3 -0
  24. data/lib/selenium/webdriver/ie/options.rb +3 -2
  25. data/lib/selenium/webdriver/remote/bidi_bridge.rb +44 -0
  26. data/lib/selenium/webdriver/remote/bridge.rb +5 -0
  27. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  28. data/lib/selenium/webdriver/remote.rb +1 -0
  29. data/lib/selenium/webdriver/support/guards/guard.rb +8 -9
  30. data/lib/selenium/webdriver/version.rb +1 -1
  31. data/selenium-webdriver.gemspec +2 -0
  32. metadata +34 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f5e5266f21804cd7520e61a6036171a3bda203460d944ac61cfd324283f72ae
4
- data.tar.gz: 8a58672a580239e27c909e781b16ff588f216f535dda5e495eff5123224e36b2
3
+ metadata.gz: 425032a72d60652d09ca2ee43f54c4d9ff9abdb8d22cde817902b59ee42f4bb1
4
+ data.tar.gz: 149b4ee90b89bf5d5c82fbc274f2758034dd0827671639041232a8fee208b756
5
5
  SHA512:
6
- metadata.gz: 78473145c4ce27a7acf22c58e6c204f7beac53b47a3b18139bb895c08c5d1da90ec5ac558bab429f5284604bba717415be0d8606bb298a68278a22a57947a546
7
- data.tar.gz: b1ae030703351b2b799881b041c9554e0c23c8cfc60a6e8eb32e7f679a7ea23f1c72c7cdbca203b2830439e2488a1ff56c6763df960f8eb873f08356f79ccf91
6
+ metadata.gz: 3025eae993eb26d61f3bc67d975611c8bf5a0c61ebf72685b19c263f2d4a1dc26c55e0c4dc9c406e17cdcd84437fc6bf56d583ef3833b227299109abefa294b6
7
+ data.tar.gz: 32e914171ea8ba5b4635edf5f829a982f6a343911475a56827b71ded109e3702fcd4079b7db12c49311e16b3ef1df81b0ee4365df1c6011c542aca8d7a348d19
data/CHANGES CHANGED
@@ -1,3 +1,22 @@
1
+ 4.22.0 (2024-06-20)
2
+ =========================
3
+
4
+ * Force UTF-8 encoding on logger (see #6937)
5
+ * Don't crash when ChildProcess is already killed (see #14032)
6
+ * Manage bidi instance on the bridge not the driver (#14071)
7
+ * Implement High Level Logging API with BiDi (#14073)
8
+ * Fix bug with message deletion in Guard class
9
+ * Change output for Guard class
10
+ * Implement toggle for BiDi and Classic implementations (#14092)
11
+ * Add preference to enable CDP in Firefox by default (#14091)
12
+ * Add support for the w3c silent option for the ruby library (#14152)
13
+ * Add CDP for Chrome 126 and remove 123
14
+
15
+ 4.21.1 (2024-05-16)
16
+ =========================
17
+
18
+ * Fixed missing Chrome binary error in Rails system tests.
19
+
1
20
  4.21.0 (2024-05-16)
2
21
  =========================
3
22
 
data/README.md CHANGED
@@ -15,7 +15,7 @@ This gem provides Ruby bindings for Selenium and supports MRI >= 3.0.
15
15
 
16
16
  ## License
17
17
 
18
- Copyright 2009-2023 Software Freedom Conservancy
18
+ Copyright 2009-2024 Software Freedom Conservancy
19
19
 
20
20
  Licensed to the Software Freedom Conservancy (SFC) under one
21
21
  or more contributor license agreements. See the NOTICE file
Binary file
Binary file
Binary file
@@ -24,7 +24,7 @@ module Selenium
24
24
  attr_accessor :type
25
25
 
26
26
  def initialize(level:, text:, timestamp:, type:, stack_trace:)
27
- super(level: level, text: text, timestamp: timestamp, type: type, stack_trace: stack_trace)
27
+ super
28
28
  @type = 'javascript'
29
29
  end
30
30
  end # JavascriptLogEntry
@@ -0,0 +1,63 @@
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
+ class BiDi
23
+ class LogHandler
24
+ ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :method, :args, :type)
25
+ JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type)
26
+
27
+ def initialize(bidi)
28
+ @bidi = bidi
29
+ @log_entry_subscribed = false
30
+ end
31
+
32
+ # @return [int] id of the handler
33
+ def add_message_handler(type)
34
+ subscribe_log_entry unless @log_entry_subscribed
35
+ @bidi.add_callback('log.entryAdded') do |params|
36
+ if params['type'] == type
37
+ log_entry_klass = type == 'console' ? ConsoleLogEntry : JavaScriptLogEntry
38
+ yield(log_entry_klass.new(**params))
39
+ end
40
+ end
41
+ end
42
+
43
+ # @param [int] id of the handler previously added
44
+ def remove_message_handler(id)
45
+ @bidi.remove_callback('log.entryAdded', id)
46
+ unsubscribe_log_entry if @log_entry_subscribed && @bidi.callbacks['log.entryAdded'].empty?
47
+ end
48
+
49
+ private
50
+
51
+ def subscribe_log_entry
52
+ @bidi.session.subscribe('log.entryAdded')
53
+ @log_entry_subscribed = true
54
+ end
55
+
56
+ def unsubscribe_log_entry
57
+ @bidi.session.unsubscribe('log.entryAdded')
58
+ @log_entry_subscribed = false
59
+ end
60
+ end # LogHandler
61
+ end # Bidi
62
+ end # WebDriver
63
+ end # Selenium
@@ -41,6 +41,10 @@ module Selenium
41
41
  }.freeze
42
42
 
43
43
  def initialize(driver, browsing_context_ids = nil)
44
+ WebDriver.logger.deprecate('LogInspector class',
45
+ 'Script class with driver.script',
46
+ id: :log_inspector)
47
+
44
48
  unless driver.capabilities.web_socket_url
45
49
  raise Error::WebDriverError,
46
50
  'WebDriver instance must support BiDi protocol'
@@ -92,7 +96,7 @@ module Selenium
92
96
 
93
97
  def on(event, &block)
94
98
  event = EVENTS[event] if event.is_a?(Symbol)
95
- @bidi.callbacks["log.#{event}"] << block
99
+ @bidi.add_callback("log.#{event}", &block)
96
100
  end
97
101
 
98
102
  def check_valid_filter(filter_by)
@@ -29,21 +29,21 @@ module Selenium
29
29
 
30
30
  def status
31
31
  status = @bidi.send_cmd('session.status')
32
- Status.new(status['ready'], status['message'])
32
+ Status.new(**status)
33
33
  end
34
34
 
35
35
  def subscribe(events, browsing_contexts = nil)
36
- events_list = Array(events)
37
- browsing_contexts_list = browsing_contexts.nil? ? nil : Array(browsing_contexts)
36
+ opts = {events: Array(events)}
37
+ opts[:browsing_contexts] = Array(browsing_contexts) if browsing_contexts
38
38
 
39
- @bidi.send_cmd('session.subscribe', events: events_list, contexts: browsing_contexts_list)
39
+ @bidi.send_cmd('session.subscribe', **opts)
40
40
  end
41
41
 
42
42
  def unsubscribe(events, browsing_contexts = nil)
43
- events_list = Array(events)
44
- browsing_contexts_list = browsing_contexts.nil? ? nil : Array(browsing_contexts)
43
+ opts = {events: Array(events)}
44
+ opts[:browsing_contexts] = Array(browsing_contexts) if browsing_contexts
45
45
 
46
- @bidi.send_cmd('session.unsubscribe', events: events_list, contexts: browsing_contexts_list)
46
+ @bidi.send_cmd('session.unsubscribe', **opts)
47
47
  end
48
48
  end # Session
49
49
  end # BiDi
@@ -0,0 +1,44 @@
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
+ class BiDi
23
+ class Struct < ::Struct
24
+ class << self
25
+ def new(*args, &block)
26
+ super(*args) do
27
+ define_method(:initialize) do |**kwargs|
28
+ converted_kwargs = kwargs.transform_keys { |key| self.class.camel_to_snake(key.to_s).to_sym }
29
+ super(*converted_kwargs.values_at(*self.class.members))
30
+ end
31
+ class_eval(&block) if block
32
+ end
33
+ end
34
+
35
+ def camel_to_snake(camel_str)
36
+ camel_str.gsub(/([A-Z])/, '_\1').downcase
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ # BiDi
43
+ end # WebDriver
44
+ end # Selenium
@@ -22,7 +22,9 @@ module Selenium
22
22
  class BiDi
23
23
  autoload :Session, 'selenium/webdriver/bidi/session'
24
24
  autoload :LogInspector, 'selenium/webdriver/bidi/log_inspector'
25
+ autoload :LogHandler, 'selenium/webdriver/bidi/log_handler'
25
26
  autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'
27
+ autoload :Struct, 'selenium/webdriver/bidi/struct'
26
28
 
27
29
  def initialize(url:)
28
30
  @ws = WebSocketConnection.new(url: url)
@@ -36,6 +38,14 @@ module Selenium
36
38
  @ws.callbacks
37
39
  end
38
40
 
41
+ def add_callback(event, &block)
42
+ @ws.add_callback(event, &block)
43
+ end
44
+
45
+ def remove_callback(event, id)
46
+ @ws.remove_callback(event, id)
47
+ end
48
+
39
49
  def session
40
50
  @session ||= Session.new(self)
41
51
  end
@@ -84,7 +84,7 @@ module Selenium
84
84
  return false unless @pid
85
85
 
86
86
  WebDriver.logger.debug("Checking if #{@pid} is exited:", id: :process)
87
- _, @status = Process.waitpid2(@pid, Process::WNOHANG | Process::WUNTRACED) if @status.nil?
87
+ _, @status = waitpid2(@pid, Process::WNOHANG | Process::WUNTRACED) if @status.nil?
88
88
  return false if @status.nil?
89
89
 
90
90
  exit_code = @status.exitstatus || @status.termsig
@@ -105,7 +105,7 @@ module Selenium
105
105
  def wait
106
106
  return if exited?
107
107
 
108
- _, @status = Process.waitpid2(@pid)
108
+ _, @status = waitpid2(@pid)
109
109
  end
110
110
 
111
111
  private
@@ -119,6 +119,12 @@ module Selenium
119
119
  rescue Errno::ECHILD, Errno::ESRCH
120
120
  # already dead
121
121
  end
122
+
123
+ def waitpid2(pid, flags = 0)
124
+ Process.waitpid2(pid, flags)
125
+ rescue Errno::ECHILD
126
+ # already dead
127
+ end
122
128
  end # ChildProcess
123
129
  end # WebDriver
124
130
  end # Selenium
@@ -70,10 +70,9 @@ module Selenium
70
70
 
71
71
  def initialize(bridge: nil, listener: nil, **opts)
72
72
  @devtools = nil
73
- @bidi = nil
74
73
  bridge ||= create_bridge(**opts)
75
- add_extensions(bridge.browser)
76
74
  @bridge = listener ? Support::EventFiringBridge.new(bridge, listener) : bridge
75
+ add_extensions(@bridge.browser)
77
76
  end
78
77
 
79
78
  def inspect
@@ -100,6 +99,22 @@ module Selenium
100
99
  @navigate ||= WebDriver::Navigation.new(bridge)
101
100
  end
102
101
 
102
+ #
103
+ # @return [Script]
104
+ # @see Script
105
+ #
106
+
107
+ def script(*args)
108
+ if args.any?
109
+ WebDriver.logger.deprecate('`Driver#script` as an alias for `#execute_script`',
110
+ '`Driver#execute_script`',
111
+ id: :driver_script)
112
+ execute_script(*args)
113
+ else
114
+ @script ||= WebDriver::Script.new(bridge)
115
+ end
116
+ end
117
+
103
118
  #
104
119
  # @return [TargetLocator]
105
120
  # @see TargetLocator
@@ -174,7 +189,6 @@ module Selenium
174
189
  ensure
175
190
  @service_manager&.stop
176
191
  @devtools&.close
177
- @bidi&.close
178
192
  end
179
193
 
180
194
  #
@@ -182,10 +196,7 @@ module Selenium
182
196
  #
183
197
 
184
198
  def close
185
- # If no top-level browsing contexts are open after calling close,
186
- # it indicates that the WebDriver session is closed.
187
- # If the WebDriver session is closed, the BiDi session also needs to be closed.
188
- bridge.close.tap { |handles| @bidi&.close if handles&.empty? }
199
+ bridge&.close
189
200
  end
190
201
 
191
202
  #
@@ -267,12 +278,6 @@ module Selenium
267
278
 
268
279
  alias all find_elements
269
280
 
270
- #
271
- # driver.script('function() { ... };')
272
- #
273
-
274
- alias script execute_script
275
-
276
281
  # Get the first element matching the given selector. If given a
277
282
  # String or Symbol, it will be used as the id of the element.
278
283
  #
@@ -313,7 +318,8 @@ module Selenium
313
318
  attr_reader :bridge
314
319
 
315
320
  def create_bridge(caps:, url:, http_client: nil)
316
- Remote::Bridge.new(http_client: http_client, url: url).tap do |bridge|
321
+ klass = caps['webSocketUrl'] ? Remote::BiDiBridge : Remote::Bridge
322
+ klass.new(http_client: http_client, url: url).tap do |bridge|
317
323
  bridge.create_session(caps)
318
324
  end
319
325
  end
@@ -28,7 +28,7 @@ module Selenium
28
28
  #
29
29
 
30
30
  def bidi
31
- @bidi ||= Selenium::WebDriver::BiDi.new(url: capabilities[:web_socket_url])
31
+ @bridge.bidi
32
32
  end
33
33
  end # HasBiDi
34
34
  end # DriverExtensions
@@ -59,7 +59,14 @@ module Selenium
59
59
  formatted = {driver_path: Platform.cygwin_path(output['driver_path'], only_cygwin: true),
60
60
  browser_path: Platform.cygwin_path(output['browser_path'], only_cygwin: true)}
61
61
  Platform.assert_executable(formatted[:driver_path])
62
- Platform.assert_executable(formatted[:browser_path])
62
+
63
+ browser_path = formatted[:browser_path]
64
+ Platform.assert_executable(browser_path)
65
+ if @options.respond_to?(:binary) && @options.binary.nil?
66
+ @options.binary = browser_path
67
+ @options.browser_version = nil
68
+ end
69
+
63
70
  formatted
64
71
  end
65
72
  rescue StandardError => e
@@ -28,7 +28,7 @@ module Selenium
28
28
 
29
29
  class PointerCancel < Interaction
30
30
  def initialize(source)
31
- super(source)
31
+ super
32
32
  @type = :pointerCancel
33
33
  end
34
34
 
@@ -28,7 +28,7 @@ module Selenium
28
28
 
29
29
  class WheelInput < InputDevice
30
30
  def initialize(name = nil)
31
- super(name)
31
+ super
32
32
  @type = Interactions::WHEEL
33
33
  end
34
34
 
@@ -185,7 +185,7 @@ module Selenium
185
185
  logger.progname = name
186
186
  logger.level = level
187
187
  logger.formatter = proc do |severity, time, progname, msg|
188
- "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
188
+ "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n".force_encoding('UTF-8')
189
189
  end
190
190
 
191
191
  logger
@@ -0,0 +1,45 @@
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
+ class Script
23
+ def initialize(bridge)
24
+ @log_handler = BiDi::LogHandler.new(bridge.bidi)
25
+ end
26
+
27
+ # @return [int] id of the handler
28
+ def add_console_message_handler(&block)
29
+ @log_handler.add_message_handler('console', &block)
30
+ end
31
+
32
+ # @return [int] id of the handler
33
+ def add_javascript_error_handler(&block)
34
+ @log_handler.add_message_handler('javascript', &block)
35
+ end
36
+
37
+ # @param [int] id of the handler previously added
38
+ def remove_console_message_handler(id)
39
+ @log_handler.remove_message_handler(id)
40
+ end
41
+
42
+ alias remove_javascript_error_handler remove_console_message_handler
43
+ end # Script
44
+ end # WebDriver
45
+ end # Selenium
@@ -52,6 +52,18 @@ module Selenium
52
52
  @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] }
53
53
  end
54
54
 
55
+ def add_callback(event, &block)
56
+ callbacks[event] << block
57
+ block.object_id
58
+ end
59
+
60
+ def remove_callback(event, id)
61
+ return if callbacks[event].reject! { |callback| callback.object_id == id }
62
+
63
+ ids = callbacks[event]&.map(&:object_id)
64
+ raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}"
65
+ end
66
+
55
67
  def send_cmd(**payload)
56
68
  id = next_id
57
69
  data = payload.merge(id: id)
@@ -98,3 +98,4 @@ require 'selenium/webdriver/common/element'
98
98
  require 'selenium/webdriver/common/shadow_root'
99
99
  require 'selenium/webdriver/common/websocket_connection'
100
100
  require 'selenium/webdriver/common/child_process'
101
+ require 'selenium/webdriver/common/script'
@@ -64,6 +64,9 @@ module Selenium
64
64
 
65
65
  @options[:args] ||= []
66
66
  @options[:prefs] ||= {}
67
+ # Firefox 129 onwards the CDP protocol will not be enabled by default. Setting this preference will enable it.
68
+ # https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/.
69
+ @options[:prefs]['remote.active-protocols'] = 3
67
70
  @options[:env] ||= {}
68
71
  @options[:log] ||= {level: log_level} if log_level
69
72
 
@@ -42,7 +42,8 @@ module Selenium
42
42
  use_legacy_file_upload_dialog_handling: 'ie.useLegacyFileUploadDialogHandling',
43
43
  attach_to_edge_chrome: 'ie.edgechromium',
44
44
  edge_executable_path: 'ie.edgepath',
45
- ignore_process_match: 'ie.ignoreprocessmatch'
45
+ ignore_process_match: 'ie.ignoreprocessmatch',
46
+ silent: 'silent'
46
47
  }.freeze
47
48
  BROWSER = 'internet explorer'
48
49
 
@@ -81,7 +82,7 @@ module Selenium
81
82
 
82
83
  def initialize(**opts)
83
84
  @args = (opts.delete(:args) || []).to_set
84
- super(**opts)
85
+ super
85
86
 
86
87
  @options[:native_events] = true if @options[:native_events].nil?
87
88
  end
@@ -0,0 +1,44 @@
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
+ class BiDiBridge < Bridge
24
+ attr_reader :bidi
25
+
26
+ def create_session(capabilities)
27
+ super
28
+ socket_url = @capabilities[:web_socket_url]
29
+ @bidi = Selenium::WebDriver::BiDi.new(url: socket_url)
30
+ end
31
+
32
+ def quit
33
+ super
34
+ ensure
35
+ bidi.close
36
+ end
37
+
38
+ def close
39
+ execute(:close_window).tap { |handles| bidi.close if handles.empty? }
40
+ end
41
+ end # BiDiBridge
42
+ end # Remote
43
+ end # WebDriver
44
+ end # Selenium
@@ -602,6 +602,11 @@ module Selenium
602
602
  execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
603
603
  end
604
604
 
605
+ def bidi
606
+ msg = 'BiDi must be enabled by setting #web_socket_url to true in options class'
607
+ raise(WebDriver::Error::WebDriverError, msg)
608
+ end
609
+
605
610
  def command_list
606
611
  COMMANDS
607
612
  end
@@ -23,7 +23,7 @@ module Selenium
23
23
  class ServerError < StandardError
24
24
  def initialize(response)
25
25
  if response.is_a? String
26
- super(response)
26
+ super
27
27
  else
28
28
  super("status code #{response.code}; payload #{response.payload}")
29
29
  end
@@ -25,6 +25,7 @@ module Selenium
25
25
  module Remote
26
26
  autoload :Features, 'selenium/webdriver/remote/features'
27
27
  autoload :Bridge, 'selenium/webdriver/remote/bridge'
28
+ autoload :BiDiBridge, 'selenium/webdriver/remote/bidi_bridge'
28
29
  autoload :Driver, 'selenium/webdriver/remote/driver'
29
30
  autoload :Response, 'selenium/webdriver/remote/response'
30
31
  autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
@@ -27,7 +27,7 @@ module Selenium
27
27
  #
28
28
 
29
29
  class Guard
30
- attr_reader :guarded, :type, :messages, :reason
30
+ attr_reader :guarded, :type, :messages, :reason, :tracker
31
31
 
32
32
  def initialize(guarded, type, guards = nil)
33
33
  @guarded = guarded
@@ -36,22 +36,21 @@ module Selenium
36
36
  @messages[:unknown] = 'TODO: Investigate why this is failing and file a bug report'
37
37
  @type = type
38
38
 
39
- @reason = @guarded.delete(:reason)
39
+ @reason = @guarded[:reason] || 'No reason given'
40
+ @guarded[:reason] = @reason
40
41
  end
41
42
 
42
43
  def message
43
- details = case @reason
44
+ details = case reason
44
45
  when Integer
45
- "Bug Filed: #{@tracker}/#{@reason}"
46
+ "Bug Filed: #{tracker}/#{reason}"
46
47
  when Symbol
47
- @messages[@reason]
48
- when String
49
- @reason
48
+ messages[reason]
50
49
  else
51
- 'no reason given'
50
+ "Guarded by #{guarded};"
52
51
  end
53
52
 
54
- case @type
53
+ case type
55
54
  when :exclude
56
55
  "Test skipped because it breaks test run; #{details}"
57
56
  when :flaky
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.21.0'
22
+ VERSION = '4.22.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
48
48
  s.require_paths = ['lib']
49
49
 
50
50
  s.add_runtime_dependency 'base64', ['~> 0.2']
51
+ s.add_runtime_dependency 'logger', ['~> 1.4']
51
52
  s.add_runtime_dependency 'rexml', ['~> 3.2', '>= 3.2.5']
52
53
  s.add_runtime_dependency 'rubyzip', ['>= 1.2.2', '< 3.0']
53
54
  s.add_runtime_dependency 'websocket', ['~> 1.0']
@@ -58,6 +59,7 @@ Gem::Specification.new do |s|
58
59
  s.add_development_dependency 'rspec', ['~> 3.0']
59
60
  s.add_development_dependency 'rubocop', ['~> 1.60', '>=1.60.2']
60
61
  s.add_development_dependency 'rubocop-performance', ['~> 1.15']
62
+ s.add_development_dependency 'rubocop-rake', ['~> 0.6.0']
61
63
  s.add_development_dependency 'rubocop-rspec', ['~> 2.16']
62
64
  s.add_development_dependency 'webmock', ['~> 3.5']
63
65
  s.add_development_dependency 'webrick', ['~> 1.7']
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.21.0
4
+ version: 4.22.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: 2024-05-16 00:00:00.000000000 Z
13
+ date: 2024-06-20 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: base64
@@ -26,6 +26,20 @@ dependencies:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
28
  version: '0.2'
29
+ - !ruby/object:Gem::Dependency
30
+ name: logger
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '1.4'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '1.4'
29
43
  - !ruby/object:Gem::Dependency
30
44
  name: rexml
31
45
  requirement: !ruby/object:Gem::Requirement
@@ -170,6 +184,20 @@ dependencies:
170
184
  - - "~>"
171
185
  - !ruby/object:Gem::Version
172
186
  version: '1.15'
187
+ - !ruby/object:Gem::Dependency
188
+ name: rubocop-rake
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: 0.6.0
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: 0.6.0
173
201
  - !ruby/object:Gem::Dependency
174
202
  name: rubocop-rspec
175
203
  requirement: !ruby/object:Gem::Requirement
@@ -268,9 +296,11 @@ files:
268
296
  - lib/selenium/webdriver/bidi/log/filter_by.rb
269
297
  - lib/selenium/webdriver/bidi/log/generic_log_entry.rb
270
298
  - lib/selenium/webdriver/bidi/log/javascript_log_entry.rb
299
+ - lib/selenium/webdriver/bidi/log_handler.rb
271
300
  - lib/selenium/webdriver/bidi/log_inspector.rb
272
301
  - lib/selenium/webdriver/bidi/navigate_result.rb
273
302
  - lib/selenium/webdriver/bidi/session.rb
303
+ - lib/selenium/webdriver/bidi/struct.rb
274
304
  - lib/selenium/webdriver/chrome.rb
275
305
  - lib/selenium/webdriver/chrome/driver.rb
276
306
  - lib/selenium/webdriver/chrome/features.rb
@@ -347,6 +377,7 @@ files:
347
377
  - lib/selenium/webdriver/common/port_prober.rb
348
378
  - lib/selenium/webdriver/common/profile_helper.rb
349
379
  - lib/selenium/webdriver/common/proxy.rb
380
+ - lib/selenium/webdriver/common/script.rb
350
381
  - lib/selenium/webdriver/common/search_context.rb
351
382
  - lib/selenium/webdriver/common/selenium_manager.rb
352
383
  - lib/selenium/webdriver/common/service.rb
@@ -393,6 +424,7 @@ files:
393
424
  - lib/selenium/webdriver/ie/options.rb
394
425
  - lib/selenium/webdriver/ie/service.rb
395
426
  - lib/selenium/webdriver/remote.rb
427
+ - lib/selenium/webdriver/remote/bidi_bridge.rb
396
428
  - lib/selenium/webdriver/remote/bridge.rb
397
429
  - lib/selenium/webdriver/remote/bridge/commands.rb
398
430
  - lib/selenium/webdriver/remote/bridge/locator_converter.rb