selenium-webdriver 4.26.0 → 4.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +11 -0
  3. data/Gemfile +1 -1
  4. data/README.md +1 -1
  5. data/bin/linux/selenium-manager +0 -0
  6. data/bin/macos/selenium-manager +0 -0
  7. data/bin/windows/selenium-manager.exe +0 -0
  8. data/lib/selenium/server.rb +3 -3
  9. data/lib/selenium/webdriver/bidi/browsing_context.rb +61 -49
  10. data/lib/selenium/webdriver/bidi/log_handler.rb +2 -0
  11. data/lib/selenium/webdriver/bidi/log_inspector.rb +4 -4
  12. data/lib/selenium/webdriver/bidi/network.rb +70 -0
  13. data/lib/selenium/webdriver/bidi/struct.rb +1 -3
  14. data/lib/selenium/webdriver/bidi.rb +3 -2
  15. data/lib/selenium/webdriver/common/child_process.rb +20 -14
  16. data/lib/selenium/webdriver/common/driver.rb +9 -0
  17. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +7 -0
  18. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +9 -2
  19. data/lib/selenium/webdriver/common/error.rb +3 -1
  20. data/lib/selenium/webdriver/common/fedcm/account.rb +2 -3
  21. data/lib/selenium/webdriver/common/logger.rb +1 -1
  22. data/lib/selenium/webdriver/{bidi/browsing_context_info.rb → common/network.rb} +27 -10
  23. data/lib/selenium/webdriver/common/script.rb +4 -4
  24. data/lib/selenium/webdriver/common/service_manager.rb +1 -0
  25. data/lib/selenium/webdriver/common/target_locator.rb +2 -0
  26. data/lib/selenium/webdriver/common.rb +1 -0
  27. data/lib/selenium/webdriver/remote/bidi_bridge.rb +22 -0
  28. data/lib/selenium/webdriver/remote/bridge.rb +3 -3
  29. data/lib/selenium/webdriver/remote/http/common.rb +2 -0
  30. data/lib/selenium/webdriver/support/guards.rb +2 -2
  31. data/lib/selenium/webdriver/version.rb +1 -1
  32. data/selenium-webdriver.gemspec +3 -2
  33. metadata +10 -9
  34. data/lib/selenium/webdriver/bidi/navigate_result.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7edc3571bd28b32bf23d755dc8386057ce7ee1072b70a3a2c673b3519acf5ee4
4
- data.tar.gz: ab849ea6ba3a5033ab1e33f2c241274cb892cdd33236e52f12ed8be7c6f2623f
3
+ metadata.gz: 7809938337140c717243484ade299cbeef583af69e195bcaeef9b86b67ba2e40
4
+ data.tar.gz: 34eb5b08f76eb6c7b6966356ede4976e3eb392d9e03005b813bd65a7d1457647
5
5
  SHA512:
6
- metadata.gz: c16d56af44cf4aea7a7988b975a8e7f23f04de2c1e81acf2593d6cc391deae93ca8501bb5523fb5b0df0781dc2e72be9667f4fd0b0bb90af52e9605959f2277b
7
- data.tar.gz: 16f14b892bb1e9578b7ba61c6fc049e2a27ec3ae8a728fbce2b212e51a0b85b29e741866acd8db6cfcc9e97e401f0d7af3aba78dec66628fab3ba9d3547e278d
6
+ metadata.gz: dc64c00f126d71a6cbc586123293bbae2d5f9d9c7af6b3aa2a6b001f0209be9f38fd6ef206ae9bdc069730c90f134bac91533600f4f7167c1ff93dd4a6ef35c6
7
+ data.tar.gz: 7dd948fd4f869958fe296ee7b0b1c7e593654e5b393707f7e50278ec978f0b9a566a16a3b860692add8bc751b02d2e38e2c758b4cdbabb8c97cca0ee21d1ec2e
data/CHANGES CHANGED
@@ -1,3 +1,14 @@
1
+ 4.27.0 (2024-11-21)
2
+ =========================
3
+ * Add CDP for Chrome 131 and remove 128
4
+ * Add Firefox CDP deprecation warnings (#14763)
5
+ * Add Bidi network commands for authentication and interception (#14523)
6
+ * Handle graceful webdriver shutdown (#14430)
7
+ * Reduce RBS errors to 0 (#14661)
8
+ * Resolve `uri` gem deprecation warning (#14770)
9
+ * Update minimum Ruby to 3.1 (#14685)
10
+ * Implement navigation commands with BiDi (#14094)
11
+
1
12
  4.26.0 (2024-10-28)
2
13
  =========================
3
14
  * Add CDP for Chrome 130 and remove 127
data/Gemfile CHANGED
@@ -7,4 +7,4 @@ end
7
7
 
8
8
  gem 'curb', '~> 1.0.5', require: false, platforms: %i[mri mingw x64_mingw]
9
9
  gem 'debug', '~> 1.7', require: false, platforms: %i[mri mingw x64_mingw]
10
- gem 'steep', '~> 1.5.0', require: false, platforms: %i[mri mingw x64_mingw]
10
+ gem 'steep', '1.5.2', require: false, platforms: %i[mri mingw x64_mingw]
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # selenium-webdriver
2
2
 
3
- This gem provides Ruby bindings for Selenium and supports MRI >= 3.0.
3
+ This gem provides Ruby bindings for Selenium and supports MRI >= 3.1.
4
4
 
5
5
  ## Install
6
6
 
Binary file
Binary file
Binary file
@@ -122,15 +122,15 @@ module Selenium
122
122
  end
123
123
  end
124
124
 
125
- def net_http_start(address, &block)
125
+ def net_http_start(address, &)
126
126
  http_proxy = ENV.fetch('http_proxy', nil) || ENV.fetch('HTTP_PROXY', nil)
127
127
  if http_proxy
128
128
  http_proxy = "http://#{http_proxy}" unless http_proxy.start_with?('http://')
129
129
  uri = URI.parse(http_proxy)
130
130
 
131
- Net::HTTP.start(address, nil, uri.host, uri.port, &block)
131
+ Net::HTTP.start(address, nil, uri.host, uri.port, &)
132
132
  else
133
- Net::HTTP.start(address, use_ssl: true, &block)
133
+ Net::HTTP.start(address, use_ssl: true, &)
134
134
  end
135
135
  end
136
136
 
@@ -17,72 +17,84 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require_relative 'navigate_result'
21
- require_relative 'browsing_context_info'
22
-
23
20
  module Selenium
24
21
  module WebDriver
25
22
  class BiDi
23
+ # Implements the browsingContext Module of the WebDriver-BiDi specification
24
+ #
25
+ # @api private
26
+ #
26
27
  class BrowsingContext
27
- attr_accessor :id
28
-
29
28
  READINESS_STATE = {
30
- none: 'none',
31
- interactive: 'interactive',
32
- complete: 'complete'
29
+ 'none' => 'none',
30
+ 'eager' => 'interactive',
31
+ 'normal' => 'complete'
33
32
  }.freeze
34
33
 
35
- def initialize(driver:, browsing_context_id: nil, type: nil, reference_context: nil)
36
- unless driver.capabilities.web_socket_url
37
- raise Error::WebDriverError,
38
- 'WebDriver instance must support BiDi protocol'
39
- end
40
-
41
- unless type.nil? || %i[window tab].include?(type)
42
- raise ArgumentError,
43
- "Valid types are :window & :tab. Received: #{type.inspect}"
44
- end
45
-
46
- @bidi = driver.bidi
47
- @id = browsing_context_id.nil? ? create(type, reference_context)['context'] : browsing_context_id
34
+ # TODO: store current window handle in bridge object instead of always calling it
35
+ def initialize(bridge)
36
+ @bridge = bridge
37
+ @bidi = @bridge.bidi
38
+ page_load_strategy = bridge.capabilities[:page_load_strategy]
39
+ @readiness = READINESS_STATE[page_load_strategy]
48
40
  end
49
41
 
50
- def navigate(url:, readiness_state: nil)
51
- unless readiness_state.nil? || READINESS_STATE.key?(readiness_state)
52
- raise ArgumentError,
53
- "Valid readiness states are :none, :interactive & :complete. Received: #{readiness_state.inspect}"
54
- end
55
-
56
- navigate_result = @bidi.send_cmd('browsingContext.navigate', context: @id, url: url,
57
- wait: READINESS_STATE[readiness_state])
58
-
59
- NavigateResult.new(
60
- url: navigate_result['url'],
61
- navigation_id: navigate_result['navigation']
62
- )
42
+ # Navigates to the specified URL in the given browsing context.
43
+ #
44
+ # @param url [String] The URL to navigate to.
45
+ # @param context_id [String, NilClass] The ID of the browsing context to navigate in.
46
+ # Defaults to the window handle of the current context.
47
+ def navigate(url, context_id: nil)
48
+ context_id ||= @bridge.window_handle
49
+ @bidi.send_cmd('browsingContext.navigate', context: context_id, url: url, wait: @readiness)
63
50
  end
64
51
 
65
- def get_tree(max_depth: nil)
66
- result = @bidi.send_cmd('browsingContext.getTree', root: @id, maxDepth: max_depth).dig('contexts', 0)
67
-
68
- BrowsingContextInfo.new(
69
- id: result['context'],
70
- url: result['url'],
71
- children: result['children'],
72
- parent_context: result['parent']
73
- )
52
+ # Traverses the browsing context history by a given delta.
53
+ #
54
+ # @param delta [Integer] The number of steps to traverse.
55
+ # Positive values go forwards, negative values go backwards.
56
+ # @param context_id [String, NilClass] The ID of the context to traverse.
57
+ # Defaults to the window handle of the current context.
58
+ def traverse_history(delta, context_id: nil)
59
+ context_id ||= @bridge.window_handle
60
+ @bidi.send_cmd('browsingContext.traverseHistory', context: context_id, delta: delta)
74
61
  end
75
62
 
76
- def close
77
- @bidi.send_cmd('browsingContext.close', context: @id)
63
+ # Reloads the browsing context.
64
+ # @param [String, NilClass] context_id The ID of the context to reload.
65
+ # Defaults to the window handle of the current context.
66
+ # @param [Boolean] ignore_cache Whether to bypass the cache when reloading.
67
+ # Defaults to false.
68
+ def reload(context_id: nil, ignore_cache: false)
69
+ context_id ||= @bridge.window_handle
70
+ params = {context: context_id, ignore_cache: ignore_cache, wait: @readiness}
71
+ @bidi.send_cmd('browsingContext.reload', **params)
78
72
  end
79
73
 
80
- private
74
+ # Closes the browsing context.
75
+ #
76
+ # @param [String] context_id The ID of the context to close.
77
+ # Defaults to the window handle of the current context.
78
+ def close(context_id: nil)
79
+ context_id ||= @bridge.window_handle
80
+ @bidi.send_cmd('browsingContext.close', context: context_id)
81
+ end
81
82
 
82
- def create(type, reference_context)
83
- @bidi.send_cmd('browsingContext.create', type: type.to_s, referenceContext: reference_context)
83
+ # Create a new browsing context.
84
+ #
85
+ # @param [Symbol] type The type of browsing context to create.
86
+ # Valid options are :tab and :window with :window being the default
87
+ # @param [String] context_id The reference context for the new browsing context.
88
+ # Defaults to the current window handle.
89
+ #
90
+ # @return [String] The context ID of the created browsing context.
91
+ def create(type: nil, context_id: nil)
92
+ type ||= :window
93
+ context_id ||= @bridge.window_handle
94
+ result = @bidi.send_cmd('browsingContext.create', type: type.to_s, referenceContext: context_id)
95
+ result['context']
84
96
  end
85
- end # BrowsingContext
97
+ end
86
98
  end # BiDi
87
99
  end # WebDriver
88
100
  end # Selenium
@@ -30,6 +30,7 @@ module Selenium
30
30
  end
31
31
 
32
32
  # @return [int] id of the handler
33
+ # steep:ignore:start
33
34
  def add_message_handler(type)
34
35
  subscribe_log_entry unless @log_entry_subscribed
35
36
  @bidi.add_callback('log.entryAdded') do |params|
@@ -39,6 +40,7 @@ module Selenium
39
40
  end
40
41
  end
41
42
  end
43
+ # steep:ignore:end
42
44
 
43
45
  # @param [int] id of the handler previously added
44
46
  def remove_message_handler(id)
@@ -79,7 +79,7 @@ module Selenium
79
79
  end
80
80
  end
81
81
 
82
- def on_log(filter_by = nil, &block)
82
+ def on_log(filter_by = nil, &)
83
83
  unless filter_by.nil?
84
84
  check_valid_filter(filter_by)
85
85
 
@@ -89,14 +89,14 @@ module Selenium
89
89
  return
90
90
  end
91
91
 
92
- on(:entry_added, &block)
92
+ on(:entry_added, &)
93
93
  end
94
94
 
95
95
  private
96
96
 
97
- def on(event, &block)
97
+ def on(event, &)
98
98
  event = EVENTS[event] if event.is_a?(Symbol)
99
- @bidi.add_callback("log.#{event}", &block)
99
+ @bidi.add_callback("log.#{event}", &)
100
100
  end
101
101
 
102
102
  def check_valid_filter(filter_by)
@@ -0,0 +1,70 @@
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 Network
24
+ EVENTS = {
25
+ before_request: 'network.beforeRequestSent',
26
+ response_started: 'network.responseStarted',
27
+ response_completed: 'network.responseCompleted',
28
+ auth_required: 'network.authRequired',
29
+ FETCH_ERROR: 'network.fetchError'
30
+ }.freeze
31
+
32
+ PHASES = {
33
+ before_request: 'beforeRequestSent',
34
+ response_started: 'responseStarted',
35
+ auth_required: 'authRequired'
36
+ }.freeze
37
+
38
+ def initialize(bidi)
39
+ @bidi = bidi
40
+ end
41
+
42
+ def add_intercept(phases: [], contexts: nil, url_patterns: nil)
43
+ @bidi.send_cmd('network.addIntercept', phases: phases, contexts: contexts, urlPatterns: url_patterns)
44
+ end
45
+
46
+ def remove_intercept(intercept)
47
+ @bidi.send_cmd('network.removeIntercept', intercept: intercept)
48
+ end
49
+
50
+ def continue_with_auth(request_id, username, password)
51
+ @bidi.send_cmd(
52
+ 'network.continueWithAuth',
53
+ 'request' => request_id,
54
+ 'action' => 'provideCredentials',
55
+ 'credentials' => {
56
+ 'type' => 'password',
57
+ 'username' => username,
58
+ 'password' => password
59
+ }
60
+ )
61
+ end
62
+
63
+ def on(event, &)
64
+ event = EVENTS[event] if event.is_a?(Symbol)
65
+ @bidi.add_callback(event, &)
66
+ end
67
+ end # Network
68
+ end # BiDi
69
+ end # WebDriver
70
+ end # Selenium
@@ -37,8 +37,6 @@ module Selenium
37
37
  end
38
38
  end
39
39
  end
40
- end
41
-
42
- # BiDi
40
+ end # BiDi
43
41
  end # WebDriver
44
42
  end # Selenium
@@ -25,6 +25,7 @@ module Selenium
25
25
  autoload :LogHandler, 'selenium/webdriver/bidi/log_handler'
26
26
  autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'
27
27
  autoload :Struct, 'selenium/webdriver/bidi/struct'
28
+ autoload :Network, 'selenium/webdriver/bidi/network'
28
29
 
29
30
  def initialize(url:)
30
31
  @ws = WebSocketConnection.new(url: url)
@@ -38,8 +39,8 @@ module Selenium
38
39
  @ws.callbacks
39
40
  end
40
41
 
41
- def add_callback(event, &block)
42
- @ws.add_callback(event, &block)
42
+ def add_callback(event, &)
43
+ @ws.add_callback(event, &)
43
44
  end
44
45
 
45
46
  def remove_callback(event, id)
@@ -64,16 +64,10 @@ module Selenium
64
64
  return unless @pid
65
65
  return if exited?
66
66
 
67
- WebDriver.logger.debug("Sending TERM to process: #{@pid}", id: :process)
68
- terminate(@pid)
69
- poll_for_exit(timeout)
70
-
71
- WebDriver.logger.debug(" -> stopped #{@pid}", id: :process)
72
- rescue TimeoutError, Errno::EINVAL
73
- WebDriver.logger.debug(" -> sending KILL to process: #{@pid}", id: :process)
74
- kill(@pid)
75
- wait
76
- WebDriver.logger.debug(" -> killed #{@pid}", id: :process)
67
+ terminate_and_wait_else_kill(timeout)
68
+ rescue Errno::ECHILD, Errno::ESRCH => e
69
+ # Process exited earlier than terminate/kill could catch
70
+ WebDriver.logger.debug(" -> process: #{@pid} does not exist (#{e.class.name})", id: :process)
77
71
  end
78
72
 
79
73
  def alive?
@@ -91,6 +85,9 @@ module Selenium
91
85
  WebDriver.logger.debug(" -> exit code is #{exit_code.inspect}", id: :process)
92
86
 
93
87
  !!exit_code
88
+ rescue Errno::ECHILD, Errno::ESRCH
89
+ WebDriver.logger.debug(" -> process: #{@pid} already finished", id: :process)
90
+ true
94
91
  end
95
92
 
96
93
  def poll_for_exit(timeout)
@@ -110,20 +107,29 @@ module Selenium
110
107
 
111
108
  private
112
109
 
110
+ def terminate_and_wait_else_kill(timeout)
111
+ WebDriver.logger.debug("Sending TERM to process: #{@pid}", id: :process)
112
+ terminate(@pid)
113
+ poll_for_exit(timeout)
114
+
115
+ WebDriver.logger.debug(" -> stopped #{@pid}", id: :process)
116
+ rescue TimeoutError, Errno::EINVAL
117
+ WebDriver.logger.debug(" -> sending KILL to process: #{@pid}", id: :process)
118
+ kill(@pid)
119
+ wait
120
+ WebDriver.logger.debug(" -> killed #{@pid}", id: :process)
121
+ end
122
+
113
123
  def terminate(pid)
114
124
  Process.kill(SIGTERM, pid)
115
125
  end
116
126
 
117
127
  def kill(pid)
118
128
  Process.kill(SIGKILL, pid)
119
- rescue Errno::ECHILD, Errno::ESRCH
120
- # already dead
121
129
  end
122
130
 
123
131
  def waitpid2(pid, flags = 0)
124
132
  Process.waitpid2(pid, flags)
125
- rescue Errno::ECHILD
126
- # already dead
127
133
  end
128
134
  end # ChildProcess
129
135
  end # WebDriver
@@ -264,6 +264,15 @@ module Selenium
264
264
  bridge.add_virtual_authenticator(options)
265
265
  end
266
266
 
267
+ #
268
+ # @return [Network]
269
+ # @see Network
270
+ #
271
+
272
+ def network
273
+ @network ||= WebDriver::Network.new(bridge)
274
+ end
275
+
267
276
  #-------------------------------- sugar --------------------------------
268
277
 
269
278
  #
@@ -57,6 +57,13 @@ module Selenium
57
57
  #
58
58
 
59
59
  def on_log_event(kind, &block)
60
+ if browser == :firefox
61
+ WebDriver.logger.deprecate(
62
+ 'Driver#on_log_event on Firefox',
63
+ 'the script.add_console_message_handler or the script.add_javascript_error_handler methods',
64
+ id: :on_log_event
65
+ )
66
+ end
60
67
  raise Error::WebDriverError, "Don't know how to handle #{kind} events" unless KINDS.include?(kind)
61
68
 
62
69
  enabled = log_listeners[kind].any?
@@ -59,9 +59,16 @@ module Selenium
59
59
  # @yieldparam [Proc] continue block which proceeds with the request and optionally yields response
60
60
  #
61
61
 
62
- def intercept(&block)
62
+ def intercept(&)
63
+ if browser == :firefox
64
+ WebDriver.logger.deprecate(
65
+ 'Driver#intercept on Firefox',
66
+ 'the new bidi.network.add_intercept method',
67
+ id: :intercept
68
+ )
69
+ end
63
70
  @interceptor ||= DevTools::NetworkInterceptor.new(devtools)
64
- @interceptor.intercept(&block)
71
+ @interceptor.intercept(&)
65
72
  end
66
73
  end # HasNetworkInterception
67
74
  end # DriverExtensions
@@ -50,9 +50,11 @@ module Selenium
50
50
  super(URLS[class_name] ? "#{msg}; #{SUPPORT_MSG} #{URLS[class_name]}" : msg)
51
51
  end
52
52
 
53
+ # steep:ignore:start
53
54
  def class_name
54
- self.class.name&.split('::')&.last&.to_sym
55
+ self.class.name.split('::')&.last&.to_sym
55
56
  end
57
+ # steep:ignore:end
56
58
  end
57
59
 
58
60
  #
@@ -30,9 +30,7 @@ module Selenium
30
30
  attr_reader :account_id, :email, :name, :given_name, :picture_url,
31
31
  :idp_config_url, :login_state, :terms_of_service_url, :privacy_policy_url
32
32
 
33
- # Initializes a new account with the provided attributes.
34
- #
35
- # @param [Hash]
33
+ # steep:ignore:start
36
34
  def initialize(**args)
37
35
  @account_id = args['accountId']
38
36
  @email = args['email']
@@ -44,6 +42,7 @@ module Selenium
44
42
  @terms_of_service_url = args['termsOfServiceUrl']
45
43
  @privacy_policy_url = args['privacyPolicyUrl']
46
44
  end
45
+ # steep:ignore:end
47
46
  end # Account
48
47
  end # FedCM
49
48
  end # WebDriver
@@ -193,7 +193,7 @@ module Selenium
193
193
 
194
194
  def discard_or_log(level, message, id)
195
195
  id = Array(id)
196
- return if (@ignored & id).any?
196
+ return if @ignored.intersect?(id)
197
197
  return if @allowed.any? && (@allowed & id).none?
198
198
 
199
199
  return if ::Logger::Severity.const_get(level.upcase) < @logger.level
@@ -19,17 +19,34 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- class BiDi
23
- class BrowsingContextInfo
24
- attr_accessor :id, :url, :children, :parent_browsing_context
22
+ class Network
23
+ attr_reader :auth_callbacks
25
24
 
26
- def initialize(id:, url:, children:, parent_context:)
27
- @id = id
28
- @url = url
29
- @children = children
30
- @parent_browsing_context = parent_context
25
+ def initialize(bridge)
26
+ @network = BiDi::Network.new(bridge.bidi)
27
+ @auth_callbacks = {}
28
+ end
29
+
30
+ def add_authentication_handler(username, password)
31
+ intercept = @network.add_intercept(phases: [BiDi::Network::PHASES[:auth_required]])
32
+ auth_id = @network.on(:auth_required) do |event|
33
+ request_id = event['requestId']
34
+ @network.continue_with_auth(request_id, username, password)
31
35
  end
32
- end # BrowsingContextInfo
33
- end # BiDi
36
+ @auth_callbacks[auth_id] = intercept
37
+
38
+ auth_id
39
+ end
40
+
41
+ def remove_authentication_handler(id)
42
+ intercept = @auth_callbacks[id]
43
+ @network.remove_intercept(intercept['intercept'])
44
+ @auth_callbacks.delete(id)
45
+ end
46
+
47
+ def clear_authentication_handlers
48
+ @auth_callbacks.each_key { |id| remove_authentication_handler(id) }
49
+ end
50
+ end # Network
34
51
  end # WebDriver
35
52
  end # Selenium
@@ -25,13 +25,13 @@ module Selenium
25
25
  end
26
26
 
27
27
  # @return [int] id of the handler
28
- def add_console_message_handler(&block)
29
- @log_handler.add_message_handler('console', &block)
28
+ def add_console_message_handler(&)
29
+ @log_handler.add_message_handler('console', &)
30
30
  end
31
31
 
32
32
  # @return [int] id of the handler
33
- def add_javascript_error_handler(&block)
34
- @log_handler.add_message_handler('javascript', &block)
33
+ def add_javascript_error_handler(&)
34
+ @log_handler.add_message_handler('javascript', &)
35
35
  end
36
36
 
37
37
  # @param [int] id of the handler previously added
@@ -113,6 +113,7 @@ module Selenium
113
113
  def stop_server
114
114
  connect_to_server do |http|
115
115
  headers = WebDriver::Remote::Http::Common::DEFAULT_HEADERS.dup
116
+ WebDriver.logger.debug('Sending shutdown request to server', id: :driver_service)
116
117
  http.get('/shutdown', headers)
117
118
  end
118
119
  end
@@ -50,6 +50,7 @@ module Selenium
50
50
  # @param type either :tab or :window
51
51
  #
52
52
 
53
+ # steep:ignore:start
53
54
  def new_window(type = :window)
54
55
  raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}" unless %i[window
55
56
  tab].include?(type)
@@ -70,6 +71,7 @@ module Selenium
70
71
  window(handle)
71
72
  end
72
73
  end
74
+ # steep:ignore:end
73
75
 
74
76
  #
75
77
  # switch to the given window handle
@@ -102,3 +102,4 @@ require 'selenium/webdriver/common/child_process'
102
102
  require 'selenium/webdriver/common/script'
103
103
  require 'selenium/webdriver/common/fedcm/account'
104
104
  require 'selenium/webdriver/common/fedcm/dialog'
105
+ require 'selenium/webdriver/common/network'
@@ -29,6 +29,22 @@ module Selenium
29
29
  @bidi = Selenium::WebDriver::BiDi.new(url: socket_url)
30
30
  end
31
31
 
32
+ def get(url)
33
+ browsing_context.navigate(url)
34
+ end
35
+
36
+ def go_back
37
+ browsing_context.traverse_history(-1)
38
+ end
39
+
40
+ def go_forward
41
+ browsing_context.traverse_history(1)
42
+ end
43
+
44
+ def refresh
45
+ browsing_context.reload
46
+ end
47
+
32
48
  def quit
33
49
  super
34
50
  ensure
@@ -38,6 +54,12 @@ module Selenium
38
54
  def close
39
55
  execute(:close_window).tap { |handles| bidi.close if handles.empty? }
40
56
  end
57
+
58
+ private
59
+
60
+ def browsing_context
61
+ @browsing_context ||= WebDriver::BiDi::BrowsingContext.new(self)
62
+ end
41
63
  end # BiDiBridge
42
64
  end # Remote
43
65
  end # WebDriver
@@ -35,10 +35,10 @@ module Selenium
35
35
  attr_reader :extra_commands
36
36
  attr_writer :element_class, :locator_converter
37
37
 
38
- def add_command(name, verb, url, &block)
38
+ def add_command(name, verb, url, &)
39
39
  @extra_commands ||= {}
40
40
  @extra_commands[name] = [verb, url]
41
- define_method(name, &block)
41
+ define_method(name, &)
42
42
  end
43
43
 
44
44
  def locator_converter
@@ -686,7 +686,7 @@ module Selenium
686
686
  end
687
687
 
688
688
  def escaper
689
- @escaper ||= defined?(URI::Parser) ? URI::DEFAULT_PARSER : URI
689
+ @escaper ||= defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
690
690
  end
691
691
 
692
692
  def commands(command)
@@ -48,6 +48,7 @@ module Selenium
48
48
  # hook for subclasses - will be called on Driver#quit
49
49
  end
50
50
 
51
+ # steep:ignore:start
51
52
  def call(verb, url, command_hash)
52
53
  url = server_url.merge(url) unless url.is_a?(URI)
53
54
  headers = common_headers.dup
@@ -66,6 +67,7 @@ module Selenium
66
67
 
67
68
  request verb, url, headers, payload
68
69
  end
70
+ # steep:ignore:end
69
71
 
70
72
  private
71
73
 
@@ -37,8 +37,8 @@ module Selenium
37
37
  @messages = {}
38
38
  end
39
39
 
40
- def add_condition(name, condition = nil, &blk)
41
- @guard_conditions << GuardCondition.new(name, condition, &blk)
40
+ def add_condition(name, condition = nil, &)
41
+ @guard_conditions << GuardCondition.new(name, condition, &)
42
42
  end
43
43
 
44
44
  def add_message(name, message)
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.26.0'
22
+ VERSION = '4.27.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -24,11 +24,12 @@ Gem::Specification.new do |s|
24
24
  'changelog_uri' => 'https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES',
25
25
  'github_repo' => 'ssh://github.com/SeleniumHQ/selenium',
26
26
  'source_code_uri' => 'https://github.com/SeleniumHQ/selenium/tree/trunk/rb',
27
- 'rubygems_mfa_required' => 'true'
27
+ 'rubygems_mfa_required' => 'true',
28
+ 'funding_uri' => 'https://github.com/sponsors/SeleniumHQ'
28
29
  }
29
30
 
30
31
  s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
31
- s.required_ruby_version = Gem::Requirement.new('>= 3.0')
32
+ s.required_ruby_version = Gem::Requirement.new('>= 3.1')
32
33
 
33
34
  s.files = [
34
35
  'CHANGES',
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.26.0
4
+ version: 4.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rodionov
8
8
  - Titus Fortner
9
9
  - Thomas Walpole
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-10-30 00:00:00.000000000 Z
13
+ date: 2024-11-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: base64
@@ -290,7 +290,6 @@ files:
290
290
  - lib/selenium/webdriver/atoms/mutationListener.js
291
291
  - lib/selenium/webdriver/bidi.rb
292
292
  - lib/selenium/webdriver/bidi/browsing_context.rb
293
- - lib/selenium/webdriver/bidi/browsing_context_info.rb
294
293
  - lib/selenium/webdriver/bidi/log/base_log_entry.rb
295
294
  - lib/selenium/webdriver/bidi/log/console_log_entry.rb
296
295
  - lib/selenium/webdriver/bidi/log/filter_by.rb
@@ -298,7 +297,7 @@ files:
298
297
  - lib/selenium/webdriver/bidi/log/javascript_log_entry.rb
299
298
  - lib/selenium/webdriver/bidi/log_handler.rb
300
299
  - lib/selenium/webdriver/bidi/log_inspector.rb
301
- - lib/selenium/webdriver/bidi/navigate_result.rb
300
+ - lib/selenium/webdriver/bidi/network.rb
302
301
  - lib/selenium/webdriver/bidi/session.rb
303
302
  - lib/selenium/webdriver/bidi/struct.rb
304
303
  - lib/selenium/webdriver/chrome.rb
@@ -376,6 +375,7 @@ files:
376
375
  - lib/selenium/webdriver/common/logs.rb
377
376
  - lib/selenium/webdriver/common/manager.rb
378
377
  - lib/selenium/webdriver/common/navigation.rb
378
+ - lib/selenium/webdriver/common/network.rb
379
379
  - lib/selenium/webdriver/common/options.rb
380
380
  - lib/selenium/webdriver/common/platform.rb
381
381
  - lib/selenium/webdriver/common/port_prober.rb
@@ -466,7 +466,8 @@ metadata:
466
466
  github_repo: ssh://github.com/SeleniumHQ/selenium
467
467
  source_code_uri: https://github.com/SeleniumHQ/selenium/tree/trunk/rb
468
468
  rubygems_mfa_required: 'true'
469
- post_install_message:
469
+ funding_uri: https://github.com/sponsors/SeleniumHQ
470
+ post_install_message:
470
471
  rdoc_options: []
471
472
  require_paths:
472
473
  - lib
@@ -474,15 +475,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
474
475
  requirements:
475
476
  - - ">="
476
477
  - !ruby/object:Gem::Version
477
- version: '3.0'
478
+ version: '3.1'
478
479
  required_rubygems_version: !ruby/object:Gem::Requirement
479
480
  requirements:
480
481
  - - ">"
481
482
  - !ruby/object:Gem::Version
482
483
  version: 1.3.1
483
484
  requirements: []
484
- rubygems_version: 3.2.33
485
- signing_key:
485
+ rubygems_version: 3.3.27
486
+ signing_key:
486
487
  specification_version: 4
487
488
  summary: Selenium is a browser automation tool for automated testing of webapps and
488
489
  more
@@ -1,33 +0,0 @@
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 NavigateResult
24
- attr_accessor :url, :navigation_id
25
-
26
- def initialize(url:, navigation_id:)
27
- @url = url
28
- @navigation_id = navigation_id
29
- end
30
- end # NavigateResult
31
- end # BiDi
32
- end # WebDriver
33
- end # Selenium