selenium-webdriver 4.1.0 → 4.9.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.
- checksums.yaml +4 -4
- data/CHANGES +221 -1
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/bin/linux/selenium-manager +0 -0
- data/bin/macos/selenium-manager +0 -0
- data/bin/windows/selenium-manager.exe +0 -0
- data/lib/selenium/server.rb +35 -26
- data/lib/selenium/webdriver/atoms/findElements.js +0 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
- data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
- data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
- data/lib/selenium/webdriver/atoms.rb +2 -3
- data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
- data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
- data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
- data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
- data/lib/selenium/webdriver/bidi/session.rb +51 -0
- data/lib/selenium/webdriver/bidi.rb +56 -0
- data/lib/selenium/webdriver/chrome/driver.rb +9 -29
- data/lib/selenium/webdriver/chrome/features.rb +6 -68
- data/lib/selenium/webdriver/chrome/options.rb +3 -223
- data/lib/selenium/webdriver/chrome/profile.rb +3 -83
- data/lib/selenium/webdriver/chrome/service.rb +3 -23
- data/lib/selenium/webdriver/chrome.rb +0 -14
- data/lib/selenium/webdriver/chromium/driver.rb +61 -0
- data/lib/selenium/webdriver/chromium/features.rb +103 -0
- data/lib/selenium/webdriver/chromium/options.rb +261 -0
- data/lib/selenium/webdriver/chromium/profile.rb +113 -0
- data/lib/selenium/webdriver/chromium/service.rb +42 -0
- data/lib/selenium/webdriver/chromium.rb +32 -0
- data/lib/selenium/webdriver/common/action_builder.rb +72 -22
- data/lib/selenium/webdriver/common/child_process.rb +124 -0
- data/lib/selenium/webdriver/common/driver.rb +36 -74
- data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +10 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -69
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
- data/lib/selenium/webdriver/common/driver_finder.rb +43 -0
- data/lib/selenium/webdriver/common/element.rb +8 -8
- data/lib/selenium/webdriver/common/error.rb +1 -3
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
- data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
- data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
- data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
- data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
- data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
- data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
- data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
- data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
- data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
- data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
- data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
- data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
- data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
- data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
- data/lib/selenium/webdriver/common/keys.rb +1 -0
- data/lib/selenium/webdriver/common/local_driver.rb +55 -0
- data/lib/selenium/webdriver/common/logger.rb +10 -2
- data/lib/selenium/webdriver/common/manager.rb +0 -27
- data/lib/selenium/webdriver/common/options.rb +32 -17
- data/lib/selenium/webdriver/common/platform.rb +8 -5
- data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
- data/lib/selenium/webdriver/common/proxy.rb +1 -1
- data/lib/selenium/webdriver/common/search_context.rb +0 -6
- data/lib/selenium/webdriver/common/selenium_manager.rb +108 -0
- data/lib/selenium/webdriver/common/service.rb +11 -22
- data/lib/selenium/webdriver/common/service_manager.rb +5 -14
- data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
- data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
- data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
- data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
- data/lib/selenium/webdriver/common/target_locator.rb +2 -3
- data/lib/selenium/webdriver/common/timeouts.rb +2 -2
- data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
- data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
- data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
- data/lib/selenium/webdriver/common/websocket_connection.rb +164 -0
- data/lib/selenium/webdriver/common/window.rb +6 -6
- data/lib/selenium/webdriver/common/zipper.rb +1 -1
- data/lib/selenium/webdriver/common.rb +21 -3
- data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
- data/lib/selenium/webdriver/devtools/request.rb +1 -3
- data/lib/selenium/webdriver/devtools/response.rb +1 -3
- data/lib/selenium/webdriver/devtools.rb +17 -114
- data/lib/selenium/webdriver/edge/driver.rb +9 -3
- data/lib/selenium/webdriver/edge/features.rb +4 -4
- data/lib/selenium/webdriver/edge/options.rb +3 -5
- data/lib/selenium/webdriver/edge/profile.rb +2 -2
- data/lib/selenium/webdriver/edge/service.rb +2 -6
- data/lib/selenium/webdriver/firefox/driver.rb +9 -2
- data/lib/selenium/webdriver/firefox/features.rb +6 -6
- data/lib/selenium/webdriver/firefox/options.rb +9 -3
- data/lib/selenium/webdriver/firefox/profile.rb +7 -11
- data/lib/selenium/webdriver/firefox/service.rb +0 -6
- data/lib/selenium/webdriver/firefox/util.rb +46 -0
- data/lib/selenium/webdriver/firefox.rb +1 -14
- data/lib/selenium/webdriver/ie/driver.rb +7 -1
- data/lib/selenium/webdriver/ie/service.rb +1 -7
- data/lib/selenium/webdriver/ie.rb +0 -14
- data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +15 -8
- data/lib/selenium/webdriver/remote/bridge.rb +59 -30
- data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
- data/lib/selenium/webdriver/remote/driver.rb +19 -14
- data/lib/selenium/webdriver/remote/http/curb.rb +0 -2
- data/lib/selenium/webdriver/remote/http/default.rb +7 -12
- data/lib/selenium/webdriver/remote/response.rb +2 -3
- data/lib/selenium/webdriver/remote.rb +0 -1
- data/lib/selenium/webdriver/safari/driver.rb +7 -1
- data/lib/selenium/webdriver/safari/features.rb +0 -2
- data/lib/selenium/webdriver/safari/options.rb +5 -1
- data/lib/selenium/webdriver/safari/service.rb +0 -4
- data/lib/selenium/webdriver/safari.rb +1 -15
- data/lib/selenium/webdriver/support/color.rb +20 -20
- data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
- data/lib/selenium/webdriver/support/guards.rb +1 -1
- data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
- data/lib/selenium/webdriver/support/select.rb +3 -1
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +4 -4
- data/selenium-webdriver.gemspec +13 -11
- metadata +70 -59
- data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
|
@@ -0,0 +1,124 @@
|
|
|
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
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
class ChildProcess
|
|
27
|
+
TimeoutError = Class.new(StandardError)
|
|
28
|
+
|
|
29
|
+
SIGTERM = 'TERM'
|
|
30
|
+
SIGKILL = 'KILL'
|
|
31
|
+
|
|
32
|
+
POLL_INTERVAL = 0.1
|
|
33
|
+
|
|
34
|
+
attr_accessor :detach
|
|
35
|
+
attr_writer :io
|
|
36
|
+
|
|
37
|
+
def self.build(*command)
|
|
38
|
+
new(*command)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize(*command)
|
|
42
|
+
@command = command
|
|
43
|
+
@detach = false
|
|
44
|
+
@pid = nil
|
|
45
|
+
@status = nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def io
|
|
49
|
+
@io ||= Platform.null_device
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def start
|
|
53
|
+
options = {%i[out err] => io}
|
|
54
|
+
options[:pgroup] = true unless Platform.windows? # NOTE: this is a bug only in Windows 7
|
|
55
|
+
|
|
56
|
+
WebDriver.logger.debug("Starting process: #{@command} with #{options}")
|
|
57
|
+
@pid = Process.spawn(*@command, options)
|
|
58
|
+
WebDriver.logger.debug(" -> pid: #{@pid}")
|
|
59
|
+
|
|
60
|
+
Process.detach(@pid) if detach
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def stop(timeout = 3)
|
|
64
|
+
return unless @pid
|
|
65
|
+
return if exited?
|
|
66
|
+
|
|
67
|
+
WebDriver.logger.debug("Sending TERM to process: #{@pid}")
|
|
68
|
+
terminate(@pid)
|
|
69
|
+
poll_for_exit(timeout)
|
|
70
|
+
|
|
71
|
+
WebDriver.logger.debug(" -> stopped #{@pid}")
|
|
72
|
+
rescue TimeoutError, Errno::EINVAL
|
|
73
|
+
WebDriver.logger.debug(" -> sending KILL to process: #{@pid}")
|
|
74
|
+
kill(@pid)
|
|
75
|
+
wait
|
|
76
|
+
WebDriver.logger.debug(" -> killed #{@pid}")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def alive?
|
|
80
|
+
@pid && !exited?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def exited?
|
|
84
|
+
return unless @pid
|
|
85
|
+
|
|
86
|
+
WebDriver.logger.debug("Checking if #{@pid} is exited:")
|
|
87
|
+
_, @status = Process.waitpid2(@pid, Process::WNOHANG | Process::WUNTRACED) if @status.nil?
|
|
88
|
+
return if @status.nil?
|
|
89
|
+
|
|
90
|
+
exit_code = @status.exitstatus || @status.termsig
|
|
91
|
+
WebDriver.logger.debug(" -> exit code is #{exit_code.inspect}")
|
|
92
|
+
|
|
93
|
+
!!exit_code
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def poll_for_exit(timeout)
|
|
97
|
+
WebDriver.logger.debug("Polling #{timeout} seconds for exit of #{@pid}")
|
|
98
|
+
|
|
99
|
+
end_time = Time.now + timeout
|
|
100
|
+
sleep POLL_INTERVAL until exited? || Time.now > end_time
|
|
101
|
+
|
|
102
|
+
raise TimeoutError, " -> #{@pid} still alive after #{timeout} seconds" unless exited?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def wait
|
|
106
|
+
return if exited?
|
|
107
|
+
|
|
108
|
+
_, @status = Process.waitpid2(@pid)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def terminate(pid)
|
|
114
|
+
Process.kill(SIGTERM, pid)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def kill(pid)
|
|
118
|
+
Process.kill(SIGKILL, pid)
|
|
119
|
+
rescue Errno::ECHILD, Errno::ESRCH
|
|
120
|
+
# already dead
|
|
121
|
+
end
|
|
122
|
+
end # ChildProcess
|
|
123
|
+
end # WebDriver
|
|
124
|
+
end # Selenium
|
|
@@ -51,7 +51,7 @@ module Selenium
|
|
|
51
51
|
Safari::Driver.new(**opts)
|
|
52
52
|
when :firefox, :ff
|
|
53
53
|
Firefox::Driver.new(**opts)
|
|
54
|
-
when :edge
|
|
54
|
+
when :edge, :microsoftedge, :msedge
|
|
55
55
|
Edge::Driver.new(**opts)
|
|
56
56
|
when :remote
|
|
57
57
|
Remote::Driver.new(**opts)
|
|
@@ -69,8 +69,8 @@ module Selenium
|
|
|
69
69
|
#
|
|
70
70
|
|
|
71
71
|
def initialize(bridge: nil, listener: nil, **opts)
|
|
72
|
-
@service = nil
|
|
73
72
|
@devtools = nil
|
|
73
|
+
@bidi = nil
|
|
74
74
|
bridge ||= create_bridge(**opts)
|
|
75
75
|
add_extensions(bridge.browser)
|
|
76
76
|
@bridge = listener ? Support::EventFiringBridge.new(bridge, listener) : bridge
|
|
@@ -123,16 +123,8 @@ module Selenium
|
|
|
123
123
|
# @see ActionBuilder
|
|
124
124
|
#
|
|
125
125
|
|
|
126
|
-
def action
|
|
127
|
-
bridge.action
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def mouse
|
|
131
|
-
bridge.mouse
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def keyboard
|
|
135
|
-
bridge.keyboard
|
|
126
|
+
def action(**opts)
|
|
127
|
+
bridge.action(**opts)
|
|
136
128
|
end
|
|
137
129
|
|
|
138
130
|
#
|
|
@@ -180,8 +172,9 @@ module Selenium
|
|
|
180
172
|
def quit
|
|
181
173
|
bridge.quit
|
|
182
174
|
ensure
|
|
183
|
-
@
|
|
175
|
+
@service_manager&.stop
|
|
184
176
|
@devtools&.close
|
|
177
|
+
@bidi&.close
|
|
185
178
|
end
|
|
186
179
|
|
|
187
180
|
#
|
|
@@ -189,7 +182,10 @@ module Selenium
|
|
|
189
182
|
#
|
|
190
183
|
|
|
191
184
|
def close
|
|
192
|
-
|
|
185
|
+
# If no top-level browsing contexts are open after calling close,
|
|
186
|
+
# it indicates that the WebDriver session is closed.
|
|
187
|
+
# If the WebDriver session is closed, the BiDi session also needs to be closed.
|
|
188
|
+
bridge.close.tap { |handles| @bidi&.close if handles&.empty? }
|
|
193
189
|
end
|
|
194
190
|
|
|
195
191
|
#
|
|
@@ -248,25 +244,34 @@ module Selenium
|
|
|
248
244
|
bridge.execute_async_script(script, *args)
|
|
249
245
|
end
|
|
250
246
|
|
|
247
|
+
#
|
|
248
|
+
# @return [VirtualAuthenticator]
|
|
249
|
+
# @see VirtualAuthenticator
|
|
250
|
+
#
|
|
251
|
+
|
|
252
|
+
def add_virtual_authenticator(options)
|
|
253
|
+
bridge.add_virtual_authenticator(options)
|
|
254
|
+
end
|
|
255
|
+
|
|
251
256
|
#-------------------------------- sugar --------------------------------
|
|
252
257
|
|
|
253
258
|
#
|
|
254
259
|
# driver.first(id: 'foo')
|
|
255
260
|
#
|
|
256
261
|
|
|
257
|
-
|
|
262
|
+
alias first find_element
|
|
258
263
|
|
|
259
264
|
#
|
|
260
265
|
# driver.all(class: 'bar') #=> [#<WebDriver::Element:0x1011c3b88, ...]
|
|
261
266
|
#
|
|
262
267
|
|
|
263
|
-
|
|
268
|
+
alias all find_elements
|
|
264
269
|
|
|
265
270
|
#
|
|
266
271
|
# driver.script('function() { ... };')
|
|
267
272
|
#
|
|
268
273
|
|
|
269
|
-
|
|
274
|
+
alias script execute_script
|
|
270
275
|
|
|
271
276
|
# Get the first element matching the given selector. If given a
|
|
272
277
|
# String or Symbol, it will be used as the id of the element.
|
|
@@ -307,72 +312,27 @@ module Selenium
|
|
|
307
312
|
|
|
308
313
|
attr_reader :bridge
|
|
309
314
|
|
|
310
|
-
def create_bridge(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
# NOTE: This is deprecated
|
|
314
|
-
cap_array = caps.is_a?(Hash) ? [caps] : Array(caps)
|
|
315
|
-
|
|
316
|
-
desired_capabilities = opts.delete(:desired_capabilities)
|
|
317
|
-
if desired_capabilities
|
|
318
|
-
WebDriver.logger.deprecate(':desired_capabilities as a parameter for driver initialization',
|
|
319
|
-
':capabilities with an Array value of capabilities/options if necessary',
|
|
320
|
-
id: :desired_capabilities)
|
|
321
|
-
desired_capabilities = Remote::Capabilities.new(desired_capabilities) if desired_capabilities.is_a?(Hash)
|
|
322
|
-
cap_array << desired_capabilities
|
|
315
|
+
def create_bridge(caps:, url:, http_client: nil)
|
|
316
|
+
Remote::Bridge.new(http_client: http_client, url: url).tap do |bridge|
|
|
317
|
+
bridge.create_session(caps)
|
|
323
318
|
end
|
|
324
|
-
|
|
325
|
-
options = opts.delete(:options)
|
|
326
|
-
if options
|
|
327
|
-
WebDriver.logger.deprecate(':options as a parameter for driver initialization',
|
|
328
|
-
':capabilities with an Array of value capabilities/options if necessary',
|
|
329
|
-
id: :browser_options)
|
|
330
|
-
cap_array << options
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
capabilities = generate_capabilities(cap_array)
|
|
334
|
-
|
|
335
|
-
bridge_opts = {http_client: opts.delete(:http_client), url: opts.delete(:url)}
|
|
336
|
-
raise ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
|
|
337
|
-
|
|
338
|
-
bridge = Remote::Bridge.new(**bridge_opts)
|
|
339
|
-
|
|
340
|
-
bridge.create_session(capabilities)
|
|
341
|
-
bridge
|
|
342
319
|
end
|
|
343
320
|
|
|
344
|
-
def generate_capabilities(
|
|
345
|
-
|
|
321
|
+
def generate_capabilities(capabilities)
|
|
322
|
+
Array(capabilities).map { |cap|
|
|
346
323
|
if cap.is_a? Symbol
|
|
347
|
-
cap =
|
|
348
|
-
elsif cap.is_a? Hash
|
|
349
|
-
new_message = 'Capabilities instance initialized with the Hash, or build values with Options class'
|
|
350
|
-
WebDriver.logger.deprecate("passing a Hash value to :capabilities",
|
|
351
|
-
new_message,
|
|
352
|
-
id: :capabilities_hash)
|
|
353
|
-
cap = Remote::Capabilities.new(cap)
|
|
324
|
+
cap = WebDriver::Options.send(cap)
|
|
354
325
|
elsif !cap.respond_to? :as_json
|
|
355
326
|
msg = ":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not"
|
|
356
327
|
raise ArgumentError, msg
|
|
357
328
|
end
|
|
358
|
-
cap
|
|
359
|
-
}.inject(:merge)
|
|
329
|
+
cap.as_json
|
|
330
|
+
}.inject(:merge)
|
|
360
331
|
end
|
|
361
332
|
|
|
362
|
-
def service_url(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
next unless opts.key? key
|
|
366
|
-
|
|
367
|
-
WebDriver.logger.deprecate(":#{key}", ':service with an instance of Selenium::WebDriver::Service',
|
|
368
|
-
id: "service_#{key}".to_sym)
|
|
369
|
-
end
|
|
370
|
-
service_config ||= Service.send(browser,
|
|
371
|
-
args: opts.delete(:driver_opts),
|
|
372
|
-
path: opts.delete(:driver_path),
|
|
373
|
-
port: opts.delete(:port))
|
|
374
|
-
@service = service_config.launch
|
|
375
|
-
@service.uri
|
|
333
|
+
def service_url(service)
|
|
334
|
+
@service_manager = service.launch
|
|
335
|
+
@service_manager.uri
|
|
376
336
|
end
|
|
377
337
|
|
|
378
338
|
def screenshot
|
|
@@ -382,11 +342,13 @@ module Selenium
|
|
|
382
342
|
def add_extensions(browser)
|
|
383
343
|
extensions = case browser
|
|
384
344
|
when :chrome, :msedge
|
|
385
|
-
|
|
345
|
+
Chromium::Driver::EXTENSIONS
|
|
386
346
|
when :firefox
|
|
387
347
|
Firefox::Driver::EXTENSIONS
|
|
388
348
|
when :safari, :safari_technology_preview
|
|
389
349
|
Safari::Driver::EXTENSIONS
|
|
350
|
+
when :ie, :internet_explorer
|
|
351
|
+
IE::Driver::EXTENSIONS
|
|
390
352
|
else
|
|
391
353
|
[]
|
|
392
354
|
end
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module DownloadsFiles
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Sets download path for Chromium.
|
|
27
26
|
#
|
|
@@ -38,7 +37,6 @@ module Selenium
|
|
|
38
37
|
}
|
|
39
38
|
@bridge.send_command(params)
|
|
40
39
|
end
|
|
41
|
-
|
|
42
40
|
end # DownloadsFiles
|
|
43
41
|
end # DriverExtensions
|
|
44
42
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasAddons
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Installs addon.
|
|
27
26
|
#
|
|
@@ -43,7 +42,6 @@ module Selenium
|
|
|
43
42
|
def uninstall_addon(id)
|
|
44
43
|
@bridge.uninstall_addon(id)
|
|
45
44
|
end
|
|
46
|
-
|
|
47
45
|
end # HasAddons
|
|
48
46
|
end # DriverExtensions
|
|
49
47
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasApplePermissions
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Returns permissions.
|
|
27
26
|
#
|
|
@@ -44,7 +43,6 @@ module Selenium
|
|
|
44
43
|
def permissions=(permissions)
|
|
45
44
|
@bridge.permissions = permissions
|
|
46
45
|
end
|
|
47
|
-
|
|
48
46
|
end # HasPermissions
|
|
49
47
|
end # DriverExtensions
|
|
50
48
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasAuthentication
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Registers basic authentication handler which is automatically
|
|
27
26
|
# used whenever browser gets an authentication required response.
|
|
@@ -82,7 +81,6 @@ module Selenium
|
|
|
82
81
|
)
|
|
83
82
|
end
|
|
84
83
|
end
|
|
85
|
-
|
|
86
84
|
end # HasAuthentication
|
|
87
85
|
end # DriverExtensions
|
|
88
86
|
end # WebDriver
|
|
@@ -20,12 +20,17 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
|
-
module
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
module HasBiDi
|
|
24
|
+
#
|
|
25
|
+
# Retrieves WebDriver BiDi connection.
|
|
26
|
+
#
|
|
27
|
+
# @return [BiDi]
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
def bidi
|
|
31
|
+
@bidi ||= Selenium::WebDriver::BiDi.new(url: capabilities[:web_socket_url])
|
|
27
32
|
end
|
|
28
|
-
end #
|
|
33
|
+
end # HasBiDi
|
|
29
34
|
end # DriverExtensions
|
|
30
35
|
end # WebDriver
|
|
31
36
|
end # Selenium
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasCasting
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# What devices ("sinks") are available to be cast to.
|
|
27
26
|
#
|
|
@@ -52,6 +51,16 @@ module Selenium
|
|
|
52
51
|
@bridge.start_cast_tab_mirroring(name)
|
|
53
52
|
end
|
|
54
53
|
|
|
54
|
+
#
|
|
55
|
+
# Starts a tab mirroring session on a specific receiver target.
|
|
56
|
+
#
|
|
57
|
+
# @param [String] name the sink to use as the target
|
|
58
|
+
#
|
|
59
|
+
|
|
60
|
+
def start_cast_desktop_mirroring(name)
|
|
61
|
+
@bridge.start_cast_desktop_mirroring(name)
|
|
62
|
+
end
|
|
63
|
+
|
|
55
64
|
#
|
|
56
65
|
# Gets error messages when there is any issue in a Cast session.
|
|
57
66
|
#
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasCDP
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Returns network conditions.
|
|
27
26
|
#
|
|
@@ -31,7 +30,6 @@ module Selenium
|
|
|
31
30
|
def execute_cdp(cmd, **params)
|
|
32
31
|
@bridge.send_command(cmd: cmd, params: params)
|
|
33
32
|
end
|
|
34
|
-
|
|
35
33
|
end # HasCDP
|
|
36
34
|
end # DriverExtensions
|
|
37
35
|
end # WebDriver
|
|
@@ -21,14 +21,12 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasContext
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Sets the context that Selenium commands are running in using
|
|
27
26
|
# a `with` statement. The state of the context on the server is
|
|
28
27
|
# saved before entering the block, and restored upon exiting it.
|
|
29
28
|
#
|
|
30
|
-
# @param [String]
|
|
31
|
-
# @param [String] value what to set the permission to
|
|
29
|
+
# @param [String] value which context gets set (either 'chrome' or 'content')
|
|
32
30
|
#
|
|
33
31
|
|
|
34
32
|
def context=(value)
|
|
@@ -38,7 +36,6 @@ module Selenium
|
|
|
38
36
|
def context
|
|
39
37
|
@bridge.context
|
|
40
38
|
end
|
|
41
|
-
|
|
42
39
|
end # HasContext
|
|
43
40
|
end # DriverExtensions
|
|
44
41
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasDebugger
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Attaches debugger to session.
|
|
27
26
|
#
|
|
@@ -35,7 +34,6 @@ module Selenium
|
|
|
35
34
|
def attach_debugger
|
|
36
35
|
@bridge.attach_debugger
|
|
37
36
|
end
|
|
38
|
-
|
|
39
37
|
end # HasDebugger
|
|
40
38
|
end # DriverExtensions
|
|
41
39
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasDevTools
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Retrieves connection to DevTools.
|
|
27
26
|
#
|
|
@@ -36,7 +35,6 @@ module Selenium
|
|
|
36
35
|
Selenium::WebDriver::DevTools.new(url: devtools_url)
|
|
37
36
|
end
|
|
38
37
|
end
|
|
39
|
-
|
|
40
38
|
end # HasDevTools
|
|
41
39
|
end # DriverExtensions
|
|
42
40
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasLaunching
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Launches Chromium app specified by id.
|
|
27
26
|
#
|
|
@@ -31,7 +30,6 @@ module Selenium
|
|
|
31
30
|
def launch_app(id)
|
|
32
31
|
@bridge.launch_app(id)
|
|
33
32
|
end
|
|
34
|
-
|
|
35
33
|
end # HasLaunching
|
|
36
34
|
end # DriverExtensions
|
|
37
35
|
end # WebDriver
|
|
@@ -29,8 +29,7 @@ module Selenium
|
|
|
29
29
|
def location=(*)
|
|
30
30
|
raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting location'
|
|
31
31
|
end
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
alias set_location location
|
|
34
33
|
end # HasLocation
|
|
35
34
|
end # DriverExtensions
|
|
36
35
|
end # WebDriver
|
|
@@ -114,7 +114,7 @@ module Selenium
|
|
|
114
114
|
execute_script(mutation_listener)
|
|
115
115
|
devtools.page.add_script_to_evaluate_on_new_document(source: mutation_listener)
|
|
116
116
|
|
|
117
|
-
devtools.runtime.on(:binding_called
|
|
117
|
+
devtools.runtime.on(:binding_called) { |event| log_mutation_event(event) }
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
def log_mutation_event(params)
|
|
@@ -137,7 +137,6 @@ module Selenium
|
|
|
137
137
|
def mutation_listener
|
|
138
138
|
@mutation_listener ||= read_atom(:mutationListener)
|
|
139
139
|
end
|
|
140
|
-
|
|
141
140
|
end # HasLogEvents
|
|
142
141
|
end # DriverExtensions
|
|
143
142
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasNetworkConditions
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Returns network conditions.
|
|
27
26
|
#
|
|
@@ -61,7 +60,6 @@ module Selenium
|
|
|
61
60
|
def delete_network_conditions
|
|
62
61
|
@bridge.delete_network_conditions
|
|
63
62
|
end
|
|
64
|
-
|
|
65
63
|
end # HasNetworkConditions
|
|
66
64
|
end # DriverExtensions
|
|
67
65
|
end # WebDriver
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasNetworkInterception
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Intercepts requests coming from browser allowing
|
|
27
26
|
# to either pass them through like proxy or provide
|
|
@@ -61,74 +60,8 @@ module Selenium
|
|
|
61
60
|
#
|
|
62
61
|
|
|
63
62
|
def intercept(&block)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
id = params['requestId']
|
|
67
|
-
if params.key?('responseStatusCode') || params.key?('responseErrorReason')
|
|
68
|
-
intercept_response(id, params, &pending_response_requests.delete(id))
|
|
69
|
-
else
|
|
70
|
-
intercept_request(id, params, &block)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
devtools.fetch.enable(patterns: [{requestStage: 'Request'}, {requestStage: 'Response'}])
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
private
|
|
77
|
-
|
|
78
|
-
def pending_response_requests
|
|
79
|
-
@pending_response_requests ||= {}
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def intercept_request(id, params, &block)
|
|
83
|
-
original = DevTools::Request.from(id, params)
|
|
84
|
-
mutable = DevTools::Request.from(id, params)
|
|
85
|
-
|
|
86
|
-
block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall
|
|
87
|
-
pending_response_requests[id] = continue
|
|
88
|
-
|
|
89
|
-
if original == mutable
|
|
90
|
-
devtools.fetch.continue_request(request_id: id)
|
|
91
|
-
else
|
|
92
|
-
devtools.fetch.continue_request(
|
|
93
|
-
request_id: id,
|
|
94
|
-
url: mutable.url,
|
|
95
|
-
method: mutable.method,
|
|
96
|
-
post_data: mutable.post_data,
|
|
97
|
-
headers: mutable.headers.map do |k, v|
|
|
98
|
-
{name: k, value: v}
|
|
99
|
-
end
|
|
100
|
-
)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def intercept_response(id, params)
|
|
106
|
-
return devtools.fetch.continue_request(request_id: id) unless block_given?
|
|
107
|
-
|
|
108
|
-
body = fetch_response_body(id)
|
|
109
|
-
original = DevTools::Response.from(id, body, params)
|
|
110
|
-
mutable = DevTools::Response.from(id, body, params)
|
|
111
|
-
yield mutable
|
|
112
|
-
|
|
113
|
-
if original == mutable
|
|
114
|
-
devtools.fetch.continue_request(request_id: id)
|
|
115
|
-
else
|
|
116
|
-
devtools.fetch.fulfill_request(
|
|
117
|
-
request_id: id,
|
|
118
|
-
body: (Base64.strict_encode64(mutable.body) if mutable.body),
|
|
119
|
-
response_code: mutable.code,
|
|
120
|
-
response_headers: mutable.headers.map do |k, v|
|
|
121
|
-
{name: k, value: v}
|
|
122
|
-
end
|
|
123
|
-
)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def fetch_response_body(id)
|
|
128
|
-
devtools.fetch.get_response_body(request_id: id).dig('result', 'body')
|
|
129
|
-
rescue Error::WebDriverError
|
|
130
|
-
# CDP fails to get body on certain responses (301) and raises:
|
|
131
|
-
# Can only get response body on requests captured after headers received.
|
|
63
|
+
@interceptor ||= DevTools::NetworkInterceptor.new(devtools)
|
|
64
|
+
@interceptor.intercept(&block)
|
|
132
65
|
end
|
|
133
66
|
end # HasNetworkInterception
|
|
134
67
|
end # DriverExtensions
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module DriverExtensions
|
|
23
23
|
module HasPermissions
|
|
24
|
-
|
|
25
24
|
#
|
|
26
25
|
# Set one permission.
|
|
27
26
|
#
|
|
@@ -44,7 +43,6 @@ module Selenium
|
|
|
44
43
|
@bridge.set_permission(key, value)
|
|
45
44
|
end
|
|
46
45
|
end
|
|
47
|
-
|
|
48
46
|
end # HasPermissions
|
|
49
47
|
end # DriverExtensions
|
|
50
48
|
end # WebDriver
|