selenium-webdriver 4.27.0 → 4.32.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +61 -0
  3. data/Gemfile +3 -1
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/bin/linux/selenium-manager +0 -0
  7. data/bin/macos/selenium-manager +0 -0
  8. data/bin/windows/selenium-manager.exe +0 -0
  9. data/lib/selenium/server.rb +4 -4
  10. data/lib/selenium/webdriver/atoms/findElements.js +50 -118
  11. data/lib/selenium/webdriver/atoms/getAttribute.js +1 -1
  12. data/lib/selenium/webdriver/atoms/isDisplayed.js +1 -1
  13. data/lib/selenium/webdriver/bidi/browsing_context.rb +15 -0
  14. data/lib/selenium/webdriver/bidi/log_inspector.rb +4 -4
  15. data/lib/selenium/webdriver/{common/html5/session_storage.rb → bidi/network/cookies.rb} +11 -34
  16. data/lib/selenium/webdriver/{common/html5/local_storage.rb → bidi/network/credentials.rb} +15 -31
  17. data/lib/selenium/webdriver/bidi/network/headers.rb +38 -0
  18. data/lib/selenium/webdriver/{common/html5/shared_web_storage.rb → bidi/network/intercepted_auth.rb} +10 -25
  19. data/lib/selenium/webdriver/{common/driver_extensions/has_web_storage.rb → bidi/network/intercepted_item.rb} +10 -11
  20. data/lib/selenium/webdriver/bidi/network/intercepted_request.rb +69 -0
  21. data/lib/selenium/webdriver/bidi/network/intercepted_response.rb +81 -0
  22. data/lib/selenium/webdriver/bidi/network/url_pattern.rb +65 -0
  23. data/lib/selenium/webdriver/bidi/network.rb +80 -11
  24. data/lib/selenium/webdriver/bidi/struct.rb +1 -1
  25. data/lib/selenium/webdriver/bidi.rb +6 -2
  26. data/lib/selenium/webdriver/chromium/driver.rb +0 -1
  27. data/lib/selenium/webdriver/common/driver.rb +3 -10
  28. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +4 -3
  29. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -2
  30. data/lib/selenium/webdriver/common/logger.rb +1 -1
  31. data/lib/selenium/webdriver/common/manager.rb +1 -1
  32. data/lib/selenium/webdriver/common/network.rb +66 -16
  33. data/lib/selenium/webdriver/common/options.rb +1 -1
  34. data/lib/selenium/webdriver/common/print_options.rb +93 -0
  35. data/lib/selenium/webdriver/common/script.rb +4 -4
  36. data/lib/selenium/webdriver/common/selenium_manager.rb +36 -17
  37. data/lib/selenium/webdriver/common/takes_screenshot.rb +1 -0
  38. data/lib/selenium/webdriver/common.rb +1 -4
  39. data/lib/selenium/webdriver/devtools.rb +7 -5
  40. data/lib/selenium/webdriver/firefox/driver.rb +0 -19
  41. data/lib/selenium/webdriver/firefox/options.rb +2 -2
  42. data/lib/selenium/webdriver/firefox/service.rb +9 -0
  43. data/lib/selenium/webdriver/ie/driver.rb +1 -1
  44. data/lib/selenium/webdriver/remote/bridge.rb +4 -64
  45. data/lib/selenium/webdriver/safari/driver.rb +1 -2
  46. data/lib/selenium/webdriver/support/guards.rb +4 -2
  47. data/lib/selenium/webdriver/version.rb +1 -1
  48. data/selenium-webdriver.gemspec +5 -4
  49. metadata +20 -20
@@ -27,12 +27,13 @@ module Selenium
27
27
  # @return [DevTools]
28
28
  #
29
29
 
30
- def devtools
31
- @devtools ||= begin
30
+ def devtools(target_type: 'page')
31
+ @devtools ||= {}
32
+ @devtools[target_type] ||= begin
32
33
  require 'selenium/devtools'
33
34
  Selenium::DevTools.version ||= devtools_version
34
35
  Selenium::DevTools.load_version
35
- Selenium::WebDriver::DevTools.new(url: devtools_url)
36
+ Selenium::WebDriver::DevTools.new(url: devtools_url, target_type: target_type)
36
37
  end
37
38
  end
38
39
  end # HasDevTools
@@ -59,7 +59,7 @@ module Selenium
59
59
  # @yieldparam [Proc] continue block which proceeds with the request and optionally yields response
60
60
  #
61
61
 
62
- def intercept(&)
62
+ def intercept(&block)
63
63
  if browser == :firefox
64
64
  WebDriver.logger.deprecate(
65
65
  'Driver#intercept on Firefox',
@@ -68,7 +68,7 @@ module Selenium
68
68
  )
69
69
  end
70
70
  @interceptor ||= DevTools::NetworkInterceptor.new(devtools)
71
- @interceptor.intercept(&)
71
+ @interceptor.intercept(&block)
72
72
  end
73
73
  end # HasNetworkInterception
74
74
  end # DriverExtensions
@@ -194,7 +194,7 @@ module Selenium
194
194
  def discard_or_log(level, message, id)
195
195
  id = Array(id)
196
196
  return if @ignored.intersect?(id)
197
- return if @allowed.any? && (@allowed & id).none?
197
+ return if @allowed.any? && !@allowed.intersect?(id)
198
198
 
199
199
  return if ::Logger::Severity.const_get(level.upcase) < @logger.level
200
200
 
@@ -65,7 +65,7 @@ module Selenium
65
65
  # Get the cookie with the given name
66
66
  #
67
67
  # @param [String] name the name of the cookie
68
- # @return [Hash, nil] the cookie, or nil if it wasn't found.
68
+ # @return [Hash] the cookie, or throws a NoSuchCookieError if it wasn't found.
69
69
  #
70
70
 
71
71
  def cookie_named(name)
@@ -17,35 +17,85 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'forwardable'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  class Network
23
- attr_reader :auth_callbacks
25
+ extend Forwardable
26
+
27
+ attr_reader :callbacks, :network
28
+ alias bidi network
29
+
30
+ def_delegators :network, :continue_with_auth, :continue_with_request, :continue_with_response
24
31
 
25
32
  def initialize(bridge)
26
33
  @network = BiDi::Network.new(bridge.bidi)
27
- @auth_callbacks = {}
34
+ @callbacks = {}
28
35
  end
29
36
 
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)
35
- end
36
- @auth_callbacks[auth_id] = intercept
37
+ def remove_handler(id)
38
+ intercept = callbacks[id]
39
+ network.remove_intercept(intercept['intercept'])
40
+ callbacks.delete(id)
41
+ end
37
42
 
38
- auth_id
43
+ def clear_handlers
44
+ callbacks.each_key { |id| remove_handler(id) }
39
45
  end
40
46
 
41
- def remove_authentication_handler(id)
42
- intercept = @auth_callbacks[id]
43
- @network.remove_intercept(intercept['intercept'])
44
- @auth_callbacks.delete(id)
47
+ def add_authentication_handler(username = nil, password = nil, *filter, pattern_type: nil, &block)
48
+ selected_block =
49
+ if username && password
50
+ proc { |auth| auth.authenticate(username, password) }
51
+ else
52
+ block
53
+ end
54
+
55
+ add_handler(
56
+ :auth_required,
57
+ BiDi::Network::PHASES[:auth_required],
58
+ BiDi::InterceptedAuth,
59
+ filter,
60
+ pattern_type: pattern_type,
61
+ &selected_block
62
+ )
45
63
  end
46
64
 
47
- def clear_authentication_handlers
48
- @auth_callbacks.each_key { |id| remove_authentication_handler(id) }
65
+ def add_request_handler(*filter, pattern_type: nil, &block)
66
+ add_handler(
67
+ :before_request,
68
+ BiDi::Network::PHASES[:before_request],
69
+ BiDi::InterceptedRequest,
70
+ filter,
71
+ pattern_type: pattern_type,
72
+ &block
73
+ )
74
+ end
75
+
76
+ def add_response_handler(*filter, pattern_type: nil, &block)
77
+ add_handler(
78
+ :response_started,
79
+ BiDi::Network::PHASES[:response_started],
80
+ BiDi::InterceptedResponse,
81
+ filter,
82
+ pattern_type: pattern_type,
83
+ &block
84
+ )
85
+ end
86
+
87
+ private
88
+
89
+ def add_handler(event_type, phase, intercept_type, filter, pattern_type: nil)
90
+ intercept = network.add_intercept(phases: [phase], url_patterns: [filter].flatten, pattern_type: pattern_type)
91
+ callback_id = network.on(event_type) do |event|
92
+ request = event['request']
93
+ intercepted_item = intercept_type.new(network, request)
94
+ yield(intercepted_item)
95
+ end
96
+
97
+ callbacks[callback_id] = intercept
98
+ callback_id
49
99
  end
50
100
  end # Network
51
101
  end # WebDriver
@@ -52,7 +52,7 @@ module Selenium
52
52
  end
53
53
 
54
54
  def set_capabilities
55
- (W3C_OPTIONS + self::CAPABILITIES.keys).each do |key|
55
+ (W3C_OPTIONS + GRID_OPTIONS + self::CAPABILITIES.keys).each do |key|
56
56
  next if method_defined? key
57
57
 
58
58
  define_method key do
@@ -0,0 +1,93 @@
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
+ # Represents options for printing a page.
23
+ class PrintOptions
24
+ DEFAULT_SCALE = 1.0
25
+ DEFAULT_ORIENTATION = 'portrait'
26
+ DEFAULT_PAGE_SIZE = {width: 21.0, height: 29.7}.freeze # A4 size in cm
27
+ DEFAULT_MARGINS = {top: 1.0, bottom: 1.0, left: 1.0, right: 1.0}.freeze
28
+
29
+ attr_accessor :orientation, :scale, :background, :page_ranges, :margins
30
+
31
+ def initialize
32
+ @orientation = DEFAULT_ORIENTATION
33
+ @scale = DEFAULT_SCALE
34
+ @background = false
35
+ @page_ranges = nil
36
+ @page_size = DEFAULT_PAGE_SIZE
37
+ @margins = DEFAULT_MARGINS
38
+ end
39
+
40
+ # Converts the options to a hash format to be used by WebDriver.
41
+ #
42
+ # @return [Hash]
43
+ def to_h
44
+ options = {
45
+ orientation: @orientation,
46
+ scale: @scale,
47
+ background: @background,
48
+ pageRanges: @page_ranges,
49
+ paperWidth: @page_size[:width],
50
+ paperHeight: @page_size[:height],
51
+ marginTop: @margins[:top],
52
+ marginBottom: @margins[:bottom],
53
+ marginLeft: @margins[:left],
54
+ marginRight: @margins[:right]
55
+ }
56
+
57
+ options.compact
58
+ end
59
+
60
+ # Gets the current page size.
61
+ #
62
+ # @return [Hash] The current page size hash with :width and :height.
63
+ attr_reader :page_size
64
+
65
+ # Sets the page size. Can be a predefined symbol or custom size hash.
66
+ #
67
+ # @param [Symbol, Hash] value The predefined size (:letter, :legal, :a4, :tabloid) or a custom hash.
68
+ def page_size=(value)
69
+ predefined_sizes = {
70
+ letter: {width: 21.59, height: 27.94},
71
+ legal: {width: 21.59, height: 35.56},
72
+ a4: {width: 21.0, height: 29.7},
73
+ tabloid: {width: 27.94, height: 43.18}
74
+ }
75
+
76
+ case value
77
+ when Symbol
78
+ raise ArgumentError, "Invalid page size: #{value}" unless predefined_sizes.key?(value)
79
+
80
+ @page_size = predefined_sizes[value]
81
+ when Hash
82
+ unless value.key?(:width) && value.key?(:height)
83
+ raise ArgumentError, 'Custom page size must include :width and :height'
84
+ end
85
+
86
+ @page_size = value
87
+ else
88
+ raise ArgumentError, 'Page size must be a Symbol or a Hash'
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -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(&)
29
- @log_handler.add_message_handler('console', &)
28
+ def add_console_message_handler(&block)
29
+ @log_handler.add_message_handler('console', &block)
30
30
  end
31
31
 
32
32
  # @return [int] id of the handler
33
- def add_javascript_error_handler(&)
34
- @log_handler.add_message_handler('javascript', &)
33
+ def add_javascript_error_handler(&block)
34
+ @log_handler.add_message_handler('javascript', &block)
35
35
  end
36
36
 
37
37
  # @param [int] id of the handler previously added
@@ -61,25 +61,12 @@ module Selenium
61
61
  end
62
62
 
63
63
  def run(*command)
64
- WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
65
-
66
- begin
67
- stdout, stderr, status = Open3.capture3(*command)
68
- rescue StandardError => e
69
- raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
70
- end
64
+ stdout, stderr, status = execute_command(*command)
65
+ result = parse_result_and_log(stdout)
71
66
 
72
- json_output = stdout.empty? ? {'logs' => [], 'result' => {}} : JSON.parse(stdout)
73
- json_output['logs'].each do |log|
74
- level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
75
- WebDriver.logger.send(level, log['message'], id: :selenium_manager)
76
- end
67
+ validate_command_result(command, status, result, stderr)
77
68
 
78
- result = json_output['result']
79
- return result unless status.exitstatus.positive? || result.nil?
80
-
81
- raise Error::WebDriverError,
82
- "Unsuccessful command executed: #{command} - Code #{status.exitstatus}\n#{result}\n#{stderr}"
69
+ result
83
70
  end
84
71
 
85
72
  def platform_location
@@ -98,6 +85,38 @@ module Selenium
98
85
  raise Error::WebDriverError, "unsupported platform: #{Platform.os}"
99
86
  end
100
87
  end
88
+
89
+ def execute_command(*command)
90
+ WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
91
+
92
+ Open3.capture3(*command)
93
+ rescue StandardError => e
94
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
95
+ end
96
+
97
+ def parse_result_and_log(stdout)
98
+ json_output = stdout.empty? ? {'logs' => [], 'result' => {}} : JSON.parse(stdout)
99
+
100
+ json_output['logs'].each do |log|
101
+ level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
102
+ WebDriver.logger.send(level, log['message'], id: :selenium_manager)
103
+ end
104
+
105
+ json_output['result']
106
+ end
107
+
108
+ def validate_command_result(command, status, result, stderr)
109
+ if status.nil? || status.exitstatus.nil?
110
+ WebDriver.logger.info("No exit status for: #{command}. Assuming success if result is present.",
111
+ id: :selenium_manager)
112
+ end
113
+
114
+ return unless status&.exitstatus&.positive? || result.nil?
115
+
116
+ code = status&.exitstatus || 'exit status not available'
117
+ raise Error::WebDriverError,
118
+ "Unsuccessful command executed: #{command} - Code #{code}\n#{result}\n#{stderr}"
119
+ end
101
120
  end
102
121
  end # SeleniumManager
103
122
  end # WebDriver
@@ -36,6 +36,7 @@ module Selenium
36
36
  'It should end with .png extension',
37
37
  id: :screenshot
38
38
  end
39
+ WebDriver.logger.debug("Saving screenshot to #{Dir.pwd}/#{png_path}")
39
40
  File.open(png_path, 'wb') { |f| f << screenshot_as(:png, full_page: full_page) }
40
41
  end
41
42
 
@@ -63,10 +63,6 @@ require 'selenium/webdriver/common/action_builder'
63
63
  require 'selenium/webdriver/common/virtual_authenticator/credential'
64
64
  require 'selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options'
65
65
  require 'selenium/webdriver/common/virtual_authenticator/virtual_authenticator'
66
- require 'selenium/webdriver/common/html5/shared_web_storage'
67
- require 'selenium/webdriver/common/html5/local_storage'
68
- require 'selenium/webdriver/common/html5/session_storage'
69
- require 'selenium/webdriver/common/driver_extensions/has_web_storage'
70
66
  require 'selenium/webdriver/common/driver_extensions/downloads_files'
71
67
  require 'selenium/webdriver/common/driver_extensions/has_session_id'
72
68
  require 'selenium/webdriver/common/driver_extensions/has_network_conditions'
@@ -91,6 +87,7 @@ require 'selenium/webdriver/common/driver_extensions/has_casting'
91
87
  require 'selenium/webdriver/common/driver_extensions/has_launching'
92
88
  require 'selenium/webdriver/common/driver_extensions/has_fedcm_dialog'
93
89
  require 'selenium/webdriver/common/keys'
90
+ require 'selenium/webdriver/common/print_options'
94
91
  require 'selenium/webdriver/common/profile_helper'
95
92
  require 'selenium/webdriver/common/options'
96
93
  require 'selenium/webdriver/common/takes_screenshot'
@@ -28,10 +28,10 @@ module Selenium
28
28
  autoload :Request, 'selenium/webdriver/devtools/request'
29
29
  autoload :Response, 'selenium/webdriver/devtools/response'
30
30
 
31
- def initialize(url:)
31
+ def initialize(url:, target_type:)
32
32
  @ws = WebSocketConnection.new(url: url)
33
33
  @session_id = nil
34
- start_session
34
+ start_session(target_type: target_type)
35
35
  end
36
36
 
37
37
  def close
@@ -81,10 +81,12 @@ module Selenium
81
81
 
82
82
  private
83
83
 
84
- def start_session
84
+ def start_session(target_type:)
85
85
  targets = target.get_targets.dig('result', 'targetInfos')
86
- page_target = targets.find { |target| target['type'] == 'page' }
87
- session = target.attach_to_target(target_id: page_target['targetId'], flatten: true)
86
+ found_target = targets.find { |target| target['type'] == target_type }
87
+ raise Error::WebDriverError, "Target type '#{target_type}' not found" unless found_target
88
+
89
+ session = target.attach_to_target(target_id: found_target['targetId'], flatten: true)
88
90
  @session_id = session.dig('result', 'sessionId')
89
91
  end
90
92
 
@@ -30,10 +30,8 @@ module Selenium
30
30
  DriverExtensions::FullPageScreenshot,
31
31
  DriverExtensions::HasContext,
32
32
  DriverExtensions::HasBiDi,
33
- DriverExtensions::HasDevTools,
34
33
  DriverExtensions::HasLogEvents,
35
34
  DriverExtensions::HasNetworkInterception,
36
- DriverExtensions::HasWebStorage,
37
35
  DriverExtensions::PrintsPage].freeze
38
36
 
39
37
  include LocalDriver
@@ -46,23 +44,6 @@ module Selenium
46
44
  def browser
47
45
  :firefox
48
46
  end
49
-
50
- private
51
-
52
- def devtools_url
53
- if capabilities['moz:debuggerAddress'].nil?
54
- raise(Error::WebDriverError, 'DevTools is not supported by this version of Firefox; use v85 or higher')
55
- end
56
-
57
- uri = URI("http://#{capabilities['moz:debuggerAddress']}")
58
- response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
59
-
60
- JSON.parse(response)['webSocketDebuggerUrl']
61
- end
62
-
63
- def devtools_version
64
- Firefox::DEVTOOLS_VERSION
65
- end
66
47
  end # Driver
67
48
  end # Firefox
68
49
  end # WebDriver
@@ -64,9 +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
67
  # https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/.
69
- @options[:prefs]['remote.active-protocols'] = 3
68
+ # Enable BiDi only
69
+ @options[:prefs]['remote.active-protocols'] = 1
70
70
  @options[:env] ||= {}
71
71
  @options[:log] ||= {level: log_level} if log_level
72
72
 
@@ -25,6 +25,15 @@ module Selenium
25
25
  EXECUTABLE = 'geckodriver'
26
26
  SHUTDOWN_SUPPORTED = false
27
27
  DRIVER_PATH_ENV_KEY = 'SE_GECKODRIVER'
28
+
29
+ def initialize(path: nil, port: nil, log: nil, args: nil)
30
+ args ||= []
31
+ unless args.any? { |arg| arg.include?('--connect-existing') }
32
+ args << '--websocket-port'
33
+ args << WebDriver::PortProber.above(9222).to_s
34
+ end
35
+ super
36
+ end
28
37
  end # Service
29
38
  end # Firefox
30
39
  end # WebDriver
@@ -27,7 +27,7 @@ module Selenium
27
27
  #
28
28
 
29
29
  class Driver < WebDriver::Driver
30
- EXTENSIONS = [DriverExtensions::HasWebStorage].freeze
30
+ EXTENSIONS = [].freeze
31
31
 
32
32
  include LocalDriver
33
33
 
@@ -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, &)
38
+ def add_command(name, verb, url, &block)
39
39
  @extra_commands ||= {}
40
40
  @extra_commands[name] = [verb, url]
41
- define_method(name, &)
41
+ define_method(name, &block)
42
42
  end
43
43
 
44
44
  def locator_converter
@@ -296,68 +296,6 @@ module Selenium
296
296
  execute :take_element_screenshot, id: element
297
297
  end
298
298
 
299
- #
300
- # HTML 5
301
- #
302
-
303
- def local_storage_item(key, value = nil)
304
- WebDriver.logger.deprecate('local_storage_item(key, value)', id: :local_storage_item)
305
- if value
306
- execute_script("localStorage.setItem('#{key}', '#{value}')")
307
- else
308
- execute_script("return localStorage.getItem('#{key}')")
309
- end
310
- end
311
-
312
- def remove_local_storage_item(key)
313
- WebDriver.logger.deprecate('remove_local_storage_item(key)', id: :remove_local_storage_item)
314
- execute_script("localStorage.removeItem('#{key}')")
315
- end
316
-
317
- def local_storage_keys
318
- WebDriver.logger.deprecate('local_storage_keys', id: :local_storage_keys)
319
- execute_script('return Object.keys(localStorage)')
320
- end
321
-
322
- def clear_local_storage
323
- WebDriver.logger.deprecate('clear_local_storage', id: :clear_local_storage)
324
- execute_script('localStorage.clear()')
325
- end
326
-
327
- def local_storage_size
328
- WebDriver.logger.deprecate('local_storage_size', id: :local_storage_size)
329
- execute_script('return localStorage.length')
330
- end
331
-
332
- def session_storage_item(key, value = nil)
333
- WebDriver.logger.deprecate('session_storage_item(key, value)', id: :session_storage_item)
334
- if value
335
- execute_script("sessionStorage.setItem('#{key}', '#{value}')")
336
- else
337
- execute_script("return sessionStorage.getItem('#{key}')")
338
- end
339
- end
340
-
341
- def remove_session_storage_item(key)
342
- WebDriver.logger.deprecate('remove_session_storage_item(key)', id: :remove_session_storage_item)
343
- execute_script("sessionStorage.removeItem('#{key}')")
344
- end
345
-
346
- def session_storage_keys
347
- WebDriver.logger.deprecate('session_storage_keys', id: :session_storage_keys)
348
- execute_script('return Object.keys(sessionStorage)')
349
- end
350
-
351
- def clear_session_storage
352
- WebDriver.logger.deprecate('clear_session_storage', id: :clear_session_storage)
353
- execute_script('sessionStorage.clear()')
354
- end
355
-
356
- def session_storage_size
357
- WebDriver.logger.deprecate('session_storage_size', id: :session_storage_size)
358
- execute_script('return sessionStorage.length')
359
- end
360
-
361
299
  #
362
300
  # javascript execution
363
301
  #
@@ -385,6 +323,8 @@ module Selenium
385
323
  end
386
324
 
387
325
  def delete_cookie(name)
326
+ raise ArgumentError, 'Cookie name cannot be null or empty' if name.nil? || name.to_s.strip.empty?
327
+
388
328
  execute :delete_cookie, name: name
389
329
  end
390
330
 
@@ -27,8 +27,7 @@ module Selenium
27
27
 
28
28
  class Driver < WebDriver::Driver
29
29
  EXTENSIONS = [DriverExtensions::HasDebugger,
30
- DriverExtensions::HasApplePermissions,
31
- DriverExtensions::HasWebStorage].freeze
30
+ DriverExtensions::HasApplePermissions].freeze
32
31
 
33
32
  include LocalDriver
34
33
 
@@ -37,8 +37,10 @@ module Selenium
37
37
  @messages = {}
38
38
  end
39
39
 
40
- def add_condition(name, condition = nil, &)
41
- @guard_conditions << GuardCondition.new(name, condition, &)
40
+ def add_condition(name, condition = false, &block)
41
+ condition = false if condition.nil?
42
+ @guard_conditions << GuardCondition.new(name, condition, &block)
43
+ WebDriver.logger.debug "Running with Guard '#{name}' set to: #{condition}"
42
44
  end
43
45
 
44
46
  def add_message(name, message)
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.27.0'
22
+ VERSION = '4.32.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.homepage = 'https://selenium.dev'
23
23
  s.metadata = {
24
24
  'changelog_uri' => 'https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES',
25
+ 'documentation_uri' => 'https://www.selenium.dev/documentation/?tab=ruby',
25
26
  'github_repo' => 'ssh://github.com/SeleniumHQ/selenium',
26
27
  'source_code_uri' => 'https://github.com/SeleniumHQ/selenium/tree/trunk/rb',
27
28
  'rubygems_mfa_required' => 'true',
@@ -58,10 +59,10 @@ Gem::Specification.new do |s|
58
59
  s.add_development_dependency 'rack', ['~> 2.0']
59
60
  s.add_development_dependency 'rake', ['~> 13.0']
60
61
  s.add_development_dependency 'rspec', ['~> 3.0']
61
- s.add_development_dependency 'rubocop', ['~> 1.60', '>=1.60.2']
62
- s.add_development_dependency 'rubocop-performance', ['~> 1.15']
63
- s.add_development_dependency 'rubocop-rake', ['~> 0.6.0']
64
- s.add_development_dependency 'rubocop-rspec', ['~> 2.16']
62
+ s.add_development_dependency 'rubocop', ['~> 1.75']
63
+ s.add_development_dependency 'rubocop-performance', ['~> 1.25']
64
+ s.add_development_dependency 'rubocop-rake', ['~> 0.7']
65
+ s.add_development_dependency 'rubocop-rspec', ['~> 3.5']
65
66
  s.add_development_dependency 'webmock', ['~> 3.5']
66
67
  s.add_development_dependency 'webrick', ['~> 1.7']
67
68
  s.add_development_dependency 'yard', ['~> 0.9.11', '>= 0.9.36']