selenium-webdriver 4.1.0 → 4.12.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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +271 -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 +36 -39
  11. data/lib/selenium/webdriver/atoms/findElements.js +4 -5
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +1 -1
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +1 -1
  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 +51 -0
  26. data/lib/selenium/webdriver/bidi.rb +56 -0
  27. data/lib/selenium/webdriver/chrome/driver.rb +9 -29
  28. data/lib/selenium/webdriver/chrome/features.rb +6 -68
  29. data/lib/selenium/webdriver/chrome/options.rb +3 -223
  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/chrome.rb +0 -16
  33. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  34. data/lib/selenium/webdriver/chromium/features.rb +103 -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 +64 -22
  39. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  40. data/lib/selenium/webdriver/common/driver.rb +31 -81
  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_remote_status.rb → has_bidi.rb} +10 -5
  47. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -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 +1 -4
  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_launching.rb +0 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -2
  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 +2 -69
  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 +1 -3
  59. data/lib/selenium/webdriver/common/driver_finder.rb +45 -0
  60. data/lib/selenium/webdriver/common/element.rb +8 -8
  61. data/lib/selenium/webdriver/common/error.rb +28 -5
  62. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  63. data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
  64. data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
  65. data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
  66. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
  67. data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
  68. data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
  69. data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
  70. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
  71. data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
  72. data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
  73. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
  74. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
  75. data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
  76. data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
  77. data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
  78. data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
  79. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
  80. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
  81. data/lib/selenium/webdriver/common/keys.rb +1 -0
  82. data/lib/selenium/webdriver/common/local_driver.rb +46 -0
  83. data/lib/selenium/webdriver/common/logger.rb +90 -25
  84. data/lib/selenium/webdriver/common/manager.rb +0 -27
  85. data/lib/selenium/webdriver/common/options.rb +13 -17
  86. data/lib/selenium/webdriver/common/platform.rb +5 -51
  87. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  88. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  89. data/lib/selenium/webdriver/common/proxy.rb +2 -2
  90. data/lib/selenium/webdriver/common/search_context.rb +0 -6
  91. data/lib/selenium/webdriver/common/selenium_manager.rb +129 -0
  92. data/lib/selenium/webdriver/common/service.rb +17 -30
  93. data/lib/selenium/webdriver/common/service_manager.rb +8 -15
  94. data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
  95. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  96. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  97. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  98. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  99. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  100. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
  101. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
  102. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  103. data/lib/selenium/webdriver/common/websocket_connection.rb +164 -0
  104. data/lib/selenium/webdriver/common/window.rb +6 -6
  105. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  106. data/lib/selenium/webdriver/common.rb +21 -3
  107. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  108. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  109. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  110. data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
  111. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  112. data/lib/selenium/webdriver/devtools/request.rb +1 -3
  113. data/lib/selenium/webdriver/devtools/response.rb +1 -3
  114. data/lib/selenium/webdriver/devtools.rb +17 -114
  115. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  116. data/lib/selenium/webdriver/edge/features.rb +4 -4
  117. data/lib/selenium/webdriver/edge/options.rb +17 -5
  118. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  119. data/lib/selenium/webdriver/edge/service.rb +1 -7
  120. data/lib/selenium/webdriver/edge.rb +0 -2
  121. data/lib/selenium/webdriver/firefox/driver.rb +9 -2
  122. data/lib/selenium/webdriver/firefox/features.rb +6 -6
  123. data/lib/selenium/webdriver/firefox/options.rb +7 -16
  124. data/lib/selenium/webdriver/firefox/profile.rb +8 -12
  125. data/lib/selenium/webdriver/firefox/service.rb +0 -18
  126. data/lib/selenium/webdriver/firefox/util.rb +46 -0
  127. data/lib/selenium/webdriver/firefox.rb +1 -14
  128. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  129. data/lib/selenium/webdriver/ie/options.rb +4 -3
  130. data/lib/selenium/webdriver/ie/service.rb +0 -22
  131. data/lib/selenium/webdriver/ie.rb +0 -14
  132. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +15 -8
  133. data/lib/selenium/webdriver/remote/bridge.rb +65 -35
  134. data/lib/selenium/webdriver/remote/capabilities.rb +3 -53
  135. data/lib/selenium/webdriver/remote/driver.rb +31 -14
  136. data/lib/selenium/webdriver/remote/http/common.rb +3 -3
  137. data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
  138. data/lib/selenium/webdriver/remote/http/default.rb +8 -14
  139. data/lib/selenium/webdriver/remote/response.rb +2 -3
  140. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  141. data/lib/selenium/webdriver/remote.rb +0 -1
  142. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  143. data/lib/selenium/webdriver/safari/features.rb +0 -2
  144. data/lib/selenium/webdriver/safari/options.rb +5 -1
  145. data/lib/selenium/webdriver/safari/service.rb +10 -4
  146. data/lib/selenium/webdriver/safari.rb +1 -15
  147. data/lib/selenium/webdriver/support/color.rb +22 -22
  148. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  149. data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
  150. data/lib/selenium/webdriver/support/guards.rb +1 -1
  151. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  152. data/lib/selenium/webdriver/support/select.rb +3 -1
  153. data/lib/selenium/webdriver/version.rb +1 -1
  154. data/lib/selenium/webdriver.rb +6 -4
  155. data/selenium-webdriver.gemspec +14 -12
  156. metadata +73 -63
  157. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
  158. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  159. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -25,11 +25,12 @@ module Selenium
25
25
 
26
26
  KEY = 'moz:firefoxOptions'
27
27
 
28
- # see: https://firefox-source-docs.mozilla.org/testing/geckodriver/Capabilities.html
28
+ # see: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions
29
29
  CAPABILITIES = {binary: 'binary',
30
30
  args: 'args',
31
31
  log: 'log',
32
32
  prefs: 'prefs',
33
+ env: 'env',
33
34
  android_package: 'androidPackage',
34
35
  android_activity: 'androidActivity',
35
36
  android_device_serial: 'androidDeviceSerial',
@@ -44,7 +45,7 @@ module Selenium
44
45
  #
45
46
  # @example
46
47
  # options = Selenium::WebDriver::Firefox::Options.new(args: ['--host=127.0.0.1'])
47
- # driver = Selenium::WebDriver.for :firefox, capabilities: options
48
+ # driver = Selenium::WebDriver.for :firefox, options: options
48
49
  #
49
50
  # @param [Hash] opts the pre-defined options to create the Firefox::Options with
50
51
  # @option opts [String] :binary Path to the Firefox executable to use
@@ -56,12 +57,14 @@ module Selenium
56
57
  #
57
58
 
58
59
  def initialize(log_level: nil, **opts)
59
- @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)
60
62
 
61
63
  super(**opts)
62
64
 
63
65
  @options[:args] ||= []
64
66
  @options[:prefs] ||= {}
67
+ @options[:env] ||= {}
65
68
  @options[:log] ||= {level: log_level} if log_level
66
69
 
67
70
  process_profile(@options.delete(:profile))
@@ -96,18 +99,6 @@ module Selenium
96
99
  @options[:prefs][name] = value
97
100
  end
98
101
 
99
- #
100
- # Run Firefox in headless mode.
101
- #
102
- # @example Enable headless mode
103
- # options = Selenium::WebDriver::Firefox::Options.new
104
- # options.headless!
105
- #
106
-
107
- def headless!
108
- add_argument '-headless'
109
- end
110
-
111
102
  #
112
103
  # Sets Firefox profile.
113
104
  #
@@ -175,7 +166,7 @@ module Selenium
175
166
  end
176
167
 
177
168
  def camelize?(key)
178
- key != "prefs"
169
+ key != 'prefs'
179
170
  end
180
171
  end # Options
181
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
@@ -96,7 +96,7 @@ module Selenium
96
96
  raise TypeError, "expected one of #{VALID_PREFERENCE_TYPES.inspect}, got #{value.inspect}:#{value.class}"
97
97
  end
98
98
 
99
- if value.is_a?(String) && stringified?(value)
99
+ if value.is_a?(String) && Util.stringified?(value)
100
100
  raise ArgumentError, "preference values must be plain strings: #{key.inspect} => #{value.inspect}"
101
101
  end
102
102
 
@@ -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
@@ -221,10 +221,6 @@ module Selenium
221
221
  end
222
222
  end
223
223
  end
224
-
225
- def stringified?(str)
226
- /^".*"$/.match?(str)
227
- end
228
224
  end # Profile
229
225
  end # Firefox
230
226
  end # WebDriver
@@ -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
@@ -0,0 +1,46 @@
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 Firefox
23
+ # @api private
24
+ module Util
25
+ module_function
26
+
27
+ def app_data_path
28
+ case Platform.os
29
+ when :windows
30
+ "#{ENV.fetch('APPDATA')}\\Mozilla\\Firefox"
31
+ when :macosx
32
+ "#{Platform.home}/Library/Application Support/Firefox"
33
+ when :unix, :linux
34
+ "#{Platform.home}/.mozilla/firefox"
35
+ else
36
+ raise "Unknown os: #{Platform.os}"
37
+ end
38
+ end
39
+
40
+ def stringified?(str)
41
+ str =~ /^".*"$/
42
+ end
43
+ end # Util
44
+ end # Firefox
45
+ end # WebDriver
46
+ end # Selenium
@@ -24,6 +24,7 @@ require 'rexml/document'
24
24
  module Selenium
25
25
  module WebDriver
26
26
  module Firefox
27
+ autoload :Util, 'selenium/webdriver/firefox/util'
27
28
  autoload :Extension, 'selenium/webdriver/firefox/extension'
28
29
  autoload :ProfilesIni, 'selenium/webdriver/firefox/profiles_ini'
29
30
  autoload :Profile, 'selenium/webdriver/firefox/profile'
@@ -41,20 +42,6 @@ module Selenium
41
42
  # until WebDriver Bidi is available.
42
43
  DEVTOOLS_VERSION = 85
43
44
 
44
- def self.driver_path=(path)
45
- WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path=',
46
- 'Selenium::WebDriver::Firefox::Service#driver_path=',
47
- id: :driver_path
48
- Selenium::WebDriver::Firefox::Service.driver_path = path
49
- end
50
-
51
- def self.driver_path
52
- WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path',
53
- 'Selenium::WebDriver::Firefox::Service#driver_path',
54
- id: :driver_path
55
- Selenium::WebDriver::Firefox::Service.driver_path
56
- end
57
-
58
45
  def self.path=(path)
59
46
  Platform.assert_executable path
60
47
  @path = path
@@ -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
@@ -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
@@ -23,20 +23,6 @@ module Selenium
23
23
  autoload :Driver, 'selenium/webdriver/ie/driver'
24
24
  autoload :Options, 'selenium/webdriver/ie/options'
25
25
  autoload :Service, 'selenium/webdriver/ie/service'
26
-
27
- def self.driver_path=(path)
28
- WebDriver.logger.deprecate 'Selenium::WebDriver::IE#driver_path=',
29
- 'Selenium::WebDriver::IE::Service#driver_path=',
30
- id: :driver_path
31
- Selenium::WebDriver::IE::Service.driver_path = path
32
- end
33
-
34
- def self.driver_path
35
- WebDriver.logger.deprecate 'Selenium::WebDriver::IE#driver_path',
36
- 'Selenium::WebDriver::IE::Service#driver_path',
37
- id: :driver_path
38
- Selenium::WebDriver::IE::Service.driver_path
39
- end
40
26
  end # IE
41
27
  end # WebDriver
42
28
  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
@@ -60,10 +59,6 @@ module Selenium
60
59
  fullscreen_window: [:post, 'session/:session_id/window/fullscreen'],
61
60
  minimize_window: [:post, 'session/:session_id/window/minimize'],
62
61
  maximize_window: [:post, 'session/:session_id/window/maximize'],
63
- set_window_size: [:post, 'session/:session_id/window/size'],
64
- get_window_size: [:get, 'session/:session_id/window/size'],
65
- set_window_position: [:post, 'session/:session_id/window/position'],
66
- get_window_position: [:get, 'session/:session_id/window/position'],
67
62
  set_window_rect: [:post, 'session/:session_id/window/rect'],
68
63
  get_window_rect: [:get, 'session/:session_id/window/rect'],
69
64
  switch_to_frame: [:post, 'session/:session_id/frame'],
@@ -130,7 +125,6 @@ module Selenium
130
125
  #
131
126
 
132
127
  element_click: [:post, 'session/:session_id/element/:id/click'],
133
- element_tap: [:post, 'session/:session_id/element/:id/tap'],
134
128
  element_clear: [:post, 'session/:session_id/element/:id/clear'],
135
129
  element_send_keys: [:post, 'session/:session_id/element/:id/value'],
136
130
 
@@ -154,9 +148,22 @@ module Selenium
154
148
  # server extensions
155
149
  #
156
150
 
157
- upload_file: [:post, 'session/:session_id/se/file']
158
- }.freeze
151
+ upload_file: [:post, 'session/:session_id/se/file'],
159
152
 
153
+ #
154
+ # virtual-authenticator
155
+ #
156
+
157
+ add_virtual_authenticator: [:post, 'session/:session_id/webauthn/authenticator'],
158
+ remove_virtual_authenticator: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId'],
159
+ add_credential: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/credential'],
160
+ get_credentials: [:get, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
161
+ remove_credential: [:delete,
162
+ 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials/:credentialId'],
163
+ remove_all_credentials: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
164
+ set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv']
165
+
166
+ }.freeze
160
167
  end # Bridge
161
168
  end # Remote
162
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
@@ -30,8 +31,8 @@ module Selenium
30
31
 
31
32
  #
32
33
  # Initializes the bridge with the given server URL
33
- # @param [String, URI] :url url for the remote server
34
- # @param [Object] :http_client an HTTP client instance that implements the same protocol as Http::Default
34
+ # @param [String, URI] url url for the remote server
35
+ # @param [Object] http_client an HTTP client instance that implements the same protocol as Http::Default
35
36
  # @api private
36
37
  #
37
38
 
@@ -118,7 +119,7 @@ module Selenium
118
119
  end
119
120
 
120
121
  def alert=(keys)
121
- execute :send_alert_text, {}, {value: keys.split(//), text: keys}
122
+ execute :send_alert_text, {}, {value: keys.chars, text: keys}
122
123
  end
123
124
 
124
125
  def alert_text
@@ -146,9 +147,7 @@ module Selenium
146
147
  end
147
148
 
148
149
  def page_source
149
- execute_script('var source = document.documentElement.outerHTML;' \
150
- 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
151
- 'return source;')
150
+ execute :get_page_source
152
151
  end
153
152
 
154
153
  #
@@ -188,6 +187,7 @@ module Selenium
188
187
  execute :delete_session
189
188
  http.close
190
189
  rescue *QUIT_ERRORS
190
+ nil
191
191
  end
192
192
 
193
193
  def close
@@ -369,21 +369,10 @@ module Selenium
369
369
  # actions
370
370
  #
371
371
 
372
- def action(async = false)
373
- ActionBuilder.new self,
374
- Interactions.pointer(:mouse, name: 'mouse'),
375
- Interactions.key('keyboard'),
376
- async
377
- end
378
- alias_method :actions, :action
379
-
380
- def mouse
381
- raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead'
382
- end
383
-
384
- def keyboard
385
- 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
386
374
  end
375
+ alias actions action
387
376
 
388
377
  def send_actions(data)
389
378
  execute :actions, {}, {actions: data}
@@ -405,20 +394,21 @@ module Selenium
405
394
  # TODO: rework file detectors before Selenium 4.0
406
395
  if @file_detector
407
396
  local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
408
- if local_files.any?
397
+ if local_files&.any?
409
398
  keys = local_files.map { |local_file| upload(local_file) }
410
399
  keys = Array(keys.join("\n"))
411
400
  end
412
401
  end
413
402
 
414
403
  # Keep .split(//) for backward compatibility for now
415
- text = keys.join('')
416
- execute :element_send_keys, {id: element}, {value: text.split(//), text: text}
404
+ text = keys.join
405
+ execute :element_send_keys, {id: element}, {value: text.chars, text: text}
417
406
  end
418
407
 
419
408
  def upload(local_file)
420
409
  unless File.file?(local_file)
421
- 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)
422
412
  raise Error::WebDriverError, "You are trying to work with something that isn't a file."
423
413
  end
424
414
 
@@ -430,10 +420,19 @@ module Selenium
430
420
  end
431
421
 
432
422
  def submit_element(element)
433
- form = find_element_by('xpath', "./ancestor-or-self::form", [:element, element])
434
- execute_script("var e = arguments[0].ownerDocument.createEvent('Event');" \
435
- "e.initEvent('submit', true, true);" \
436
- 'if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }', form.as_json)
423
+ script = "/* submitForm */ var form = arguments[0];\n" \
424
+ "while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
425
+ "form = form.parentNode;\n" \
426
+ "}\n" \
427
+ "if (!form) { throw Error('Unable to find containing form element'); }\n" \
428
+ "if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" \
429
+ "var e = form.ownerDocument.createEvent('Event');\n" \
430
+ "e.initEvent('submit', true, true);\n" \
431
+ "if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n"
432
+
433
+ execute_script(script, Element::ELEMENT_KEY => element)
434
+ rescue Error::JavascriptError
435
+ raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
437
436
  end
438
437
 
439
438
  #
@@ -445,7 +444,7 @@ module Selenium
445
444
  end
446
445
 
447
446
  def element_attribute(element, name)
448
- WebDriver.logger.info "Using script for :getAttribute of #{name}"
447
+ WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
449
448
  execute_atom :getAttribute, element, name
450
449
  end
451
450
 
@@ -505,7 +504,7 @@ module Selenium
505
504
  end
506
505
 
507
506
  def element_displayed?(element)
508
- WebDriver.logger.info 'Using script for :isDisplayed'
507
+ WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
509
508
  execute_atom :isDisplayed, element
510
509
  end
511
510
 
@@ -521,7 +520,7 @@ module Selenium
521
520
  Element.new self, element_id_from(execute(:get_active_element))
522
521
  end
523
522
 
524
- alias_method :switch_to_active_element, :active_element
523
+ alias switch_to_active_element active_element
525
524
 
526
525
  def find_element_by(how, what, parent_ref = [])
527
526
  how, what = convert_locator(how, what)
@@ -564,6 +563,39 @@ module Selenium
564
563
  ShadowRoot.new self, shadow_root_id_from(id)
565
564
  end
566
565
 
566
+ #
567
+ # virtual-authenticator
568
+ #
569
+
570
+ def add_virtual_authenticator(options)
571
+ authenticator_id = execute :add_virtual_authenticator, {}, options.as_json
572
+ VirtualAuthenticator.new(self, authenticator_id, options)
573
+ end
574
+
575
+ def remove_virtual_authenticator(id)
576
+ execute :remove_virtual_authenticator, {authenticatorId: id}
577
+ end
578
+
579
+ def add_credential(credential, id)
580
+ execute :add_credential, {authenticatorId: id}, credential
581
+ end
582
+
583
+ def credentials(authenticator_id)
584
+ execute :get_credentials, {authenticatorId: authenticator_id}
585
+ end
586
+
587
+ def remove_credential(credential_id, authenticator_id)
588
+ execute :remove_credential, {credentialId: credential_id, authenticatorId: authenticator_id}
589
+ end
590
+
591
+ def remove_all_credentials(authenticator_id)
592
+ execute :remove_all_credentials, {authenticatorId: authenticator_id}
593
+ end
594
+
595
+ def user_verified(verified, authenticator_id)
596
+ execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
597
+ end
598
+
567
599
  private
568
600
 
569
601
  #
@@ -584,7 +616,7 @@ module Selenium
584
616
  raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
585
617
  end
586
618
 
587
- WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
619
+ WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
588
620
  http.call(verb, path, command_hash)['value']
589
621
  end
590
622
 
@@ -639,8 +671,6 @@ module Selenium
639
671
  when 'name'
640
672
  how = 'css selector'
641
673
  what = "*[name='#{escape_css(what.to_s)}']"
642
- when 'tag name'
643
- how = 'css selector'
644
674
  end
645
675
 
646
676
  if what.is_a?(Hash)
@@ -653,7 +683,7 @@ module Selenium
653
683
  [how, what]
654
684
  end
655
685
 
656
- ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/.freeze
686
+ ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
657
687
  UNICODE_CODE_POINT = 30
658
688
 
659
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