selenium-webdriver 4.2.0 → 4.4.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +40 -1
  3. data/lib/selenium/server.rb +1 -1
  4. data/lib/selenium/webdriver/chrome/options.rb +14 -0
  5. data/lib/selenium/webdriver/chrome.rb +0 -14
  6. data/lib/selenium/webdriver/common/driver.rb +20 -53
  7. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -67
  8. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +17 -34
  9. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +1 -1
  10. data/lib/selenium/webdriver/common/manager.rb +0 -27
  11. data/lib/selenium/webdriver/common/options.rb +2 -9
  12. data/lib/selenium/webdriver/common/takes_screenshot.rb +1 -1
  13. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +83 -0
  14. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +73 -0
  15. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  16. data/lib/selenium/webdriver/common/websocket_connection.rb +13 -6
  17. data/lib/selenium/webdriver/common/window.rb +6 -6
  18. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  19. data/lib/selenium/webdriver/common.rb +3 -1
  20. data/lib/selenium/webdriver/devtools/network_interceptor.rb +176 -0
  21. data/lib/selenium/webdriver/devtools.rb +1 -0
  22. data/lib/selenium/webdriver/firefox.rb +0 -14
  23. data/lib/selenium/webdriver/ie.rb +0 -14
  24. data/lib/selenium/webdriver/remote/bridge.rb +35 -2
  25. data/lib/selenium/webdriver/remote/commands.rb +15 -1
  26. data/lib/selenium/webdriver/remote/driver.rb +0 -1
  27. data/lib/selenium/webdriver/safari.rb +0 -14
  28. data/lib/selenium/webdriver/version.rb +1 -1
  29. data/selenium-webdriver.gemspec +3 -3
  30. metadata +17 -15
  31. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -31
  32. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
@@ -0,0 +1,62 @@
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
+ #
21
+ # Options for the creation of virtual authenticators.
22
+ # @see http://w3c.github.io/webauthn/#sctn-automation
23
+ #
24
+
25
+ module Selenium
26
+ module WebDriver
27
+ class VirtualAuthenticatorOptions
28
+
29
+ PROTOCOL = {ctap2: "ctap2", u2f: "ctap1/u2f"}.freeze
30
+ TRANSPORT = {ble: "ble", usb: "usb", nfc: "nfc", internal: "internal"}.freeze
31
+
32
+ attr_accessor :protocol, :transport, :resident_key, :user_verification, :user_consenting, :user_verified
33
+ alias_method :resident_key?, :resident_key
34
+ alias_method :user_verification?, :user_verification
35
+ alias_method :user_consenting?, :user_consenting
36
+ alias_method :user_verified?, :user_verified
37
+
38
+ def initialize(protocol: :ctap2, transport: :usb, resident_key: false,
39
+ user_verification: false, user_consenting: true, user_verified: false)
40
+ @protocol = protocol
41
+ @transport = transport
42
+ @resident_key = resident_key
43
+ @user_verification = user_verification
44
+ @user_consenting = user_consenting
45
+ @user_verified = user_verified
46
+ end
47
+
48
+ #
49
+ # @api private
50
+ #
51
+
52
+ def as_json(*)
53
+ {'protocol' => PROTOCOL[protocol],
54
+ 'transport' => TRANSPORT[transport],
55
+ 'hasResidentKey' => resident_key?,
56
+ 'hasUserVerification' => user_verification?,
57
+ 'isUserConsenting' => user_consenting?,
58
+ 'isUserVerified' => user_verified?}
59
+ end
60
+ end # VirtualAuthenticatorOptions
61
+ end # WebDriver
62
+ end # Selenium
@@ -25,10 +25,11 @@ module Selenium
25
25
  RESPONSE_WAIT_TIMEOUT = 30
26
26
  RESPONSE_WAIT_INTERVAL = 0.1
27
27
 
28
+ MAX_LOG_MESSAGE_SIZE = 9999
29
+
28
30
  def initialize(url:)
29
31
  @callback_threads = ThreadGroup.new
30
32
 
31
- @messages = []
32
33
  @session_id = nil
33
34
  @url = url
34
35
 
@@ -49,17 +50,23 @@ module Selenium
49
50
  def send_cmd(**payload)
50
51
  id = next_id
51
52
  data = payload.merge(id: id)
53
+ WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE]
52
54
  data = JSON.generate(data)
53
- WebDriver.logger.debug "WebSocket -> #{data}"
54
-
55
55
  out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text')
56
56
  socket.write(out_frame.to_s)
57
57
 
58
- wait.until { @messages.find { |m| m['id'] == id } }
58
+ wait.until { messages.delete(id) }
59
59
  end
60
60
 
61
61
  private
62
62
 
63
+ # We should be thread-safe to use the hash without synchronization
64
+ # because its keys are WebSocket message identifiers and they should be
65
+ # unique within a devtools session.
66
+ def messages
67
+ @messages ||= {}
68
+ end
69
+
63
70
  def process_handshake
64
71
  socket.print(ws.to_s)
65
72
  ws << socket.readpartial(1024)
@@ -97,8 +104,8 @@ module Selenium
97
104
  return {} if message.empty?
98
105
 
99
106
  message = JSON.parse(message)
100
- @messages << message
101
- WebDriver.logger.debug "WebSocket <- #{message}"
107
+ messages[message["id"]] = message
108
+ WebDriver.logger.debug "WebSocket <- #{message}"[...MAX_LOG_MESSAGE_SIZE]
102
109
 
103
110
  message
104
111
  end
@@ -36,8 +36,8 @@ module Selenium
36
36
 
37
37
  def size=(dimension)
38
38
  unless dimension.respond_to?(:width) && dimension.respond_to?(:height)
39
- raise ArgumentError, "expected #{dimension.inspect}:#{dimension.class}" \
40
- ' to respond to #width and #height'
39
+ raise ArgumentError, "expected #{dimension.inspect}:#{dimension.class} " \
40
+ 'to respond to #width and #height'
41
41
  end
42
42
 
43
43
  @bridge.resize_window dimension.width, dimension.height
@@ -61,8 +61,8 @@ module Selenium
61
61
 
62
62
  def position=(point)
63
63
  unless point.respond_to?(:x) && point.respond_to?(:y)
64
- raise ArgumentError, "expected #{point.inspect}:#{point.class}" \
65
- ' to respond to #x and #y'
64
+ raise ArgumentError, "expected #{point.inspect}:#{point.class} " \
65
+ 'to respond to #x and #y'
66
66
  end
67
67
 
68
68
  @bridge.reposition_window point.x, point.y
@@ -86,8 +86,8 @@ module Selenium
86
86
 
87
87
  def rect=(rectangle)
88
88
  unless %w[x y width height].all? { |val| rectangle.respond_to? val }
89
- raise ArgumentError, "expected #{rectangle.inspect}:#{rectangle.class}" \
90
- ' to respond to #x, #y, #width, and #height'
89
+ raise ArgumentError, "expected #{rectangle.inspect}:#{rectangle.class} " \
90
+ 'to respond to #x, #y, #width, and #height'
91
91
  end
92
92
 
93
93
  @bridge.set_window_rect(x: rectangle.x,
@@ -41,7 +41,7 @@ module Selenium
41
41
  to = File.join(destination, entry.name)
42
42
  dirname = File.dirname(to)
43
43
 
44
- FileUtils.mkdir_p dirname unless File.exist? dirname
44
+ FileUtils.mkdir_p dirname
45
45
  zip.extract(entry, to)
46
46
  end
47
47
  end
@@ -57,6 +57,9 @@ require 'selenium/webdriver/common/interactions/wheel_input'
57
57
  require 'selenium/webdriver/common/interactions/scroll_origin'
58
58
  require 'selenium/webdriver/common/interactions/wheel_actions'
59
59
  require 'selenium/webdriver/common/action_builder'
60
+ require 'selenium/webdriver/common/virtual_authenticator/credential'
61
+ require 'selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options'
62
+ require 'selenium/webdriver/common/virtual_authenticator/virtual_authenticator'
60
63
  require 'selenium/webdriver/common/html5/shared_web_storage'
61
64
  require 'selenium/webdriver/common/html5/local_storage'
62
65
  require 'selenium/webdriver/common/html5/session_storage'
@@ -64,7 +67,6 @@ require 'selenium/webdriver/common/driver_extensions/has_web_storage'
64
67
  require 'selenium/webdriver/common/driver_extensions/downloads_files'
65
68
  require 'selenium/webdriver/common/driver_extensions/has_location'
66
69
  require 'selenium/webdriver/common/driver_extensions/has_session_id'
67
- require 'selenium/webdriver/common/driver_extensions/has_remote_status'
68
70
  require 'selenium/webdriver/common/driver_extensions/has_network_conditions'
69
71
  require 'selenium/webdriver/common/driver_extensions/has_network_connection'
70
72
  require 'selenium/webdriver/common/driver_extensions/has_network_interception'
@@ -0,0 +1,176 @@
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
+ class DevTools
23
+
24
+ #
25
+ # Wraps the network request/response interception, providing
26
+ # thread-safety guarantees and handling special cases such as browser
27
+ # canceling requests midst interception.
28
+ #
29
+ # You should not be using this class directly, use Driver#intercept instead.
30
+ # @api private
31
+ #
32
+
33
+ class NetworkInterceptor
34
+
35
+ # CDP fails to get body on certain responses (301) and raises:
36
+ # "Can only get response body on requests captured after headers received."
37
+ CANNOT_GET_BODY_ON_REDIRECT_ERROR_CODE = "-32000"
38
+
39
+ # CDP fails to operate with intercepted requests.
40
+ # Typical reason is browser cancelling intercepted requests/responses.
41
+ INVALID_INTERCEPTION_ID_ERROR_CODE = "-32602"
42
+
43
+ def initialize(devtools)
44
+ @devtools = devtools
45
+ @lock = Mutex.new
46
+ end
47
+
48
+ def intercept(&block)
49
+ devtools.network.on(:loading_failed) { |params| track_cancelled_request(params) }
50
+ devtools.fetch.on(:request_paused) { |params| request_paused(params, &block) }
51
+
52
+ devtools.network.set_cache_disabled(cache_disabled: true)
53
+ devtools.network.enable
54
+ devtools.fetch.enable(patterns: [{requestStage: 'Request'}, {requestStage: 'Response'}])
55
+ end
56
+
57
+ private
58
+
59
+ attr_accessor :devtools, :lock
60
+
61
+ # We should be thread-safe to use the hash without synchronization
62
+ # because its keys are interception job identifiers and they should be
63
+ # unique within a devtools session.
64
+ def pending_response_requests
65
+ @pending_response_requests ||= {}
66
+ end
67
+
68
+ # Ensure usage of cancelled_requests is thread-safe via synchronization!
69
+ def cancelled_requests
70
+ @cancelled_requests ||= []
71
+ end
72
+
73
+ def track_cancelled_request(data)
74
+ return unless data['canceled']
75
+
76
+ lock.synchronize { cancelled_requests << data['requestId'] }
77
+ end
78
+
79
+ def request_paused(data, &block)
80
+ id = data['requestId']
81
+ network_id = data['networkId']
82
+
83
+ with_cancellable_request(network_id) do
84
+ if response?(data)
85
+ block = pending_response_requests.delete(id)
86
+ intercept_response(id, data, &block)
87
+ else
88
+ intercept_request(id, data, &block)
89
+ end
90
+ end
91
+ end
92
+
93
+ # The presence of any of these fields indicate we're at the response stage.
94
+ # @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#event-requestPaused
95
+ def response?(params)
96
+ params.key?('responseStatusCode') || params.key?('responseErrorReason')
97
+ end
98
+
99
+ def intercept_request(id, params, &block)
100
+ original = DevTools::Request.from(id, params)
101
+ mutable = DevTools::Request.from(id, params)
102
+
103
+ block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall
104
+ pending_response_requests[id] = continue
105
+
106
+ if original == mutable
107
+ continue_request(original.id)
108
+ else
109
+ mutate_request(mutable)
110
+ end
111
+ end
112
+ end
113
+
114
+ def intercept_response(id, params)
115
+ return continue_response(id) unless block_given?
116
+
117
+ body = fetch_response_body(id)
118
+ original = DevTools::Response.from(id, body, params)
119
+ mutable = DevTools::Response.from(id, body, params)
120
+ yield mutable
121
+
122
+ if original == mutable
123
+ continue_response(id)
124
+ else
125
+ mutate_response(mutable)
126
+ end
127
+ end
128
+
129
+ def continue_request(id)
130
+ devtools.fetch.continue_request(request_id: id)
131
+ end
132
+ alias_method :continue_response, :continue_request
133
+
134
+ def mutate_request(request)
135
+ devtools.fetch.continue_request(
136
+ request_id: request.id,
137
+ url: request.url,
138
+ method: request.method,
139
+ post_data: request.post_data,
140
+ headers: request.headers.map do |k, v|
141
+ {name: k, value: v}
142
+ end
143
+ )
144
+ end
145
+
146
+ def mutate_response(response)
147
+ devtools.fetch.fulfill_request(
148
+ request_id: response.id,
149
+ body: (Base64.strict_encode64(response.body) if response.body),
150
+ response_code: response.code,
151
+ response_headers: response.headers.map do |k, v|
152
+ {name: k, value: v}
153
+ end
154
+ )
155
+ end
156
+
157
+ def fetch_response_body(id)
158
+ devtools.fetch.get_response_body(request_id: id).dig('result', 'body')
159
+ rescue Error::WebDriverError => e
160
+ raise unless e.message.start_with?(CANNOT_GET_BODY_ON_REDIRECT_ERROR_CODE)
161
+ end
162
+
163
+ def with_cancellable_request(network_id)
164
+ yield
165
+ rescue Error::WebDriverError => e
166
+ raise if e.message.start_with?(INVALID_INTERCEPTION_ID_ERROR_CODE) && !cancelled?(network_id)
167
+ end
168
+
169
+ def cancelled?(network_id)
170
+ lock.synchronize { !!cancelled_requests.delete(network_id) }
171
+ end
172
+
173
+ end # NetworkInterceptor
174
+ end # DevTools
175
+ end # WebDriver
176
+ end # Selenium
@@ -23,6 +23,7 @@ module Selenium
23
23
  autoload :ConsoleEvent, 'selenium/webdriver/devtools/console_event'
24
24
  autoload :ExceptionEvent, 'selenium/webdriver/devtools/exception_event'
25
25
  autoload :MutationEvent, 'selenium/webdriver/devtools/mutation_event'
26
+ autoload :NetworkInterceptor, 'selenium/webdriver/devtools/network_interceptor'
26
27
  autoload :PinnedScript, 'selenium/webdriver/devtools/pinned_script'
27
28
  autoload :Request, 'selenium/webdriver/devtools/request'
28
29
  autoload :Response, 'selenium/webdriver/devtools/response'
@@ -42,20 +42,6 @@ module Selenium
42
42
  # until WebDriver Bidi is available.
43
43
  DEVTOOLS_VERSION = 85
44
44
 
45
- def self.driver_path=(path)
46
- WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path=',
47
- 'Selenium::WebDriver::Firefox::Service#driver_path=',
48
- id: :driver_path
49
- Selenium::WebDriver::Firefox::Service.driver_path = path
50
- end
51
-
52
- def self.driver_path
53
- WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path',
54
- 'Selenium::WebDriver::Firefox::Service#driver_path',
55
- id: :driver_path
56
- Selenium::WebDriver::Firefox::Service.driver_path
57
- end
58
-
59
45
  def self.path=(path)
60
46
  Platform.assert_executable path
61
47
  @path = path
@@ -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
@@ -426,8 +426,8 @@ module Selenium
426
426
 
427
427
  def submit_element(element)
428
428
  script = "var form = arguments[0];\n" \
429
- "while (form.nodeName != \"FORM\" && form.parentNode) {\n" \
430
- " form = form.parentNode;\n" \
429
+ "while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
430
+ "form = form.parentNode;\n" \
431
431
  "}\n" \
432
432
  "if (!form) { throw Error('Unable to find containing form element'); }\n" \
433
433
  "if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" \
@@ -568,6 +568,39 @@ module Selenium
568
568
  ShadowRoot.new self, shadow_root_id_from(id)
569
569
  end
570
570
 
571
+ #
572
+ # virtual-authenticator
573
+ #
574
+
575
+ def add_virtual_authenticator(options)
576
+ authenticator_id = execute :add_virtual_authenticator, {}, options.as_json
577
+ VirtualAuthenticator.new(self, authenticator_id, options)
578
+ end
579
+
580
+ def remove_virtual_authenticator(id)
581
+ execute :remove_virtual_authenticator, {authenticatorId: id}
582
+ end
583
+
584
+ def add_credential(credential, id)
585
+ execute :add_credential, {authenticatorId: id}, credential
586
+ end
587
+
588
+ def credentials(authenticator_id)
589
+ execute :get_credentials, {authenticatorId: authenticator_id}
590
+ end
591
+
592
+ def remove_credential(credential_id, authenticator_id)
593
+ execute :remove_credential, {credentialId: credential_id, authenticatorId: authenticator_id}
594
+ end
595
+
596
+ def remove_all_credentials(authenticator_id)
597
+ execute :remove_all_credentials, {authenticatorId: authenticator_id}
598
+ end
599
+
600
+ def user_verified(verified, authenticator_id)
601
+ execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
602
+ end
603
+
571
604
  private
572
605
 
573
606
  #
@@ -149,7 +149,21 @@ module Selenium
149
149
  # server extensions
150
150
  #
151
151
 
152
- upload_file: [:post, 'session/:session_id/se/file']
152
+ upload_file: [:post, 'session/:session_id/se/file'],
153
+
154
+ #
155
+ # virtual-authenticator
156
+ #
157
+
158
+ add_virtual_authenticator: [:post, 'session/:session_id/webauthn/authenticator'],
159
+ remove_virtual_authenticator: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId'],
160
+ add_credential: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/credential'],
161
+ get_credentials: [:get, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
162
+ remove_credential: [:delete,
163
+ 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials/:credentialId'],
164
+ remove_all_credentials: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
165
+ set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv']
166
+
153
167
  }.freeze
154
168
 
155
169
  end # Bridge
@@ -29,7 +29,6 @@ module Selenium
29
29
  class Driver < WebDriver::Driver
30
30
  include DriverExtensions::UploadsFiles
31
31
  include DriverExtensions::HasSessionId
32
- include DriverExtensions::HasRemoteStatus
33
32
 
34
33
  def initialize(bridge: nil, listener: nil, **opts)
35
34
  desired_capabilities = opts[:desired_capabilities]
@@ -53,20 +53,6 @@ module Selenium
53
53
 
54
54
  raise Error::WebDriverError, 'Unable to find Safari'
55
55
  end
56
-
57
- def driver_path=(path)
58
- WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path=',
59
- 'Selenium::WebDriver::Safari::Service#driver_path=',
60
- id: :driver_path
61
- Selenium::WebDriver::Safari::Service.driver_path = path
62
- end
63
-
64
- def driver_path
65
- WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path',
66
- 'Selenium::WebDriver::Safari::Service#driver_path',
67
- id: :driver_path
68
- Selenium::WebDriver::Safari::Service.driver_path
69
- end
70
56
  end
71
57
  end # Safari
72
58
  end # WebDriver
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.2.0'
22
+ VERSION = '4.4.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -56,10 +56,10 @@ Gem::Specification.new do |s|
56
56
  s.add_development_dependency 'rack', ['~> 2.0']
57
57
  s.add_development_dependency 'rake'
58
58
  s.add_development_dependency 'rspec', ['~> 3.0']
59
- s.add_development_dependency 'rubocop', ['~> 1.22']
60
- s.add_development_dependency 'rubocop-performance'
59
+ s.add_development_dependency 'rubocop', ['~> 1.31']
60
+ s.add_development_dependency 'rubocop-performance', ['~> 1.13']
61
61
  s.add_development_dependency 'rubocop-rake'
62
- s.add_development_dependency 'rubocop-rspec'
62
+ s.add_development_dependency 'rubocop-rspec', ['~> 2.12']
63
63
  s.add_development_dependency 'webmock', ['~> 3.5']
64
64
  s.add_development_dependency 'webrick', ['~> 1.7']
65
65
  s.add_development_dependency 'yard', ['~> 0.9.11']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rodionov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-05-27 00:00:00.000000000 Z
13
+ date: 2022-08-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: childprocess
@@ -162,28 +162,28 @@ dependencies:
162
162
  requirements:
163
163
  - - "~>"
164
164
  - !ruby/object:Gem::Version
165
- version: '1.22'
165
+ version: '1.31'
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
- version: '1.22'
172
+ version: '1.31'
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: rubocop-performance
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
- - - ">="
177
+ - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '0'
179
+ version: '1.13'
180
180
  type: :development
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
- - - ">="
184
+ - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: '0'
186
+ version: '1.13'
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: rubocop-rake
189
189
  requirement: !ruby/object:Gem::Requirement
@@ -202,16 +202,16 @@ dependencies:
202
202
  name: rubocop-rspec
203
203
  requirement: !ruby/object:Gem::Requirement
204
204
  requirements:
205
- - - ">="
205
+ - - "~>"
206
206
  - !ruby/object:Gem::Version
207
- version: '0'
207
+ version: '2.12'
208
208
  type: :development
209
209
  prerelease: false
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
- - - ">="
212
+ - - "~>"
213
213
  - !ruby/object:Gem::Version
214
- version: '0'
214
+ version: '2.12'
215
215
  - !ruby/object:Gem::Dependency
216
216
  name: webmock
217
217
  requirement: !ruby/object:Gem::Requirement
@@ -311,7 +311,6 @@ files:
311
311
  - lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb
312
312
  - lib/selenium/webdriver/common/driver_extensions/has_permissions.rb
313
313
  - lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb
314
- - lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb
315
314
  - lib/selenium/webdriver/common/driver_extensions/has_session_id.rb
316
315
  - lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb
317
316
  - lib/selenium/webdriver/common/driver_extensions/prints_page.rb
@@ -360,6 +359,9 @@ files:
360
359
  - lib/selenium/webdriver/common/takes_screenshot.rb
361
360
  - lib/selenium/webdriver/common/target_locator.rb
362
361
  - lib/selenium/webdriver/common/timeouts.rb
362
+ - lib/selenium/webdriver/common/virtual_authenticator/credential.rb
363
+ - lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb
364
+ - lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb
363
365
  - lib/selenium/webdriver/common/wait.rb
364
366
  - lib/selenium/webdriver/common/websocket_connection.rb
365
367
  - lib/selenium/webdriver/common/window.rb
@@ -368,6 +370,7 @@ files:
368
370
  - lib/selenium/webdriver/devtools/console_event.rb
369
371
  - lib/selenium/webdriver/devtools/exception_event.rb
370
372
  - lib/selenium/webdriver/devtools/mutation_event.rb
373
+ - lib/selenium/webdriver/devtools/network_interceptor.rb
371
374
  - lib/selenium/webdriver/devtools/pinned_script.rb
372
375
  - lib/selenium/webdriver/devtools/request.rb
373
376
  - lib/selenium/webdriver/devtools/response.rb
@@ -398,7 +401,6 @@ files:
398
401
  - lib/selenium/webdriver/remote/http/common.rb
399
402
  - lib/selenium/webdriver/remote/http/curb.rb
400
403
  - lib/selenium/webdriver/remote/http/default.rb
401
- - lib/selenium/webdriver/remote/http/persistent.rb
402
404
  - lib/selenium/webdriver/remote/response.rb
403
405
  - lib/selenium/webdriver/remote/server_error.rb
404
406
  - lib/selenium/webdriver/safari.rb
@@ -443,7 +445,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
443
445
  - !ruby/object:Gem::Version
444
446
  version: 1.3.1
445
447
  requirements: []
446
- rubygems_version: 3.0.3
448
+ rubygems_version: 3.0.3.1
447
449
  signing_key:
448
450
  specification_version: 4
449
451
  summary: Selenium is a browser automation tool for automated testing of webapps and