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
@@ -21,7 +21,6 @@ module Selenium
21
21
  module WebDriver
22
22
  class DevTools
23
23
  class Response
24
-
25
24
  attr_accessor :code, :body, :headers
26
25
  attr_reader :id
27
26
 
@@ -59,7 +58,6 @@ module Selenium
59
58
  def inspect
60
59
  %(#<#{self.class.name} @id="#{id}" @code="#{code}")
61
60
  end
62
-
63
61
  end # Response
64
62
  end # DevTools
65
63
  end # WebDriver
@@ -52,7 +52,17 @@ module Selenium
52
52
  end
53
53
 
54
54
  def method_missing(method, *_args)
55
- desired_class = "Selenium::DevTools::V#{Selenium::DevTools.version}::#{method.capitalize}"
55
+ namespace = "Selenium::DevTools::V#{Selenium::DevTools.version}"
56
+ methods_to_classes = "#{namespace}::METHODS_TO_CLASSES"
57
+
58
+ desired_class = if Object.const_defined?(methods_to_classes)
59
+ # selenium-devtools 0.113 and newer
60
+ "#{namespace}::#{Object.const_get(methods_to_classes)[method]}"
61
+ else
62
+ # selenium-devtools 0.112 and older
63
+ "#{namespace}::#{method.capitalize}"
64
+ end
65
+
56
66
  return unless Object.const_defined?(desired_class)
57
67
 
58
68
  self.class.class_eval do
@@ -81,7 +91,6 @@ module Selenium
81
91
  def error_message(error)
82
92
  [error['code'], error['message'], error['data']].join(': ')
83
93
  end
84
-
85
94
  end # DevTools
86
95
  end # WebDriver
87
96
  end # Selenium
@@ -17,18 +17,24 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/driver'
20
+ require 'selenium/webdriver/chromium/driver'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
-
26
25
  #
27
26
  # Driver implementation for Microsoft Edge.
28
27
  # @api private
29
28
  #
30
29
 
31
- class Driver < Selenium::WebDriver::Chrome::Driver
30
+ class Driver < Chromium::Driver
31
+ include LocalDriver
32
+
33
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
34
+ caps, url = initialize_local_driver(capabilities, options, service, url)
35
+ super(caps: caps, url: url, **opts)
36
+ end
37
+
32
38
  def browser
33
39
  :edge
34
40
  end
@@ -17,14 +17,13 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/features'
20
+ require 'selenium/webdriver/chromium/features'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
25
  module Features
26
-
27
- include WebDriver::Chrome::Features
26
+ include WebDriver::Chromium::Features
28
27
 
29
28
  EDGE_COMMANDS = {
30
29
  get_cast_sinks: [:get, 'session/:session_id/ms/cast/get_sinks'],
@@ -37,7 +36,7 @@ module Selenium
37
36
  }.freeze
38
37
 
39
38
  def commands(command)
40
- EDGE_COMMANDS[command] || Chrome::Features::CHROME_COMMANDS[command] || self.class::COMMANDS[command]
39
+ EDGE_COMMANDS[command] || CHROMIUM_COMMANDS[command] || self.class::COMMANDS[command]
41
40
  end
42
41
  end # Bridge
43
42
  end # Edge
@@ -17,23 +17,35 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/options'
20
+ require 'selenium/webdriver/chromium/options'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
- class Options < Selenium::WebDriver::Chrome::Options
25
+ class Options < Chromium::Options
26
26
  KEY = 'ms:edgeOptions'
27
27
  BROWSER = 'MicrosoftEdge'
28
28
 
29
- protected
29
+ #
30
+ # Changes the browser name enable webview2
31
+ # see: https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/webdriver
32
+ # Automation of WebView2 apps with Microsoft Edge WebDriver
33
+ #
34
+ # @example Enable webview2
35
+ # options = Selenium::WebDriver::Edge::Options.new
36
+ # options.webview2!
37
+ #
30
38
 
31
- def enable_logging(browser_options)
32
- browser_options['ms:loggingPrefs'] = @logging_prefs
39
+ def webview2!
40
+ @options[:browser_name] = 'webview2'
33
41
  end
34
42
 
35
43
  private
36
44
 
45
+ def enable_logging(browser_options)
46
+ browser_options['ms:loggingPrefs'] = @logging_prefs
47
+ end
48
+
37
49
  def binary_path
38
50
  Edge.path
39
51
  end
@@ -17,7 +17,7 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/profile'
20
+ require 'selenium/webdriver/chromium/profile'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
@@ -26,7 +26,7 @@ module Selenium
26
26
  # @private
27
27
  #
28
28
 
29
- class Profile < Selenium::WebDriver::Chrome::Profile
29
+ class Profile < Chromium::Profile
30
30
  end # Profile
31
31
  end # Edge
32
32
  end # WebDriver
@@ -17,18 +17,12 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/service'
21
-
22
20
  module Selenium
23
21
  module WebDriver
24
22
  module Edge
25
- class Service < Selenium::WebDriver::Chrome::Service
23
+ class Service < WebDriver::Service
26
24
  DEFAULT_PORT = 9515
27
25
  EXECUTABLE = 'msedgedriver'
28
- MISSING_TEXT = <<~ERROR
29
- Unable to find msedgedriver. Please download the server from
30
- https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ and place it somewhere on your PATH.
31
- ERROR
32
26
  SHUTDOWN_SUPPORTED = true
33
27
  end # Service
34
28
  end # Edge
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Firefox
23
-
24
23
  #
25
24
  # Driver implementation for Firefox using GeckoDriver.
26
25
  # @api private
@@ -37,6 +36,13 @@ module Selenium
37
36
  DriverExtensions::HasWebStorage,
38
37
  DriverExtensions::PrintsPage].freeze
39
38
 
39
+ include LocalDriver
40
+
41
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
42
+ caps, url = initialize_local_driver(capabilities, options, service, url)
43
+ super(caps: caps, url: url, **opts)
44
+ end
45
+
40
46
  def browser
41
47
  :firefox
42
48
  end
@@ -45,7 +51,7 @@ module Selenium
45
51
 
46
52
  def devtools_url
47
53
  if capabilities['moz:debuggerAddress'].nil?
48
- raise(Error::WebDriverError, "DevTools is not supported by this version of Firefox; use v85 or higher")
54
+ raise(Error::WebDriverError, 'DevTools is not supported by this version of Firefox; use v85 or higher')
49
55
  end
50
56
 
51
57
  uri = URI("http://#{capabilities['moz:debuggerAddress']}")
@@ -21,7 +21,6 @@ module Selenium
21
21
  module WebDriver
22
22
  module Firefox
23
23
  module Features
24
-
25
24
  FIREFOX_COMMANDS = {
26
25
  get_context: [:get, 'session/:session_id/moz/context'],
27
26
  set_context: [:post, 'session/:session_id/moz/context'],
@@ -35,7 +34,11 @@ module Selenium
35
34
  end
36
35
 
37
36
  def install_addon(path, temporary)
38
- addon = File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
37
+ addon = if File.directory?(path)
38
+ Zipper.zip(path)
39
+ else
40
+ File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
41
+ end
39
42
 
40
43
  payload = {addon: addon}
41
44
  payload[:temporary] = temporary unless temporary.nil?
@@ -57,7 +57,8 @@ module Selenium
57
57
  #
58
58
 
59
59
  def initialize(log_level: nil, **opts)
60
- @debugger_address = opts.delete(:debugger_address)
60
+ @debugger_address = opts.delete(:debugger_address) { true }
61
+ opts[:accept_insecure_certs] = true unless opts.key?(:accept_insecure_certs)
61
62
 
62
63
  super(**opts)
63
64
 
@@ -98,18 +99,6 @@ module Selenium
98
99
  @options[:prefs][name] = value
99
100
  end
100
101
 
101
- #
102
- # Run Firefox in headless mode.
103
- #
104
- # @example Enable headless mode
105
- # options = Selenium::WebDriver::Firefox::Options.new
106
- # options.headless!
107
- #
108
-
109
- def headless!
110
- add_argument '-headless'
111
- end
112
-
113
102
  #
114
103
  # Sets Firefox profile.
115
104
  #
@@ -177,7 +166,7 @@ module Selenium
177
166
  end
178
167
 
179
168
  def camelize?(key)
180
- key != "prefs"
169
+ key != 'prefs'
181
170
  end
182
171
  end # Options
183
172
  end # Firefox
@@ -26,11 +26,11 @@ module Selenium
26
26
  VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String].freeze
27
27
 
28
28
  DEFAULT_PREFERENCES = {
29
- "browser.newtabpage.enabled" => false,
30
- "browser.startup.homepage" => "about:blank",
31
- "browser.usedOnWindows10.introURL" => "about:blank",
32
- "network.captive-portal-service.enabled" => false,
33
- "security.csp.enable" => false
29
+ 'browser.newtabpage.enabled' => false,
30
+ 'browser.startup.homepage' => 'about:blank',
31
+ 'browser.usedOnWindows10.introURL' => 'about:blank',
32
+ 'network.captive-portal-service.enabled' => false,
33
+ 'security.csp.enable' => false
34
34
  }.freeze
35
35
 
36
36
  attr_reader :name, :log_file
@@ -143,7 +143,7 @@ module Selenium
143
143
  end
144
144
  end
145
145
 
146
- alias_method :as_json, :encoded
146
+ alias as_json encoded
147
147
 
148
148
  private
149
149
 
@@ -160,7 +160,7 @@ module Selenium
160
160
  destination = File.join(directory, 'extensions')
161
161
 
162
162
  @extensions.each do |name, extension|
163
- WebDriver.logger.debug({extenstion: name}.inspect)
163
+ WebDriver.logger.debug({extension: name}.inspect, id: :firefox_profile)
164
164
  extension.write_to(destination)
165
165
  end
166
166
  end
@@ -23,25 +23,7 @@ module Selenium
23
23
  class Service < WebDriver::Service
24
24
  DEFAULT_PORT = 4444
25
25
  EXECUTABLE = 'geckodriver'
26
- MISSING_TEXT = <<~ERROR
27
- Unable to find Mozilla geckodriver. Please download the server from
28
- https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
29
- More info at https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver.
30
- ERROR
31
26
  SHUTDOWN_SUPPORTED = false
32
-
33
- private
34
-
35
- # NOTE: This processing is deprecated
36
- def extract_service_args(driver_opts)
37
- driver_args = super
38
- driver_opts = driver_opts.dup
39
- driver_args << "--binary=#{driver_opts[:binary]}" if driver_opts.key?(:binary)
40
- driver_args << "--log=#{driver_opts[:log]}" if driver_opts.key?(:log)
41
- driver_args << "--marionette-port=#{driver_opts[:marionette_port]}" if driver_opts.key?(:marionette_port)
42
- driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
43
- driver_args
44
- end
45
27
  end # Service
46
28
  end # Firefox
47
29
  end # WebDriver
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module IE
23
-
24
23
  #
25
24
  # Driver implementation for Internet Explorer supporting
26
25
  # both OSS and W3C dialects of JSON wire protocol.
@@ -30,6 +29,13 @@ module Selenium
30
29
  class Driver < WebDriver::Driver
31
30
  EXTENSIONS = [DriverExtensions::HasWebStorage].freeze
32
31
 
32
+ include LocalDriver
33
+
34
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
35
+ caps, url = initialize_local_driver(capabilities, options, service, url)
36
+ super(caps: caps, url: url, **opts)
37
+ end
38
+
33
39
  def browser
34
40
  :internet_explorer
35
41
  end
@@ -41,7 +41,8 @@ module Selenium
41
41
  use_per_process_proxy: 'ie.usePerProcessProxy',
42
42
  use_legacy_file_upload_dialog_handling: 'ie.useLegacyFileUploadDialogHandling',
43
43
  attach_to_edge_chrome: 'ie.edgechromium',
44
- edge_executable_path: 'ie.edgepath'
44
+ edge_executable_path: 'ie.edgepath',
45
+ ignore_process_match: 'ie.ignoreprocessmatch'
45
46
  }.freeze
46
47
  BROWSER = 'internet explorer'
47
48
 
@@ -23,29 +23,7 @@ module Selenium
23
23
  class Service < WebDriver::Service
24
24
  DEFAULT_PORT = 5555
25
25
  EXECUTABLE = 'IEDriverServer'
26
- MISSING_TEXT = <<~ERROR
27
- Unable to find IEDriverServer. Please download the server from
28
- https://www.selenium.dev/downloads/ and place it somewhere on your PATH.
29
- More info at https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver.
30
- ERROR
31
26
  SHUTDOWN_SUPPORTED = true
32
-
33
- private
34
-
35
- # NOTE: This processing is deprecated
36
- def extract_service_args(driver_opts)
37
- driver_args = super
38
- driver_opts = driver_opts.dup
39
- driver_args << "--log-level=#{driver_opts[:log_level].to_s.upcase}" if driver_opts.key?(:log_level)
40
- driver_args << "--log-file=#{driver_opts[:log_file]}" if driver_opts.key?(:log_file)
41
- if driver_opts.key?(:implementation)
42
- driver_args << "--implementation=#{driver_opts[:implementation].to_s.upcase}"
43
- end
44
- driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
45
- driver_args << "--extract_path=#{driver_opts[:extract_path]}" if driver_opts.key?(:extract_path)
46
- driver_args << "--silent" if driver_opts[:silent] == true
47
- driver_args
48
- end
49
27
  end # Server
50
28
  end # IE
51
29
  end # WebDriver
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
-
24
23
  #
25
24
  # https://w3c.github.io/webdriver/#endpoints
26
25
  # @api private
@@ -165,7 +164,6 @@ module Selenium
165
164
  set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv']
166
165
 
167
166
  }.freeze
168
-
169
167
  end # Bridge
170
168
  end # Remote
171
169
  end # WebDriver
@@ -21,6 +21,7 @@ module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
23
  class Bridge
24
+ autoload :COMMANDS, 'selenium/webdriver/remote/bridge/commands'
24
25
  include Atoms
25
26
 
26
27
  PORT = 4444
@@ -186,6 +187,7 @@ module Selenium
186
187
  execute :delete_session
187
188
  http.close
188
189
  rescue *QUIT_ERRORS
190
+ nil
189
191
  end
190
192
 
191
193
  def close
@@ -367,18 +369,10 @@ module Selenium
367
369
  # actions
368
370
  #
369
371
 
370
- def action(deprecated_async = nil, async: false, devices: [], duration: 250)
371
- ActionBuilder.new self, nil, nil, deprecated_async, async: async, devices: devices, duration: duration
372
- end
373
- alias_method :actions, :action
374
-
375
- def mouse
376
- raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead'
377
- end
378
-
379
- def keyboard
380
- raise Error::UnsupportedOperationError, '#keyboard is no longer supported, use #action instead'
372
+ def action(async: false, devices: [], duration: 250)
373
+ ActionBuilder.new self, async: async, devices: devices, duration: duration
381
374
  end
375
+ alias actions action
382
376
 
383
377
  def send_actions(data)
384
378
  execute :actions, {}, {actions: data}
@@ -400,7 +394,7 @@ module Selenium
400
394
  # TODO: rework file detectors before Selenium 4.0
401
395
  if @file_detector
402
396
  local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
403
- if local_files.any?
397
+ if local_files&.any?
404
398
  keys = local_files.map { |local_file| upload(local_file) }
405
399
  keys = Array(keys.join("\n"))
406
400
  end
@@ -413,7 +407,8 @@ module Selenium
413
407
 
414
408
  def upload(local_file)
415
409
  unless File.file?(local_file)
416
- WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
410
+ WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!",
411
+ id: :file_detector)
417
412
  raise Error::WebDriverError, "You are trying to work with something that isn't a file."
418
413
  end
419
414
 
@@ -425,7 +420,7 @@ module Selenium
425
420
  end
426
421
 
427
422
  def submit_element(element)
428
- script = "var form = arguments[0];\n" \
423
+ script = "/* submitForm */ var form = arguments[0];\n" \
429
424
  "while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
430
425
  "form = form.parentNode;\n" \
431
426
  "}\n" \
@@ -437,7 +432,7 @@ module Selenium
437
432
 
438
433
  execute_script(script, Element::ELEMENT_KEY => element)
439
434
  rescue Error::JavascriptError
440
- raise Error::UnsupportedOperationError, "To submit an element, it must be nested inside a form element"
435
+ raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
441
436
  end
442
437
 
443
438
  #
@@ -449,7 +444,7 @@ module Selenium
449
444
  end
450
445
 
451
446
  def element_attribute(element, name)
452
- WebDriver.logger.info "Using script for :getAttribute of #{name}"
447
+ WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
453
448
  execute_atom :getAttribute, element, name
454
449
  end
455
450
 
@@ -509,7 +504,7 @@ module Selenium
509
504
  end
510
505
 
511
506
  def element_displayed?(element)
512
- WebDriver.logger.info 'Using script for :isDisplayed'
507
+ WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
513
508
  execute_atom :isDisplayed, element
514
509
  end
515
510
 
@@ -525,7 +520,7 @@ module Selenium
525
520
  Element.new self, element_id_from(execute(:get_active_element))
526
521
  end
527
522
 
528
- alias_method :switch_to_active_element, :active_element
523
+ alias switch_to_active_element active_element
529
524
 
530
525
  def find_element_by(how, what, parent_ref = [])
531
526
  how, what = convert_locator(how, what)
@@ -621,7 +616,7 @@ module Selenium
621
616
  raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
622
617
  end
623
618
 
624
- WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
619
+ WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
625
620
  http.call(verb, path, command_hash)['value']
626
621
  end
627
622
 
@@ -688,7 +683,7 @@ module Selenium
688
683
  [how, what]
689
684
  end
690
685
 
691
- ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/.freeze
686
+ ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
692
687
  UNICODE_CODE_POINT = 30
693
688
 
694
689
  # Escapes invalid characters in CSS selector.
@@ -20,14 +20,12 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
-
24
23
  #
25
24
  # Specification of the desired and/or actual capabilities of the browser that the
26
25
  # server is being asked to create.
27
26
  #
28
27
 
29
28
  class Capabilities
30
-
31
29
  KNOWN = [
32
30
  :browser_name,
33
31
  :browser_version,
@@ -55,60 +53,11 @@ module Selenium
55
53
  end
56
54
  end
57
55
 
58
- #
59
- # Backward compatibility
60
- #
61
-
62
- alias_method :version, :browser_version
63
- alias_method :version=, :browser_version=
64
- alias_method :platform, :platform_name
65
- alias_method :platform=, :platform_name=
66
-
67
56
  #
68
57
  # Convenience methods for the common choices.
69
58
  #
70
59
 
71
60
  class << self
72
- def chrome(opts = {})
73
- new({
74
- browser_name: 'chrome'
75
- }.merge(opts))
76
- end
77
-
78
- def edge(opts = {})
79
- new({
80
- browser_name: 'MicrosoftEdge'
81
- }.merge(opts))
82
- end
83
- alias_method :microsoftedge, :edge
84
-
85
- def firefox(opts = {})
86
- new({
87
- browser_name: 'firefox'
88
- }.merge(opts))
89
- end
90
- alias_method :ff, :firefox
91
-
92
- def safari(opts = {})
93
- new({
94
- browser_name: Selenium::WebDriver::Safari.technology_preview? ? "Safari Technology Preview" : 'safari'
95
- }.merge(opts))
96
- end
97
-
98
- def htmlunit(opts = {})
99
- new({
100
- browser_name: 'htmlunit'
101
- }.merge(opts))
102
- end
103
-
104
- def internet_explorer(opts = {})
105
- new({
106
- browser_name: 'internet explorer',
107
- platform_name: :windows
108
- }.merge(opts))
109
- end
110
- alias_method :ie, :internet_explorer
111
-
112
61
  def always_match(capabilities)
113
62
  new(always_match: capabilities)
114
63
  end
@@ -134,7 +83,8 @@ module Selenium
134
83
 
135
84
  # Remote Server Specific
136
85
  if data.key?('webdriver.remote.sessionid')
137
- caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
86
+ caps[:remote_session_id] =
87
+ data.delete('webdriver.remote.sessionid')
138
88
  end
139
89
 
140
90
  KNOWN.each do |cap|
@@ -269,7 +219,7 @@ module Selenium
269
219
  as_json == other.as_json
270
220
  end
271
221
 
272
- alias_method :eql?, :==
222
+ alias eql? ==
273
223
 
274
224
  protected
275
225
 
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
-
24
23
  #
25
24
  # Driver implementation for remote server.
26
25
  # @api private
@@ -30,17 +29,12 @@ module Selenium
30
29
  include DriverExtensions::UploadsFiles
31
30
  include DriverExtensions::HasSessionId
32
31
 
33
- def initialize(bridge: nil, listener: nil, **opts)
34
- desired_capabilities = opts[:desired_capabilities]
35
- if desired_capabilities.is_a?(Symbol)
36
- unless Remote::Capabilities.respond_to?(desired_capabilities)
37
- raise Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
38
- end
32
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
33
+ raise ArgumentError, "Can not set :service object on #{self.class}" if service
39
34
 
40
- opts[:desired_capabilities] = Remote::Capabilities.__send__(desired_capabilities)
41
- end
42
- opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
43
- super
35
+ url ||= "http://#{Platform.localhost}:4444/wd/hub"
36
+ caps = process_options(options, capabilities)
37
+ super(caps: caps, url: url, **opts)
44
38
  @bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
45
39
  end
46
40
 
@@ -51,8 +45,20 @@ module Selenium
51
45
  end
52
46
 
53
47
  def devtools_version
54
- capabilities['se:cdpVersion']&.split('.')&.first ||
55
- raise(Error::WebDriverError, "DevTools is not supported by the Remote Server")
48
+ cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
49
+ raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
50
+
51
+ Integer(cdp_version)
52
+ end
53
+
54
+ def process_options(options, capabilities)
55
+ if options && capabilities
56
+ msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
57
+ raise ArgumentError, msg
58
+ elsif options.nil? && capabilities.nil?
59
+ raise ArgumentError, "#{self.class} needs :options to be set"
60
+ end
61
+ options ? options.as_json : generate_capabilities(capabilities)
56
62
  end
57
63
  end # Driver
58
64
  end # Remote