selenium-webdriver 4.25.0 → 4.27.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +18 -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 +4 -2
  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 +7 -6
  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: 933e4204f7292ea54294b360eb588ee5ce965af527555629de203f11f6535931
4
- data.tar.gz: fb8f77b1b744c4e3f7922e66d9e956e41f4eba67181f0aa306ae8362730c1159
3
+ metadata.gz: 7809938337140c717243484ade299cbeef583af69e195bcaeef9b86b67ba2e40
4
+ data.tar.gz: 34eb5b08f76eb6c7b6966356ede4976e3eb392d9e03005b813bd65a7d1457647
5
5
  SHA512:
6
- metadata.gz: 1c4ca19d4a8dca6fb0dc25e4ebae8aea5e3d7dd5797977b53048b5a460e1d08c65b11e335789e43d93ff64d2ac2a31c077a2631cf01041874bb0e82845509c4a
7
- data.tar.gz: 1b3074dac91a3a612c64573218fb4accdc708dce7b78c31bfd8162575616da9c1cf9434463d45ef8d007fda7d28eee1d99d416f506a2c47e445f850e7a85a46d
6
+ metadata.gz: dc64c00f126d71a6cbc586123293bbae2d5f9d9c7af6b3aa2a6b001f0209be9f38fd6ef206ae9bdc069730c90f134bac91533600f4f7167c1ff93dd4a6ef35c6
7
+ data.tar.gz: 7dd948fd4f869958fe296ee7b0b1c7e593654e5b393707f7e50278ec978f0b9a566a16a3b860692add8bc751b02d2e38e2c758b4cdbabb8c97cca0ee21d1ec2e
data/CHANGES CHANGED
@@ -1,3 +1,21 @@
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
+
12
+ 4.26.0 (2024-10-28)
13
+ =========================
14
+ * Add CDP for Chrome 130 and remove 127
15
+ * Add missing RBS methods (#14621)
16
+ * Update Ruby BiDi script structs to match spec
17
+ * Add RBS type support for BiDi related classes (#14611)
18
+
1
19
  4.25.0 (2024-09-19)
2
20
  =========================
3
21
  * Add CDP for Chrome 129 and remove 126
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
@@ -21,8 +21,8 @@ module Selenium
21
21
  module WebDriver
22
22
  class BiDi
23
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)
24
+ ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source, :method, :args)
25
+ JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source)
26
26
 
27
27
  def initialize(bidi)
28
28
  @bidi = bidi
@@ -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.25.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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.25.0
4
+ version: 4.27.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-09-20 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,6 +466,7 @@ 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
+ funding_uri: https://github.com/sponsors/SeleniumHQ
469
470
  post_install_message:
470
471
  rdoc_options: []
471
472
  require_paths:
@@ -474,14 +475,14 @@ 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
+ rubygems_version: 3.3.27
485
486
  signing_key:
486
487
  specification_version: 4
487
488
  summary: Selenium is a browser automation tool for automated testing of webapps and
@@ -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