selenium-webdriver 4.5.0 → 4.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +219 -1
  3. data/Gemfile +3 -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 +8 -22
  11. data/lib/selenium/webdriver/atoms/findElements.js +5 -5
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +2 -1
  14. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  15. data/lib/selenium/webdriver/atoms.rb +5 -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/{common/driver_extensions/has_location.rb → bidi/log/filter_by.rb} +14 -11
  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 -30
  28. data/lib/selenium/webdriver/chrome/features.rb +8 -71
  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 +4 -19
  32. data/lib/selenium/webdriver/chrome.rb +0 -2
  33. data/lib/selenium/webdriver/chromium/driver.rb +60 -0
  34. data/lib/selenium/webdriver/chromium/features.rb +99 -0
  35. data/lib/selenium/webdriver/chromium/options.rb +243 -0
  36. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  37. data/lib/selenium/webdriver/chromium.rb +29 -0
  38. data/lib/selenium/webdriver/common/action_builder.rb +11 -58
  39. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  40. data/lib/selenium/webdriver/common/driver.rb +19 -36
  41. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  42. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  43. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  44. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +0 -2
  47. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +0 -1
  48. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  49. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  51. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb +65 -0
  53. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +0 -1
  55. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  56. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +0 -2
  57. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  58. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +0 -2
  59. data/lib/selenium/webdriver/common/driver_finder.rb +45 -0
  60. data/lib/selenium/webdriver/common/element.rb +6 -6
  61. data/lib/selenium/webdriver/common/error.rb +27 -4
  62. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  63. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +3 -3
  64. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +2 -2
  65. data/lib/selenium/webdriver/common/interactions/scroll.rb +7 -5
  66. data/lib/selenium/webdriver/common/local_driver.rb +46 -0
  67. data/lib/selenium/webdriver/common/logger.rb +91 -26
  68. data/lib/selenium/webdriver/common/options.rb +15 -8
  69. data/lib/selenium/webdriver/common/platform.rb +8 -49
  70. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  71. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  72. data/lib/selenium/webdriver/common/proxy.rb +2 -2
  73. data/lib/selenium/webdriver/common/selenium_manager.rb +140 -0
  74. data/lib/selenium/webdriver/common/service.rb +21 -30
  75. data/lib/selenium/webdriver/common/service_manager.rb +6 -12
  76. data/lib/selenium/webdriver/common/shadow_root.rb +1 -2
  77. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  78. data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
  79. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  80. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  81. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  82. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +8 -6
  83. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +0 -1
  84. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +16 -16
  85. data/lib/selenium/webdriver/common/websocket_connection.rb +12 -4
  86. data/lib/selenium/webdriver/common.rb +5 -2
  87. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  88. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  89. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  90. data/lib/selenium/webdriver/devtools/network_interceptor.rb +4 -7
  91. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  92. data/lib/selenium/webdriver/devtools/request.rb +0 -2
  93. data/lib/selenium/webdriver/devtools/response.rb +0 -2
  94. data/lib/selenium/webdriver/devtools.rb +11 -2
  95. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  96. data/lib/selenium/webdriver/edge/features.rb +7 -4
  97. data/lib/selenium/webdriver/edge/options.rb +17 -5
  98. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  99. data/lib/selenium/webdriver/edge/service.rb +8 -7
  100. data/lib/selenium/webdriver/edge.rb +0 -2
  101. data/lib/selenium/webdriver/firefox/driver.rb +8 -2
  102. data/lib/selenium/webdriver/firefox/features.rb +5 -2
  103. data/lib/selenium/webdriver/firefox/options.rb +2 -14
  104. data/lib/selenium/webdriver/firefox/profile.rb +10 -8
  105. data/lib/selenium/webdriver/firefox/service.rb +0 -18
  106. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  107. data/lib/selenium/webdriver/{common/driver_extensions/has_network_connection.rb → ie/features.rb} +8 -11
  108. data/lib/selenium/webdriver/ie/options.rb +4 -3
  109. data/lib/selenium/webdriver/ie/service.rb +0 -22
  110. data/lib/selenium/webdriver/ie.rb +4 -3
  111. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +0 -8
  112. data/lib/selenium/webdriver/remote/bridge.rb +13 -37
  113. data/lib/selenium/webdriver/remote/capabilities.rb +3 -53
  114. data/lib/selenium/webdriver/remote/driver.rb +35 -13
  115. data/lib/selenium/webdriver/remote/features.rb +75 -0
  116. data/lib/selenium/webdriver/remote/http/common.rb +3 -3
  117. data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
  118. data/lib/selenium/webdriver/remote/http/default.rb +2 -2
  119. data/lib/selenium/webdriver/remote/response.rb +0 -1
  120. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  121. data/lib/selenium/webdriver/remote.rb +1 -1
  122. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  123. data/lib/selenium/webdriver/safari/features.rb +5 -3
  124. data/lib/selenium/webdriver/safari/options.rb +5 -1
  125. data/lib/selenium/webdriver/safari/service.rb +10 -4
  126. data/lib/selenium/webdriver/safari.rb +1 -1
  127. data/lib/selenium/webdriver/support/color.rb +17 -17
  128. data/lib/selenium/webdriver/support/event_firing_bridge.rb +2 -2
  129. data/lib/selenium/webdriver/support/guards/guard.rb +6 -5
  130. data/lib/selenium/webdriver/support/guards/guard_condition.rb +0 -2
  131. data/lib/selenium/webdriver/support/guards.rb +1 -1
  132. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  133. data/lib/selenium/webdriver/support/select.rb +2 -5
  134. data/lib/selenium/webdriver/version.rb +1 -1
  135. data/lib/selenium/webdriver.rb +5 -4
  136. data/selenium-webdriver.gemspec +10 -11
  137. metadata +43 -84
  138. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  139. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -17,8 +17,6 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'net/http'
21
-
22
20
  module Selenium
23
21
  module WebDriver
24
22
  module 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(options: nil, service: nil, url: nil, **opts)
42
+ caps, url = initialize_local_driver(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'],
@@ -30,8 +29,12 @@ module Selenium
30
29
  full_page_screenshot: [:get, 'session/:session_id/moz/screenshot/full']
31
30
  }.freeze
32
31
 
32
+ def command_list
33
+ FIREFOX_COMMANDS.merge(self.class::COMMANDS)
34
+ end
35
+
33
36
  def commands(command)
34
- FIREFOX_COMMANDS[command] || self.class::COMMANDS[command]
37
+ command_list[command]
35
38
  end
36
39
 
37
40
  def install_addon(path, temporary)
@@ -45,7 +45,7 @@ module Selenium
45
45
  #
46
46
  # @example
47
47
  # options = Selenium::WebDriver::Firefox::Options.new(args: ['--host=127.0.0.1'])
48
- # driver = Selenium::WebDriver.for :firefox, capabilities: options
48
+ # driver = Selenium::WebDriver.for :firefox, options: options
49
49
  #
50
50
  # @param [Hash] opts the pre-defined options to create the Firefox::Options with
51
51
  # @option opts [String] :binary Path to the Firefox executable to use
@@ -99,18 +99,6 @@ module Selenium
99
99
  @options[:prefs][name] = value
100
100
  end
101
101
 
102
- #
103
- # Run Firefox in headless mode.
104
- #
105
- # @example Enable headless mode
106
- # options = Selenium::WebDriver::Firefox::Options.new
107
- # options.headless!
108
- #
109
-
110
- def headless!
111
- add_argument '-headless'
112
- end
113
-
114
102
  #
115
103
  # Sets Firefox profile.
116
104
  #
@@ -178,7 +166,7 @@ module Selenium
178
166
  end
179
167
 
180
168
  def camelize?(key)
181
- key != "prefs"
169
+ key != 'prefs'
182
170
  end
183
171
  end # Options
184
172
  end # Firefox
@@ -26,13 +26,15 @@ 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
+ LOCK_FILES = %w[.parentlock parent.lock lock].freeze
37
+
36
38
  attr_reader :name, :log_file
37
39
  attr_writer :secure_ssl, :load_no_focus_lib
38
40
 
@@ -143,7 +145,7 @@ module Selenium
143
145
  end
144
146
  end
145
147
 
146
- alias_method :as_json, :encoded
148
+ alias as_json encoded
147
149
 
148
150
  private
149
151
 
@@ -160,7 +162,7 @@ module Selenium
160
162
  destination = File.join(directory, 'extensions')
161
163
 
162
164
  @extensions.each do |name, extension|
163
- WebDriver.logger.debug({extenstion: name}.inspect)
165
+ WebDriver.logger.debug({extension: name}.inspect, id: :firefox_profile)
164
166
  extension.write_to(destination)
165
167
  end
166
168
  end
@@ -176,7 +178,7 @@ module Selenium
176
178
  end
177
179
 
178
180
  def delete_lock_files(directory)
179
- %w[.parentlock parent.lock].each do |name|
181
+ LOCK_FILES.each do |name|
180
182
  FileUtils.rm_f File.join(directory, name)
181
183
  end
182
184
  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(options: nil, service: nil, url: nil, **opts)
35
+ caps, url = initialize_local_driver(options, service, url)
36
+ super(caps: caps, url: url, **opts)
37
+ end
38
+
33
39
  def browser
34
40
  :internet_explorer
35
41
  end
@@ -17,21 +17,18 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- # TODO: Deprecated; Delete after 4.0 release
21
20
  module Selenium
22
21
  module WebDriver
23
- module DriverExtensions
24
- module HasNetworkConnection
25
- def network_connection_type
26
- raise Error::UnsupportedOperationError,
27
- 'The W3C standard does not currently support getting network connection'
22
+ module IE
23
+ module Features
24
+ def command_list
25
+ self.class::COMMANDS
28
26
  end
29
27
 
30
- def network_connection_type=(*)
31
- raise Error::UnsupportedOperationError,
32
- 'The W3C standard does not currently support setting network connection'
28
+ def commands(command)
29
+ command_list[command]
33
30
  end
34
- end # HasNetworkConnection
35
- end # DriverExtensions
31
+ end # Bridge
32
+ end # Ie
36
33
  end # WebDriver
37
34
  end # Selenium
@@ -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
 
@@ -52,12 +53,12 @@ module Selenium
52
53
  #
53
54
  # @example
54
55
  # options = Selenium::WebDriver::IE::Options.new(args: ['--host=127.0.0.1'])
55
- # driver = Selenium::WebDriver.for(:ie, capabilities: options)
56
+ # driver = Selenium::WebDriver.for(:ie, options: options)
56
57
  #
57
58
  # @example
58
59
  # options = Selenium::WebDriver::IE::Options.new
59
60
  # options.element_scroll_behavior = Selenium::WebDriver::IE::Options::SCROLL_BOTTOM
60
- # driver = Selenium::WebDriver.for(:ie, capabilities: options)
61
+ # driver = Selenium::WebDriver.for(:ie, options: options)
61
62
  #
62
63
  # @param [Hash] opts the pre-defined options
63
64
  # @option opts [Array<String>] args
@@ -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,9 +20,10 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module IE
23
- autoload :Driver, 'selenium/webdriver/ie/driver'
24
- autoload :Options, 'selenium/webdriver/ie/options'
25
- autoload :Service, 'selenium/webdriver/ie/service'
23
+ autoload :Features, 'selenium/webdriver/ie/features'
24
+ autoload :Driver, 'selenium/webdriver/ie/driver'
25
+ autoload :Options, 'selenium/webdriver/ie/options'
26
+ autoload :Service, 'selenium/webdriver/ie/service'
26
27
  end # IE
27
28
  end # WebDriver
28
29
  end # Selenium
@@ -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
@@ -145,12 +144,6 @@ module Selenium
145
144
  take_screenshot: [:get, 'session/:session_id/screenshot'],
146
145
  take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
147
146
 
148
- #
149
- # server extensions
150
- #
151
-
152
- upload_file: [:post, 'session/:session_id/se/file'],
153
-
154
147
  #
155
148
  # virtual-authenticator
156
149
  #
@@ -165,7 +158,6 @@ module Selenium
165
158
  set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv']
166
159
 
167
160
  }.freeze
168
-
169
161
  end # Bridge
170
162
  end # Remote
171
163
  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}
@@ -397,35 +391,17 @@ module Selenium
397
391
  end
398
392
 
399
393
  def send_keys_to_element(element, keys)
400
- # TODO: rework file detectors before Selenium 4.0
401
- if @file_detector
402
- local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
403
- if local_files.any?
404
- keys = local_files.map { |local_file| upload(local_file) }
405
- keys = Array(keys.join("\n"))
406
- end
407
- end
408
-
409
- # Keep .split(//) for backward compatibility for now
394
+ keys = upload_if_necessary(keys) if @file_detector
410
395
  text = keys.join
411
396
  execute :element_send_keys, {id: element}, {value: text.chars, text: text}
412
397
  end
413
398
 
414
- def upload(local_file)
415
- unless File.file?(local_file)
416
- WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
417
- raise Error::WebDriverError, "You are trying to work with something that isn't a file."
418
- end
419
-
420
- execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
421
- end
422
-
423
399
  def clear_element(element)
424
400
  execute :element_clear, id: element
425
401
  end
426
402
 
427
403
  def submit_element(element)
428
- script = "var form = arguments[0];\n" \
404
+ script = "/* submitForm */ var form = arguments[0];\n" \
429
405
  "while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
430
406
  "form = form.parentNode;\n" \
431
407
  "}\n" \
@@ -437,7 +413,7 @@ module Selenium
437
413
 
438
414
  execute_script(script, Element::ELEMENT_KEY => element)
439
415
  rescue Error::JavascriptError
440
- raise Error::UnsupportedOperationError, "To submit an element, it must be nested inside a form element"
416
+ raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
441
417
  end
442
418
 
443
419
  #
@@ -449,7 +425,7 @@ module Selenium
449
425
  end
450
426
 
451
427
  def element_attribute(element, name)
452
- WebDriver.logger.info "Using script for :getAttribute of #{name}"
428
+ WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
453
429
  execute_atom :getAttribute, element, name
454
430
  end
455
431
 
@@ -509,7 +485,7 @@ module Selenium
509
485
  end
510
486
 
511
487
  def element_displayed?(element)
512
- WebDriver.logger.info 'Using script for :isDisplayed'
488
+ WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
513
489
  execute_atom :isDisplayed, element
514
490
  end
515
491
 
@@ -525,7 +501,7 @@ module Selenium
525
501
  Element.new self, element_id_from(execute(:get_active_element))
526
502
  end
527
503
 
528
- alias_method :switch_to_active_element, :active_element
504
+ alias switch_to_active_element active_element
529
505
 
530
506
  def find_element_by(how, what, parent_ref = [])
531
507
  how, what = convert_locator(how, what)
@@ -621,7 +597,7 @@ module Selenium
621
597
  raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
622
598
  end
623
599
 
624
- WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
600
+ WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
625
601
  http.call(verb, path, command_hash)['value']
626
602
  end
627
603
 
@@ -688,7 +664,7 @@ module Selenium
688
664
  [how, what]
689
665
  end
690
666
 
691
- ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/.freeze
667
+ ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
692
668
  UNICODE_CODE_POINT = 30
693
669
 
694
670
  # 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
@@ -29,19 +28,18 @@ module Selenium
29
28
  class Driver < WebDriver::Driver
30
29
  include DriverExtensions::UploadsFiles
31
30
  include DriverExtensions::HasSessionId
31
+ include DriverExtensions::HasFileDownloads
32
32
 
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
33
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
34
+ raise ArgumentError, "Can not set :service object on #{self.class}" if service
39
35
 
40
- opts[:desired_capabilities] = Remote::Capabilities.__send__(desired_capabilities)
41
- end
42
- opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
43
- super
36
+ url ||= "http://#{Platform.localhost}:4444/wd/hub"
37
+ caps = process_options(options, capabilities)
38
+ super(caps: caps, url: url, **opts)
44
39
  @bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
40
+ command_list = @bridge.command_list
41
+ @bridge.extend(WebDriver::Remote::Features)
42
+ @bridge.add_commands(command_list)
45
43
  end
46
44
 
47
45
  private
@@ -51,8 +49,32 @@ module Selenium
51
49
  end
52
50
 
53
51
  def devtools_version
54
- capabilities['se:cdpVersion']&.split('.')&.first ||
55
- raise(Error::WebDriverError, "DevTools is not supported by the Remote Server")
52
+ cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
53
+ raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
54
+
55
+ Integer(cdp_version)
56
+ end
57
+
58
+ def process_options(options, capabilities)
59
+ if options && capabilities
60
+ msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
61
+ raise ArgumentError, msg
62
+ elsif options.nil? && capabilities.nil?
63
+ raise ArgumentError, "#{self.class} needs :options to be set"
64
+ end
65
+ options ? options.as_json : generate_capabilities(capabilities)
66
+ end
67
+
68
+ def generate_capabilities(capabilities)
69
+ Array(capabilities).map { |cap|
70
+ if cap.is_a? Symbol
71
+ cap = WebDriver::Options.send(cap)
72
+ elsif !cap.respond_to? :as_json
73
+ msg = ":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not"
74
+ raise ArgumentError, msg
75
+ end
76
+ cap.as_json
77
+ }.inject(:merge)
56
78
  end
57
79
  end # Driver
58
80
  end # Remote