selenium-webdriver 4.4.0 → 4.8.1

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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +98 -1
  3. data/LICENSE +1 -1
  4. data/NOTICE +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 +20 -16
  9. data/lib/selenium/webdriver/atoms/findElements.js +0 -0
  10. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  11. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  12. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  13. data/lib/selenium/webdriver/atoms.rb +2 -3
  14. data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
  15. data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
  16. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  17. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
  19. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  20. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  21. data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
  22. data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
  23. data/lib/selenium/webdriver/bidi/session.rb +13 -0
  24. data/lib/selenium/webdriver/bidi.rb +3 -2
  25. data/lib/selenium/webdriver/chrome/driver.rb +19 -28
  26. data/lib/selenium/webdriver/chrome/features.rb +5 -72
  27. data/lib/selenium/webdriver/chrome/options.rb +3 -237
  28. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  29. data/lib/selenium/webdriver/chrome/service.rb +4 -19
  30. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  31. data/lib/selenium/webdriver/chromium/features.rb +103 -0
  32. data/lib/selenium/webdriver/chromium/options.rb +261 -0
  33. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  34. data/lib/selenium/webdriver/chromium/service.rb +42 -0
  35. data/lib/selenium/webdriver/chromium.rb +32 -0
  36. data/lib/selenium/webdriver/common/action_builder.rb +11 -48
  37. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  38. data/lib/selenium/webdriver/common/driver.rb +39 -26
  39. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  40. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  41. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  42. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  43. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  44. data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +0 -1
  46. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  47. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +0 -2
  48. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  49. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  51. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +0 -1
  53. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +0 -2
  55. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  56. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +0 -2
  57. data/lib/selenium/webdriver/common/element.rb +7 -7
  58. data/lib/selenium/webdriver/common/error.rb +0 -2
  59. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  60. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +3 -3
  61. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +2 -2
  62. data/lib/selenium/webdriver/common/interactions/scroll.rb +7 -5
  63. data/lib/selenium/webdriver/common/logger.rb +10 -2
  64. data/lib/selenium/webdriver/common/options.rb +30 -8
  65. data/lib/selenium/webdriver/common/platform.rb +4 -1
  66. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  67. data/lib/selenium/webdriver/common/proxy.rb +1 -1
  68. data/lib/selenium/webdriver/common/selenium_manager.rb +89 -0
  69. data/lib/selenium/webdriver/common/service.rb +16 -8
  70. data/lib/selenium/webdriver/common/service_manager.rb +2 -10
  71. data/lib/selenium/webdriver/common/shadow_root.rb +1 -2
  72. data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
  73. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  74. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  75. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  76. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +8 -6
  77. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +0 -1
  78. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +16 -16
  79. data/lib/selenium/webdriver/common/websocket_connection.rb +10 -2
  80. data/lib/selenium/webdriver/common.rb +2 -0
  81. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  82. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  83. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  84. data/lib/selenium/webdriver/devtools/network_interceptor.rb +3 -6
  85. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  86. data/lib/selenium/webdriver/devtools/request.rb +0 -2
  87. data/lib/selenium/webdriver/devtools/response.rb +0 -2
  88. data/lib/selenium/webdriver/devtools.rb +0 -1
  89. data/lib/selenium/webdriver/edge/driver.rb +20 -3
  90. data/lib/selenium/webdriver/edge/features.rb +3 -4
  91. data/lib/selenium/webdriver/edge/options.rb +3 -5
  92. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  93. data/lib/selenium/webdriver/edge/service.rb +2 -2
  94. data/lib/selenium/webdriver/firefox/driver.rb +19 -2
  95. data/lib/selenium/webdriver/firefox/features.rb +5 -2
  96. data/lib/selenium/webdriver/firefox/options.rb +6 -2
  97. data/lib/selenium/webdriver/firefox/profile.rb +6 -6
  98. data/lib/selenium/webdriver/firefox/service.rb +0 -1
  99. data/lib/selenium/webdriver/ie/driver.rb +20 -1
  100. data/lib/selenium/webdriver/ie/service.rb +1 -2
  101. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +0 -2
  102. data/lib/selenium/webdriver/remote/bridge.rb +9 -15
  103. data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
  104. data/lib/selenium/webdriver/remote/driver.rb +13 -13
  105. data/lib/selenium/webdriver/remote/http/curb.rb +0 -2
  106. data/lib/selenium/webdriver/remote/http/default.rb +1 -0
  107. data/lib/selenium/webdriver/remote/response.rb +0 -1
  108. data/lib/selenium/webdriver/remote.rb +0 -1
  109. data/lib/selenium/webdriver/safari/driver.rb +20 -1
  110. data/lib/selenium/webdriver/safari/features.rb +0 -2
  111. data/lib/selenium/webdriver/safari/options.rb +5 -1
  112. data/lib/selenium/webdriver/safari.rb +1 -1
  113. data/lib/selenium/webdriver/support/color.rb +15 -15
  114. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  115. data/lib/selenium/webdriver/support/guards/guard_condition.rb +0 -2
  116. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  117. data/lib/selenium/webdriver/support/select.rb +3 -1
  118. data/lib/selenium/webdriver/version.rb +1 -1
  119. data/lib/selenium/webdriver.rb +3 -4
  120. data/selenium-webdriver.gemspec +8 -9
  121. metadata +31 -74
  122. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  123. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -21,7 +21,6 @@ module Selenium
21
21
  module WebDriver
22
22
  module DriverExtensions
23
23
  module HasPermissions
24
-
25
24
  #
26
25
  # Set one permission.
27
26
  #
@@ -44,7 +43,6 @@ module Selenium
44
43
  @bridge.set_permission(key, value)
45
44
  end
46
45
  end
47
-
48
46
  end # HasPermissions
49
47
  end # DriverExtensions
50
48
  end # WebDriver
@@ -21,7 +21,6 @@ module Selenium
21
21
  module WebDriver
22
22
  module DriverExtensions
23
23
  module HasPinnedScripts
24
-
25
24
  #
26
25
  # Returns the list of all pinned scripts.
27
26
  #
@@ -70,7 +69,6 @@ module Selenium
70
69
  devtools.page.remove_script_to_evaluate_on_new_document(identifier: script.devtools_identifier)
71
70
  pinned_scripts.delete(script)
72
71
  end
73
-
74
72
  end # HasPinnedScripts
75
73
  end # DriverExtensions
76
74
  end # WebDriver
@@ -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
@@ -213,7 +212,6 @@ module Selenium
213
212
  #
214
213
 
215
214
  class UnsupportedOperationError < WebDriverError; end
216
-
217
215
  end # Error
218
216
  end # WebDriver
219
217
  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)
@@ -48,9 +48,10 @@ module Selenium
48
48
  #
49
49
  # @param [String] progname Allow child projects to use Selenium's Logger pattern
50
50
  #
51
- def initialize(progname = 'Selenium')
51
+ def initialize(progname = 'Selenium', ignored: nil)
52
52
  @logger = create_logger(progname)
53
- @ignored = []
53
+ @ignored = Array(ignored)
54
+ @first_warning = false
54
55
  end
55
56
 
56
57
  #
@@ -94,6 +95,13 @@ module Selenium
94
95
  # @yield see #deprecate
95
96
  #
96
97
  def warn(message, id: [])
98
+ unless @first_warning
99
+ @first_warning = true
100
+ warn("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
101
+ "https://selenium.dev/documentation/webdriver/troubleshooting/logging#ruby\n"
102
+ end
103
+ end
104
+
97
105
  id = Array(id)
98
106
  return if (@ignored & id).any?
99
107
 
@@ -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,13 @@ 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
+
90
+ unless name.to_s.include?(':')
91
+ WebDriver.logger.deprecate('Options#add_option for w3c or browser specific capabilities',
92
+ 'applicable attribute accessors or pass into constructor',
93
+ id: :add_option)
94
+ end
89
95
  @options[name] = value
90
96
  end
91
97
 
@@ -95,7 +101,7 @@ module Selenium
95
101
  as_json == other.as_json
96
102
  end
97
103
 
98
- alias_method :eql?, :==
104
+ alias eql? ==
99
105
 
100
106
  #
101
107
  # @api private
@@ -106,11 +112,27 @@ module Selenium
106
112
 
107
113
  w3c_options = process_w3c_options(options)
108
114
 
109
- self.class::CAPABILITIES.each do |capability_alias, capability_name|
110
- capability_value = options.delete(capability_alias)
111
- options[capability_name] = capability_value if !capability_value.nil? && !options.key?(capability_name)
115
+ browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
116
+ from_name = options.delete(capability_name)
117
+ from_alias = options.delete(capability_alias)
118
+ capability_value = if !from_name.nil? && capability_alias != capability_name
119
+ WebDriver.logger.deprecate("#{capability_name} as option",
120
+ capability_alias.to_s, id: :option_symbols)
121
+ from_name
122
+ elsif !from_alias.nil?
123
+ from_alias
124
+ end
125
+
126
+ hash[capability_name] = capability_value unless capability_value.nil?
112
127
  end
113
- browser_options = defined?(self.class::KEY) ? {self.class::KEY => options} : options
128
+
129
+ unless options.empty?
130
+ msg = 'These options are not w3c compliant and will result in failures in a future release'
131
+ WebDriver.logger.warn("#{msg}: #{options}")
132
+ browser_options.merge!(options)
133
+ end
134
+
135
+ browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
114
136
 
115
137
  process_browser_options(browser_options)
116
138
  generate_as_json(w3c_options.merge(browser_options))
@@ -78,6 +78,10 @@ module Selenium
78
78
  engine == :jruby
79
79
  end
80
80
 
81
+ def truffleruby?
82
+ engine == :truffleruby
83
+ end
84
+
81
85
  def ruby_version
82
86
  RUBY_VERSION
83
87
  end
@@ -105,7 +109,6 @@ module Selenium
105
109
 
106
110
  def cygwin?
107
111
  RUBY_PLATFORM.include?('cygwin')
108
- !Regexp.last_match.nil?
109
112
  end
110
113
 
111
114
  def null_device
@@ -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
@@ -0,0 +1,89 @@
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
+ require 'open3'
21
+
22
+ module Selenium
23
+ module WebDriver
24
+ #
25
+ # Wrapper for getting information from the Selenium Manager binaries.
26
+ # This implementation is still in beta, and may change.
27
+ # @api private
28
+ #
29
+ class SeleniumManager
30
+ BIN_PATH = '../../../../../bin'
31
+
32
+ class << self
33
+ # @param [String] driver_name which driver to use.
34
+ # @return [String] the path to the correct driver.
35
+ def driver_path(driver_name)
36
+ unless %w[chromedriver geckodriver msedgedriver IEDriverServer].include?(driver_name)
37
+ msg = "Unable to locate driver with name: #{driver_name}"
38
+ raise Error::WebDriverError, msg
39
+ end
40
+
41
+ location = run("#{binary} --driver #{driver_name}")
42
+ WebDriver.logger.debug("Driver found at #{location}")
43
+ Platform.assert_executable location
44
+
45
+ location
46
+ end
47
+
48
+ private
49
+
50
+ # @return [String] the path to the correct selenium manager
51
+ def binary
52
+ @binary ||= begin
53
+ path = File.expand_path(BIN_PATH, __FILE__)
54
+ path << if Platform.windows?
55
+ '/windows/selenium-manager.exe'
56
+ elsif Platform.mac?
57
+ '/macos/selenium-manager'
58
+ elsif Platform.linux?
59
+ '/linux/selenium-manager'
60
+ end
61
+ location = File.expand_path(path, __FILE__)
62
+ unless location.is_a?(String) && File.exist?(location) && File.executable?(location)
63
+ raise Error::WebDriverError, 'Unable to obtain Selenium Manager'
64
+ end
65
+
66
+ WebDriver.logger.debug("Selenium Manager found at #{location}")
67
+ location
68
+ end
69
+ end
70
+
71
+ def run(command)
72
+ WebDriver.logger.debug("Executing Process #{command}")
73
+
74
+ begin
75
+ stdout, stderr, status = Open3.capture3(command)
76
+ rescue StandardError => e
77
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}", e.message
78
+ end
79
+
80
+ if status.exitstatus.positive?
81
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}\n#{stdout}#{stderr}"
82
+ end
83
+
84
+ stdout.gsub("INFO\t", '').strip
85
+ end
86
+ end
87
+ end # SeleniumManager
88
+ end # WebDriver
89
+ end # Selenium
@@ -39,12 +39,13 @@ module Selenium
39
39
  def ie(**opts)
40
40
  IE::Service.new(**opts)
41
41
  end
42
- alias_method :internet_explorer, :ie
42
+ alias internet_explorer ie
43
43
 
44
44
  def edge(**opts)
45
45
  Edge::Service.new(**opts)
46
46
  end
47
- alias_method :microsoftedge, :edge
47
+ alias microsoftedge edge
48
+ alias msedge edge
48
49
 
49
50
  def safari(**opts)
50
51
  Safari::Service.new(**opts)
@@ -56,8 +57,8 @@ module Selenium
56
57
  end
57
58
  end
58
59
 
59
- attr_accessor :host
60
- attr_reader :executable_path, :port, :extra_args
60
+ attr_accessor :host, :executable_path, :port, :args
61
+ alias extra_args args
61
62
 
62
63
  #
63
64
  # End users should use a class method for the desired driver, rather than using this directly.
@@ -74,15 +75,13 @@ module Selenium
74
75
  @host = Platform.localhost
75
76
  @port = Integer(port)
76
77
 
77
- @extra_args = args.is_a?(Hash) ? extract_service_args(args) : args
78
+ @args = args.is_a?(Hash) ? extract_service_args(args) : args
78
79
 
79
80
  raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
80
81
  end
81
82
 
82
83
  def launch
83
- sm = ServiceManager.new(self)
84
- sm.start
85
- sm
84
+ ServiceManager.new(self).tap(&:start)
86
85
  end
87
86
 
88
87
  def shutdown_supported
@@ -92,6 +91,9 @@ module Selenium
92
91
  protected
93
92
 
94
93
  def extract_service_args(driver_opts)
94
+ WebDriver.logger.deprecate('initializing Service class with :args using Hash',
95
+ ':args parameter with an Array of String values',
96
+ id: :driver_opts)
95
97
  driver_opts.key?(:args) ? driver_opts.delete(:args) : []
96
98
  end
97
99
 
@@ -101,6 +103,12 @@ module Selenium
101
103
  path = path.call if path.is_a?(Proc)
102
104
  path ||= Platform.find_binary(self.class::EXECUTABLE)
103
105
 
106
+ begin
107
+ path ||= SeleniumManager.driver_path(self.class::EXECUTABLE)
108
+ rescue Error::WebDriverError => e
109
+ WebDriver.logger.debug("Unable obtain driver using Selenium Manager\n #{e.message}")
110
+ end
111
+
104
112
  raise Error::WebDriverError, self.class::MISSING_TEXT unless path
105
113
 
106
114
  Platform.assert_executable path
@@ -40,7 +40,7 @@ module Selenium
40
40
  @executable_path = config.executable_path
41
41
  @host = Platform.localhost
42
42
  @port = config.port
43
- @extra_args = config.extra_args
43
+ @extra_args = config.args
44
44
  @shutdown_supported = config.shutdown_supported
45
45
 
46
46
  raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
@@ -79,12 +79,7 @@ module Selenium
79
79
  def build_process(*command)
80
80
  WebDriver.logger.debug("Executing Process #{command}")
81
81
  @process = ChildProcess.build(*command)
82
- if WebDriver.logger.debug?
83
- @process.io.stdout = @process.io.stderr = WebDriver.logger.io
84
- elsif Platform.jruby?
85
- # Apparently we need to read the output of drivers on JRuby.
86
- @process.io.stdout = @process.io.stderr = File.new(Platform.null_device, 'w')
87
- end
82
+ @process.io = WebDriver.logger.io if WebDriver.logger.debug?
88
83
 
89
84
  @process
90
85
  end
@@ -104,8 +99,6 @@ module Selenium
104
99
 
105
100
  def start_process
106
101
  @process = build_process(@executable_path, "--port=#{@port}", *@extra_args)
107
- # NOTE: this is a bug only in Windows 7
108
- @process.leader = true unless Platform.windows?
109
102
  @process.start
110
103
  end
111
104
 
@@ -113,7 +106,6 @@ module Selenium
113
106
  return if process_exited?
114
107
 
115
108
  @process.stop STOP_TIMEOUT
116
- @process.io.stdout.close if Platform.jruby? && !WebDriver.logger.debug?
117
109
  end
118
110
 
119
111
  def stop_server
@@ -42,7 +42,7 @@ module Selenium
42
42
  def ==(other)
43
43
  other.is_a?(self.class) && ref == other.ref
44
44
  end
45
- alias_method :eql?, :==
45
+ alias eql? ==
46
46
 
47
47
  def hash
48
48
  [@id, @bridge].hash
@@ -81,7 +81,6 @@ module Selenium
81
81
  private
82
82
 
83
83
  attr_reader :bridge
84
-
85
84
  end # ShadowRoot
86
85
  end # WebDriver
87
86
  end # Selenium
@@ -26,6 +26,7 @@ module Selenium
26
26
  class SocketLock
27
27
  def initialize(port, timeout)
28
28
  @port = port
29
+ @server = nil
29
30
  @timeout = timeout
30
31
  end
31
32
 
@@ -66,8 +67,7 @@ module Selenium
66
67
 
67
68
  def can_lock?
68
69
  @server = TCPServer.new(Platform.localhost, @port)
69
- ChildProcess.close_on_exec @server
70
-
70
+ @server.close_on_exec = true
71
71
  true
72
72
  rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => e
73
73
  WebDriver.logger.debug("#{self}: #{e.message}")
@@ -32,8 +32,8 @@ module Selenium
32
32
  def save_screenshot(png_path, full_page: false)
33
33
  extension = File.extname(png_path).downcase
34
34
  if extension != '.png'
35
- WebDriver.logger.warn "name used for saved screenshot does not match file type. " \
36
- "It should end with .png extension",
35
+ WebDriver.logger.warn 'name used for saved screenshot does not match file type. ' \
36
+ 'It should end with .png extension',
37
37
  id: :screenshot
38
38
  end
39
39
  File.open(png_path, 'wb') { |f| f << screenshot_as(:png, full_page: full_page) }
@@ -60,7 +60,6 @@ module Selenium
60
60
  rescue NameError
61
61
  raise Error::UnsupportedOperationError, "Full Page Screenshots are not supported for #{inspect}"
62
62
  end
63
-
64
63
  end # TakesScreenshot
65
64
  end # WebDriver
66
65
  end # Selenium
@@ -51,9 +51,8 @@ module Selenium
51
51
  #
52
52
 
53
53
  def new_window(type = :window)
54
- unless %i[window tab].include?(type)
55
- raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}"
56
- end
54
+ raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}" unless %i[window
55
+ tab].include?(type)
57
56
 
58
57
  handle = @bridge.new_window(type)['handle']
59
58
 
@@ -48,7 +48,7 @@ module Selenium
48
48
  def script
49
49
  Float(@bridge.timeouts['script']) / 1000
50
50
  end
51
- alias_method :script_timeout, :script
51
+ alias script_timeout script
52
52
 
53
53
  #
54
54
  # Sets the amount of time to wait for an asynchronous script to finish
@@ -59,7 +59,7 @@ module Selenium
59
59
  def script=(seconds)
60
60
  @bridge.timeouts = {'script' => Integer(seconds * 1000)}
61
61
  end
62
- alias_method :script_timeout=, :script=
62
+ alias script_timeout= script=
63
63
 
64
64
  #
65
65
  # Gets the amount of time to wait for a page load to complete before throwing an error.
@@ -44,8 +44,8 @@ module Selenium
44
44
 
45
45
  def from_json(opts)
46
46
  user_handle = opts['userHandle'] ? decode(opts['userHandle']) : nil
47
- new(id: decode(opts["credentialId"]),
48
- resident_credential: opts["isResidentCredential"],
47
+ new(id: decode(opts['credentialId']),
48
+ resident_credential: opts['isResidentCredential'],
49
49
  rp_id: opts['rpId'],
50
50
  private_key: opts['privateKey'],
51
51
  sign_count: opts['signCount'],
@@ -54,15 +54,17 @@ module Selenium
54
54
  end
55
55
 
56
56
  attr_reader :id, :resident_credential, :rp_id, :user_handle, :private_key, :sign_count
57
- alias_method :resident_credential?, :resident_credential
57
+ alias resident_credential? resident_credential
58
58
 
59
- def initialize(id:, resident_credential:, rp_id:, private_key:, user_handle: nil, sign_count: 0)
59
+ def initialize(id:, resident_credential:, rp_id:, private_key:, **opts)
60
60
  @id = id
61
61
  @resident_credential = resident_credential
62
62
  @rp_id = rp_id
63
- @user_handle = user_handle
63
+ @user_handle = opts.delete(:user_handle) { nil }
64
64
  @private_key = private_key
65
- @sign_count = sign_count
65
+ @sign_count = opts.delete(:sign_count) { 0 }
66
+
67
+ raise ArgumentError, "Invalid arguments: #{opts.keys}" unless opts.empty?
66
68
  end
67
69
 
68
70
  #
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class VirtualAuthenticator
23
-
24
23
  attr_reader :options
25
24
 
26
25
  #