selenium-webdriver 4.4.0 → 4.11.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +177 -1
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/README.md +2 -2
  7. data/bin/linux/selenium-manager +0 -0
  8. data/bin/macos/selenium-manager +0 -0
  9. data/bin/windows/selenium-manager.exe +0 -0
  10. data/lib/selenium/server.rb +21 -29
  11. data/lib/selenium/webdriver/atoms/findElements.js +3 -4
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  14. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  15. data/lib/selenium/webdriver/atoms.rb +2 -3
  16. data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
  17. data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  19. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  20. data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
  21. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  22. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  23. data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
  24. data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
  25. data/lib/selenium/webdriver/bidi/session.rb +13 -0
  26. data/lib/selenium/webdriver/bidi.rb +3 -2
  27. data/lib/selenium/webdriver/chrome/driver.rb +9 -29
  28. data/lib/selenium/webdriver/chrome/features.rb +5 -72
  29. data/lib/selenium/webdriver/chrome/options.rb +3 -237
  30. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  31. data/lib/selenium/webdriver/chrome/service.rb +0 -22
  32. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  33. data/lib/selenium/webdriver/chromium/features.rb +103 -0
  34. data/lib/selenium/webdriver/chromium/options.rb +243 -0
  35. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  36. data/lib/selenium/webdriver/chromium.rb +31 -0
  37. data/lib/selenium/webdriver/common/action_builder.rb +11 -56
  38. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  39. data/lib/selenium/webdriver/common/driver.rb +21 -26
  40. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  41. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  42. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  43. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  44. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +0 -1
  47. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  48. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +0 -2
  49. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  51. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +0 -1
  54. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  55. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +0 -2
  56. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  57. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +0 -2
  58. data/lib/selenium/webdriver/common/driver_finder.rb +45 -0
  59. data/lib/selenium/webdriver/common/element.rb +7 -7
  60. data/lib/selenium/webdriver/common/error.rb +27 -4
  61. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  62. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +3 -3
  63. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +2 -2
  64. data/lib/selenium/webdriver/common/interactions/scroll.rb +7 -5
  65. data/lib/selenium/webdriver/common/local_driver.rb +55 -0
  66. data/lib/selenium/webdriver/common/logger.rb +90 -25
  67. data/lib/selenium/webdriver/common/options.rb +11 -8
  68. data/lib/selenium/webdriver/common/platform.rb +4 -50
  69. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  70. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  71. data/lib/selenium/webdriver/common/proxy.rb +2 -2
  72. data/lib/selenium/webdriver/common/selenium_manager.rb +131 -0
  73. data/lib/selenium/webdriver/common/service.rb +17 -30
  74. data/lib/selenium/webdriver/common/service_manager.rb +6 -12
  75. data/lib/selenium/webdriver/common/shadow_root.rb +1 -2
  76. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  77. data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
  78. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  79. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  80. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  81. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +8 -6
  82. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +0 -1
  83. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +16 -16
  84. data/lib/selenium/webdriver/common/websocket_connection.rb +12 -4
  85. data/lib/selenium/webdriver/common.rb +4 -0
  86. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  87. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  88. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  89. data/lib/selenium/webdriver/devtools/network_interceptor.rb +4 -7
  90. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  91. data/lib/selenium/webdriver/devtools/request.rb +0 -2
  92. data/lib/selenium/webdriver/devtools/response.rb +0 -2
  93. data/lib/selenium/webdriver/devtools.rb +11 -2
  94. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  95. data/lib/selenium/webdriver/edge/features.rb +3 -4
  96. data/lib/selenium/webdriver/edge/options.rb +17 -5
  97. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  98. data/lib/selenium/webdriver/edge/service.rb +1 -7
  99. data/lib/selenium/webdriver/firefox/driver.rb +8 -2
  100. data/lib/selenium/webdriver/firefox/features.rb +5 -2
  101. data/lib/selenium/webdriver/firefox/options.rb +3 -14
  102. data/lib/selenium/webdriver/firefox/profile.rb +7 -7
  103. data/lib/selenium/webdriver/firefox/service.rb +0 -18
  104. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  105. data/lib/selenium/webdriver/ie/options.rb +2 -1
  106. data/lib/selenium/webdriver/ie/service.rb +0 -22
  107. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +0 -2
  108. data/lib/selenium/webdriver/remote/bridge.rb +15 -20
  109. data/lib/selenium/webdriver/remote/capabilities.rb +3 -53
  110. data/lib/selenium/webdriver/remote/driver.rb +19 -13
  111. data/lib/selenium/webdriver/remote/http/common.rb +3 -3
  112. data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
  113. data/lib/selenium/webdriver/remote/http/default.rb +2 -2
  114. data/lib/selenium/webdriver/remote/response.rb +0 -1
  115. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  116. data/lib/selenium/webdriver/remote.rb +0 -1
  117. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  118. data/lib/selenium/webdriver/safari/features.rb +0 -2
  119. data/lib/selenium/webdriver/safari/options.rb +5 -1
  120. data/lib/selenium/webdriver/safari/service.rb +10 -4
  121. data/lib/selenium/webdriver/safari.rb +1 -1
  122. data/lib/selenium/webdriver/support/color.rb +17 -17
  123. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  124. data/lib/selenium/webdriver/support/guards/guard_condition.rb +0 -2
  125. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  126. data/lib/selenium/webdriver/support/select.rb +3 -1
  127. data/lib/selenium/webdriver/version.rb +1 -1
  128. data/lib/selenium/webdriver.rb +4 -4
  129. data/selenium-webdriver.gemspec +10 -11
  130. metadata +40 -82
  131. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  132. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -43,7 +43,7 @@ module Selenium
43
43
  def ==(other)
44
44
  other.is_a?(self.class) && ref == other.ref
45
45
  end
46
- alias_method :eql?, :==
46
+ alias eql? ==
47
47
 
48
48
  def hash
49
49
  [@id, @bridge].hash
@@ -101,7 +101,7 @@ module Selenium
101
101
  # if it exists. If it does not, then the value of the attribute with the given name is returned.
102
102
  # If neither exists, null is returned.
103
103
  #
104
- # The "style" attribute is converted as best can be to a text representation with a trailing semi-colon.
104
+ # The "style" attribute is converted as best can be to a text representation with a trailing semicolon.
105
105
  #
106
106
  # The following are deemed to be "boolean" attributes, and will return either "true" or "false":
107
107
  #
@@ -207,7 +207,7 @@ module Selenium
207
207
  def send_keys(*args)
208
208
  bridge.send_keys_to_element @id, Keys.encode(args)
209
209
  end
210
- alias_method :send_key, :send_keys
210
+ alias send_key send_keys
211
211
 
212
212
  #
213
213
  # If this element is a text entry element, this will clear the value. Has no effect on other
@@ -275,7 +275,7 @@ module Selenium
275
275
  def css_value(prop)
276
276
  bridge.element_value_of_css_property @id, prop
277
277
  end
278
- alias_method :style, :css_value
278
+ alias style css_value
279
279
 
280
280
  #
281
281
  # Get the location of this element.
@@ -333,18 +333,18 @@ module Selenium
333
333
  # element.first(id: 'foo')
334
334
  #
335
335
 
336
- alias_method :first, :find_element
336
+ alias first find_element
337
337
 
338
338
  #
339
339
  # element.all(class: 'bar')
340
340
  #
341
341
 
342
- alias_method :all, :find_elements
342
+ alias all find_elements
343
343
 
344
344
  #
345
345
  # element['class'] or element[:class] #=> "someclass"
346
346
  #
347
- alias_method :[], :attribute
347
+ alias [] attribute
348
348
 
349
349
  #
350
350
  # @api private
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Error
23
-
24
23
  #
25
24
  # Returns exception from its string representation.
26
25
  # @param [String, nil] error
@@ -35,13 +34,20 @@ module Selenium
35
34
  WebDriverError
36
35
  end
37
36
 
37
+ SUPPORT_MSG = 'For documentation on this error, please visit:'
38
+ ERROR_URL = 'https://www.selenium.dev/documentation/webdriver/troubleshooting/errors'
39
+
38
40
  class WebDriverError < StandardError; end
39
41
 
40
42
  #
41
43
  # An element could not be located on the page using the given search parameters.
42
44
  #
43
45
 
44
- class NoSuchElementError < WebDriverError; end
46
+ class NoSuchElementError < WebDriverError
47
+ def initialize(msg = '')
48
+ super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}#no-such-element-exception")
49
+ end
50
+ end
45
51
 
46
52
  #
47
53
  # A command to switch to a frame could not be satisfied because the frame could not be found.
@@ -59,7 +65,11 @@ module Selenium
59
65
  # A command failed because the referenced element is no longer attached to the DOM.
60
66
  #
61
67
 
62
- class StaleElementReferenceError < WebDriverError; end
68
+ class StaleElementReferenceError < WebDriverError
69
+ def initialize(msg = '')
70
+ super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}#stale-element-reference-exception")
71
+ end
72
+ end
63
73
 
64
74
  #
65
75
  # A command failed because the referenced shadow root is no longer attached to the DOM.
@@ -133,7 +143,11 @@ module Selenium
133
143
  # Argument was an invalid selector.
134
144
  #
135
145
 
136
- class InvalidSelectorError < WebDriverError; end
146
+ class InvalidSelectorError < WebDriverError
147
+ def initialize(msg = '')
148
+ super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}#invalid-selector-exception")
149
+ end
150
+ end
137
151
 
138
152
  #
139
153
  # A new session could not be created.
@@ -214,6 +228,15 @@ module Selenium
214
228
 
215
229
  class UnsupportedOperationError < WebDriverError; end
216
230
 
231
+ #
232
+ # Indicates that driver was not specified and could not be located.
233
+ #
234
+
235
+ class NoSuchDriverError < WebDriverError
236
+ def initialize(msg = '')
237
+ super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}/driver_location")
238
+ end
239
+ end
217
240
  end # Error
218
241
  end # WebDriver
219
242
  end # Selenium
@@ -26,8 +26,8 @@ module Selenium
26
26
  def key?(key)
27
27
  keys.include? key
28
28
  end
29
- alias_method :member?, :key?
30
- alias_method :has_key?, :key?
29
+ alias member? key?
30
+ alias has_key? key?
31
31
 
32
32
  def fetch(key)
33
33
  return self[key] if key? key
@@ -95,9 +95,9 @@ module Selenium
95
95
  # @return [ActionBuilder] A self reference.
96
96
  #
97
97
 
98
- def move_to(element, right_by = nil, down_by = nil, device: nil, duration: default_move_duration, **opts)
99
- pointer = pointer_input(device)
100
- pointer.create_pointer_move(duration: duration,
98
+ def move_to(element, right_by = nil, down_by = nil, **opts)
99
+ pointer = pointer_input(opts.delete(:device))
100
+ pointer.create_pointer_move(duration: opts.delete(:duration) || default_move_duration,
101
101
  x: right_by || 0,
102
102
  y: down_by || 0,
103
103
  origin: element,
@@ -33,12 +33,12 @@ module Selenium
33
33
  POINTER = :pointer
34
34
  ORIGINS = [VIEWPORT, POINTER].freeze
35
35
 
36
- def initialize(source, duration, x, y, element: nil, origin: nil, **opts)
36
+ def initialize(source, duration, x, y, **opts)
37
37
  super(source)
38
38
  @duration = duration * 1000
39
39
  @x_offset = x
40
40
  @y_offset = y
41
- @origin = element || origin || :viewport
41
+ @origin = opts.delete(:element) || opts.delete(:origin) || :viewport
42
42
  @type = :pointerMove
43
43
  @opts = opts
44
44
  end
@@ -27,15 +27,17 @@ module Selenium
27
27
  #
28
28
 
29
29
  class Scroll < Interaction
30
- def initialize(source:, x: 0, y: 0, delta_x: 0, delta_y: 0, origin: :viewport, duration: 0.25)
30
+ def initialize(source:, origin: :viewport, duration: 0.25, **opts)
31
31
  super(source)
32
32
  @type = :scroll
33
33
  @duration = duration * 1000
34
34
  @origin = origin
35
- @x_offset = x
36
- @y_offset = y
37
- @delta_x = delta_x
38
- @delta_y = delta_y
35
+ @x_offset = opts.delete(:x) || 0
36
+ @y_offset = opts.delete(:y) || 0
37
+ @delta_x = opts.delete(:delta_x) || 0
38
+ @delta_y = opts.delete(:delta_y) || 0
39
+
40
+ raise ArgumentError, "Invalid arguments: #{opts.keys}" unless opts.empty?
39
41
  end
40
42
 
41
43
  def assert_source(source)
@@ -0,0 +1,55 @@
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 LocalDriver
23
+ def initialize_local_driver(capabilities, options, service, url)
24
+ raise ArgumentError, "Can't initialize #{self.class} with :url" if url
25
+
26
+ service ||= Service.send(browser)
27
+ caps = process_options(options, capabilities, service)
28
+ url = service_url(service)
29
+
30
+ [caps, url]
31
+ end
32
+
33
+ def process_options(options, capabilities, service)
34
+ default_options = Options.send(browser)
35
+
36
+ if options && capabilities
37
+ msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
38
+ raise ArgumentError, msg
39
+ elsif options && !options.is_a?(default_options.class)
40
+ raise ArgumentError, ":options must be an instance of #{default_options.class}"
41
+ elsif capabilities
42
+ WebDriver.logger.deprecate("The :capabilities parameter for #{self.class}",
43
+ ":options argument with an instance of #{self.class}",
44
+ id: :capabilities)
45
+ service.executable_path ||= WebDriver::DriverFinder.path(capabilities, service.class)
46
+ generate_capabilities(capabilities)
47
+ else
48
+ options ||= default_options
49
+ service.executable_path ||= WebDriver::DriverFinder.path(options, service.class)
50
+ options.as_json
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -38,19 +38,31 @@ module Selenium
38
38
 
39
39
  def_delegators :@logger,
40
40
  :close,
41
- :debug, :debug?,
42
- :info, :info?,
41
+ :debug?,
42
+ :info?,
43
43
  :warn?,
44
- :error, :error?,
44
+ :error?,
45
45
  :fatal, :fatal?,
46
- :level, :level=
46
+ :level
47
47
 
48
48
  #
49
49
  # @param [String] progname Allow child projects to use Selenium's Logger pattern
50
50
  #
51
- def initialize(progname = 'Selenium')
52
- @logger = create_logger(progname)
53
- @ignored = []
51
+ def initialize(progname = 'Selenium', default_level: nil, ignored: nil, allowed: nil)
52
+ default_level ||= $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
53
+
54
+ @logger = create_logger(progname, level: default_level)
55
+ @ignored = Array(ignored)
56
+ @allowed = Array(allowed)
57
+ @first_warning = false
58
+ end
59
+
60
+ def level=(level)
61
+ if level == :info && @logger.level == :info
62
+ info(':info is now the default log level, to see additional logging, set log level to :debug')
63
+ end
64
+
65
+ @logger.level = level
54
66
  end
55
67
 
56
68
  #
@@ -80,27 +92,64 @@ module Selenium
80
92
  #
81
93
  # Will not log the provided ID.
82
94
  #
83
- # @param [Array, Symbol] id
95
+ # @param [Array, Symbol] ids
96
+ #
97
+ def ignore(*ids)
98
+ @ignored += Array(ids).flatten
99
+ end
100
+
101
+ #
102
+ # Will only log the provided ID.
84
103
  #
85
- def ignore(id)
86
- Array(id).each { |ignore| @ignored << ignore }
104
+ # @param [Array, Symbol] ids
105
+ #
106
+ def allow(ids)
107
+ @allowed += Array(ids).flatten
87
108
  end
88
109
 
89
110
  #
90
- # Overrides default #warn to skip ignored messages by provided id
111
+ # Used to supply information of interest for debugging a problem
112
+ # Overrides default #debug to skip ignored messages by provided id
91
113
  #
92
114
  # @param [String] message
93
115
  # @param [Symbol, Array<Sybmol>] id
94
116
  # @yield see #deprecate
95
117
  #
96
- def warn(message, id: [])
97
- id = Array(id)
98
- return if (@ignored & id).any?
118
+ def debug(message, id: [], &block)
119
+ discard_or_log(:debug, message, id, &block)
120
+ end
99
121
 
100
- msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
101
- msg += " #{yield}" if block_given?
122
+ #
123
+ # Used to supply information of general interest
124
+ #
125
+ # @param [String] message
126
+ # @param [Symbol, Array<Sybmol>] id
127
+ # @yield see #deprecate
128
+ #
129
+ def info(message, id: [], &block)
130
+ discard_or_log(:info, message, id, &block)
131
+ end
102
132
 
103
- @logger.warn { msg }
133
+ #
134
+ # Used to supply information that suggests an error occurred
135
+ #
136
+ # @param [String] message
137
+ # @param [Symbol, Array<Sybmol>] id
138
+ # @yield see #deprecate
139
+ #
140
+ def error(message, id: [], &block)
141
+ discard_or_log(:error, message, id, &block)
142
+ end
143
+
144
+ #
145
+ # Used to supply information that suggests action be taken by user
146
+ #
147
+ # @param [String] message
148
+ # @param [Symbol, Array<Sybmol>] id
149
+ # @yield see #deprecate
150
+ #
151
+ def warn(message, id: [], &block)
152
+ discard_or_log(:warn, message, id, &block)
104
153
  end
105
154
 
106
155
  #
@@ -114,11 +163,11 @@ module Selenium
114
163
  #
115
164
  def deprecate(old, new = nil, id: [], reference: '', &block)
116
165
  id = Array(id)
117
- return if @ignored.include?(:deprecations) || (@ignored & id).any?
166
+ return if @ignored.include?(:deprecations)
118
167
 
119
- ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
168
+ id << :deprecations if @allowed.include?(:deprecations)
120
169
 
121
- message = +"[DEPRECATION] #{ids}#{old} is deprecated"
170
+ message = +"[DEPRECATION] #{old} is deprecated"
122
171
  message << if new
123
172
  ". Use #{new} instead."
124
173
  else
@@ -126,15 +175,15 @@ module Selenium
126
175
  end
127
176
  message << " See explanation for this deprecation: #{reference}." unless reference.empty?
128
177
 
129
- warn message, &block
178
+ discard_or_log(:warn, message, id, &block)
130
179
  end
131
180
 
132
181
  private
133
182
 
134
- def create_logger(name)
183
+ def create_logger(name, level:)
135
184
  logger = ::Logger.new($stdout)
136
185
  logger.progname = name
137
- logger.level = default_level
186
+ logger.level = level
138
187
  logger.formatter = proc do |severity, time, progname, msg|
139
188
  "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
140
189
  end
@@ -142,8 +191,24 @@ module Selenium
142
191
  logger
143
192
  end
144
193
 
145
- def default_level
146
- $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
194
+ def discard_or_log(level, message, id)
195
+ id = Array(id)
196
+ return if (@ignored & id).any?
197
+ return if @allowed.any? && (@allowed & id).none?
198
+
199
+ return if ::Logger::Severity.const_get(level.upcase) < @logger.level
200
+
201
+ unless @first_warning
202
+ @first_warning = true
203
+ info("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
204
+ "https://selenium.dev/documentation/webdriver/troubleshooting/logging\n"
205
+ end
206
+ end
207
+
208
+ msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
209
+ msg += " #{yield}" if block_given?
210
+
211
+ @logger.send(level) { msg }
147
212
  end
148
213
  end # Logger
149
214
  end # WebDriver
@@ -38,12 +38,12 @@ module Selenium
38
38
  def ie(**opts)
39
39
  IE::Options.new(**opts)
40
40
  end
41
- alias_method :internet_explorer, :ie
41
+ alias internet_explorer ie
42
42
 
43
43
  def edge(**opts)
44
44
  Edge::Options.new(**opts)
45
45
  end
46
- alias_method :microsoftedge, :edge
46
+ alias microsoftedge edge
47
47
 
48
48
  def safari(**opts)
49
49
  Safari::Options.new(**opts)
@@ -85,7 +85,7 @@ module Selenium
85
85
  #
86
86
 
87
87
  def add_option(name, value = nil)
88
- @options[name.keys.first] = name.values.first if value.nil? && name.is_a?(Hash)
88
+ name, value = name.first if value.nil? && name.is_a?(Hash)
89
89
  @options[name] = value
90
90
  end
91
91
 
@@ -95,7 +95,7 @@ module Selenium
95
95
  as_json == other.as_json
96
96
  end
97
97
 
98
- alias_method :eql?, :==
98
+ alias eql? ==
99
99
 
100
100
  #
101
101
  # @api private
@@ -106,11 +106,14 @@ module Selenium
106
106
 
107
107
  w3c_options = process_w3c_options(options)
108
108
 
109
- self.class::CAPABILITIES.each do |capability_alias, capability_name|
109
+ browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
110
110
  capability_value = options.delete(capability_alias)
111
- options[capability_name] = capability_value if !capability_value.nil? && !options.key?(capability_name)
111
+ hash[capability_name] = capability_value unless capability_value.nil?
112
112
  end
113
- browser_options = defined?(self.class::KEY) ? {self.class::KEY => options} : options
113
+
114
+ raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?
115
+
116
+ browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
114
117
 
115
118
  process_browser_options(browser_options)
116
119
  generate_as_json(w3c_options.merge(browser_options))
@@ -123,7 +126,7 @@ module Selenium
123
126
  end
124
127
 
125
128
  def process_w3c_options(options)
126
- w3c_options = options.select { |key, _val| w3c?(key) }
129
+ w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
127
130
  w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
128
131
  options.delete_if { |key, _val| w3c?(key) }
129
132
  w3c_options
@@ -62,22 +62,14 @@ module Selenium
62
62
  end
63
63
  end
64
64
 
65
- def bitsize
66
- @bitsize ||= if defined?(FFI::Platform::ADDRESS_SIZE)
67
- FFI::Platform::ADDRESS_SIZE
68
- elsif defined?(FFI)
69
- FFI.type_size(:pointer) == 4 ? 32 : 64
70
- elsif jruby?
71
- Integer(ENV_JAVA['sun.arch.data.model'])
72
- else
73
- 1.size == 4 ? 32 : 64
74
- end
75
- end
76
-
77
65
  def jruby?
78
66
  engine == :jruby
79
67
  end
80
68
 
69
+ def truffleruby?
70
+ engine == :truffleruby
71
+ end
72
+
81
73
  def ruby_version
82
74
  RUBY_VERSION
83
75
  end
@@ -105,7 +97,6 @@ module Selenium
105
97
 
106
98
  def cygwin?
107
99
  RUBY_PLATFORM.include?('cygwin')
108
- !Regexp.last_match.nil?
109
100
  end
110
101
 
111
102
  def null_device
@@ -155,43 +146,6 @@ module Selenium
155
146
  at_exit { yield if Process.pid == pid }
156
147
  end
157
148
 
158
- def find_binary(*binary_names)
159
- paths = ENV['PATH'].split(File::PATH_SEPARATOR)
160
-
161
- if windows?
162
- binary_names.map! { |n| "#{n}.exe" }
163
- binary_names.dup.each { |n| binary_names << n.gsub('exe', 'bat') }
164
- end
165
-
166
- binary_names.each do |binary_name|
167
- paths.each do |path|
168
- full_path = File.join(path, binary_name)
169
- full_path = unix_path(full_path) if windows?
170
- exe = Dir.glob(full_path).find { |f| File.executable?(f) }
171
- return exe if exe
172
- end
173
- end
174
-
175
- nil
176
- end
177
-
178
- def find_in_program_files(*binary_names)
179
- paths = [
180
- ENV.fetch('PROGRAMFILES', '\\Program Files'),
181
- ENV.fetch('ProgramFiles(x86)', '\\Program Files (x86)'),
182
- ENV.fetch('ProgramW6432', '\\Program Files')
183
- ]
184
-
185
- paths.each do |root|
186
- binary_names.each do |name|
187
- exe = File.join(root, name)
188
- return exe if File.executable?(exe)
189
- end
190
- end
191
-
192
- nil
193
- end
194
-
195
149
  def localhost
196
150
  info = Socket.getaddrinfo 'localhost', 80, Socket::AF_INET, Socket::SOCK_STREAM
197
151
 
@@ -34,7 +34,7 @@ module Selenium
34
34
  Platform.interfaces.each do |host|
35
35
  TCPServer.new(host, port).close
36
36
  rescue *IGNORED_ERRORS => e
37
- WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
37
+ WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})", id: :driver_service)
38
38
  # ignored - some machines appear unable to bind to some of their interfaces
39
39
  end
40
40
 
@@ -40,7 +40,7 @@ module Selenium
40
40
  end
41
41
 
42
42
  def as_json(*)
43
- {"zip" => encoded}
43
+ {'zip' => encoded}
44
44
  end
45
45
 
46
46
  def to_json(*)
@@ -74,7 +74,7 @@ module Selenium
74
74
  def ==(other)
75
75
  other.is_a?(self.class) && as_json == other.as_json
76
76
  end
77
- alias_method :eql?, :==
77
+ alias eql? ==
78
78
 
79
79
  def ftp=(value)
80
80
  self.type = :manual
@@ -152,7 +152,7 @@ module Selenium
152
152
  'socksUsername' => socks_username,
153
153
  'socksPassword' => socks_password,
154
154
  'socksVersion' => socks_version
155
- }.delete_if { |_k, v| v.nil? }
155
+ }.compact
156
156
 
157
157
  json_result if json_result.length > 1
158
158
  end