selenium-webdriver 4.1.0 → 4.9.1
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 +234 -1
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +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 +36 -27
- 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 +64 -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 +44 -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 +76 -24
- 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/port_prober.rb +1 -1
- 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 +20 -23
- data/lib/selenium/webdriver/common/service_manager.rb +8 -15
- data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
- data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
- data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
- 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 +8 -12
- 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 +65 -35
- data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
- data/lib/selenium/webdriver/remote/driver.rb +19 -14
- data/lib/selenium/webdriver/remote/http/common.rb +3 -3
- data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
- 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 +22 -22
- 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 +5 -4
- data/selenium-webdriver.gemspec +13 -12
- metadata +70 -73
- 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
|
@@ -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]
|
|
34
|
-
# @param [Object]
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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 = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])
|
|
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,
|
|
@@ -59,10 +57,25 @@ module Selenium
|
|
|
59
57
|
# Backward compatibility
|
|
60
58
|
#
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
def version
|
|
61
|
+
WebDriver.logger.deprecate('`Capabilities#version`', '`Capabilities#browser_version`', id: :jwp_caps)
|
|
62
|
+
browser_version
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def version=(value)
|
|
66
|
+
WebDriver.logger.deprecate('`Capabilities#version=`', '`Capabilities#browser_version=`', id: :jwp_caps)
|
|
67
|
+
self.browser_version = value
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def platform
|
|
71
|
+
WebDriver.logger.deprecate('`Capabilities#platform`', '`Capabilities#platform_name`', id: :jwp_caps)
|
|
72
|
+
platform_name
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def platform=(value)
|
|
76
|
+
WebDriver.logger.deprecate('`Capabilities#platform=`', '`Capabilities#platform_name=`', id: :jwp_caps)
|
|
77
|
+
self.platform_name = value
|
|
78
|
+
end
|
|
66
79
|
|
|
67
80
|
#
|
|
68
81
|
# Convenience methods for the common choices.
|
|
@@ -70,44 +83,52 @@ module Selenium
|
|
|
70
83
|
|
|
71
84
|
class << self
|
|
72
85
|
def chrome(opts = {})
|
|
86
|
+
WebDriver.logger.deprecate('Remote::Capabilities.chrome', 'Options.chrome', id: :caps_browsers)
|
|
73
87
|
new({
|
|
74
88
|
browser_name: 'chrome'
|
|
75
89
|
}.merge(opts))
|
|
76
90
|
end
|
|
77
91
|
|
|
78
92
|
def edge(opts = {})
|
|
93
|
+
WebDriver.logger.deprecate('Remote::Capabilities.edge', 'Options.edge', id: :caps_browsers)
|
|
79
94
|
new({
|
|
80
95
|
browser_name: 'MicrosoftEdge'
|
|
81
96
|
}.merge(opts))
|
|
82
97
|
end
|
|
83
|
-
|
|
98
|
+
alias microsoftedge edge
|
|
84
99
|
|
|
85
100
|
def firefox(opts = {})
|
|
101
|
+
WebDriver.logger.deprecate('Remote::Capabilities.firefox', 'Options.firefox', id: :caps_browsers)
|
|
86
102
|
new({
|
|
87
103
|
browser_name: 'firefox'
|
|
88
104
|
}.merge(opts))
|
|
89
105
|
end
|
|
90
|
-
|
|
106
|
+
alias ff firefox
|
|
91
107
|
|
|
92
108
|
def safari(opts = {})
|
|
109
|
+
WebDriver.logger.deprecate('Remote::Capabilities.safari', 'Options.safari', id: :caps_browsers)
|
|
93
110
|
new({
|
|
94
|
-
browser_name: Selenium::WebDriver::Safari.technology_preview? ?
|
|
111
|
+
browser_name: Selenium::WebDriver::Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
|
|
95
112
|
}.merge(opts))
|
|
96
113
|
end
|
|
97
114
|
|
|
98
115
|
def htmlunit(opts = {})
|
|
116
|
+
WebDriver.logger.deprecate('Remote::Capabilities.htmlunit',
|
|
117
|
+
'as argument in constructor',
|
|
118
|
+
id: :caps_browsers)
|
|
99
119
|
new({
|
|
100
120
|
browser_name: 'htmlunit'
|
|
101
121
|
}.merge(opts))
|
|
102
122
|
end
|
|
103
123
|
|
|
104
124
|
def internet_explorer(opts = {})
|
|
125
|
+
WebDriver.logger.deprecate('Remote::Capabilities.ie', 'Options.ie', id: :caps_browsers)
|
|
105
126
|
new({
|
|
106
127
|
browser_name: 'internet explorer',
|
|
107
128
|
platform_name: :windows
|
|
108
129
|
}.merge(opts))
|
|
109
130
|
end
|
|
110
|
-
|
|
131
|
+
alias ie internet_explorer
|
|
111
132
|
|
|
112
133
|
def always_match(capabilities)
|
|
113
134
|
new(always_match: capabilities)
|
|
@@ -134,7 +155,8 @@ module Selenium
|
|
|
134
155
|
|
|
135
156
|
# Remote Server Specific
|
|
136
157
|
if data.key?('webdriver.remote.sessionid')
|
|
137
|
-
caps[:remote_session_id] =
|
|
158
|
+
caps[:remote_session_id] =
|
|
159
|
+
data.delete('webdriver.remote.sessionid')
|
|
138
160
|
end
|
|
139
161
|
|
|
140
162
|
KNOWN.each do |cap|
|
|
@@ -269,7 +291,7 @@ module Selenium
|
|
|
269
291
|
as_json == other.as_json
|
|
270
292
|
end
|
|
271
293
|
|
|
272
|
-
|
|
294
|
+
alias eql? ==
|
|
273
295
|
|
|
274
296
|
protected
|
|
275
297
|
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# Driver implementation for remote server.
|
|
26
25
|
# @api private
|
|
@@ -29,19 +28,13 @@ module Selenium
|
|
|
29
28
|
class Driver < WebDriver::Driver
|
|
30
29
|
include DriverExtensions::UploadsFiles
|
|
31
30
|
include DriverExtensions::HasSessionId
|
|
32
|
-
include DriverExtensions::HasRemoteStatus
|
|
33
31
|
|
|
34
|
-
def initialize(
|
|
35
|
-
|
|
36
|
-
if desired_capabilities.is_a?(Symbol)
|
|
37
|
-
unless Remote::Capabilities.respond_to?(desired_capabilities)
|
|
38
|
-
raise Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
|
|
39
|
-
end
|
|
32
|
+
def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
|
|
33
|
+
raise ArgumentError, "Can not set :service object on #{self.class}" if service
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
super
|
|
35
|
+
url ||= "http://#{Platform.localhost}:4444/wd/hub"
|
|
36
|
+
caps = process_options(options, capabilities)
|
|
37
|
+
super(caps: caps, url: url, **opts)
|
|
45
38
|
@bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
|
|
46
39
|
end
|
|
47
40
|
|
|
@@ -52,8 +45,20 @@ module Selenium
|
|
|
52
45
|
end
|
|
53
46
|
|
|
54
47
|
def devtools_version
|
|
55
|
-
capabilities['se:cdpVersion']&.split('.')&.first
|
|
56
|
-
|
|
48
|
+
cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
|
|
49
|
+
raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
|
|
50
|
+
|
|
51
|
+
Integer(cdp_version)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def process_options(options, capabilities)
|
|
55
|
+
if options && capabilities
|
|
56
|
+
msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
|
|
57
|
+
raise ArgumentError, msg
|
|
58
|
+
elsif options.nil? && capabilities.nil?
|
|
59
|
+
raise ArgumentError, "#{self.class} needs :options to be set"
|
|
60
|
+
end
|
|
61
|
+
options ? options.as_json : generate_capabilities(capabilities)
|
|
57
62
|
end
|
|
58
63
|
end # Driver
|
|
59
64
|
end # Remote
|
|
@@ -49,8 +49,8 @@ module Selenium
|
|
|
49
49
|
payload = JSON.generate(command_hash)
|
|
50
50
|
headers['Content-Length'] = payload.bytesize.to_s if %i[post put].include?(verb)
|
|
51
51
|
|
|
52
|
-
WebDriver.logger.
|
|
53
|
-
WebDriver.logger.debug(" > #{headers.inspect}")
|
|
52
|
+
WebDriver.logger.debug(" >>> #{url} | #{payload}", id: :command)
|
|
53
|
+
WebDriver.logger.debug(" > #{headers.inspect}", id: :header)
|
|
54
54
|
elsif verb == :post
|
|
55
55
|
payload = '{}'
|
|
56
56
|
headers['Content-Length'] = '2'
|
|
@@ -75,7 +75,7 @@ module Selenium
|
|
|
75
75
|
code = code.to_i
|
|
76
76
|
body = body.to_s.strip
|
|
77
77
|
content_type = content_type.to_s
|
|
78
|
-
WebDriver.logger.
|
|
78
|
+
WebDriver.logger.debug("<- #{body}", id: :command)
|
|
79
79
|
|
|
80
80
|
if content_type.include? CONTENT_TYPE
|
|
81
81
|
raise Error::WebDriverError, "empty body: #{content_type.inspect} (#{code})\n#{body}" if body.empty?
|
|
@@ -22,7 +22,6 @@ require 'curb'
|
|
|
22
22
|
module Selenium
|
|
23
23
|
module WebDriver
|
|
24
24
|
module Remote
|
|
25
|
-
|
|
26
25
|
module Http
|
|
27
26
|
#
|
|
28
27
|
# An alternative to the default Net::HTTP client.
|
|
@@ -38,7 +37,6 @@ module Selenium
|
|
|
38
37
|
#
|
|
39
38
|
|
|
40
39
|
class Curb < Common
|
|
41
|
-
|
|
42
40
|
def quit_errors
|
|
43
41
|
[Curl::Err::RecvError] + super
|
|
44
42
|
end
|
|
@@ -85,7 +83,7 @@ module Selenium
|
|
|
85
83
|
c.max_redirects = MAX_REDIRECTS
|
|
86
84
|
c.follow_location = true
|
|
87
85
|
c.timeout = @timeout if @timeout
|
|
88
|
-
c.verbose = WebDriver.logger.
|
|
86
|
+
c.verbose = WebDriver.logger.debug?
|
|
89
87
|
|
|
90
88
|
c
|
|
91
89
|
end
|
|
@@ -75,9 +75,10 @@ module Selenium
|
|
|
75
75
|
begin
|
|
76
76
|
request = new_request_for(verb, url, headers, payload)
|
|
77
77
|
response = response_for(request)
|
|
78
|
-
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE
|
|
79
|
-
# a retry is sometimes needed
|
|
80
|
-
# run out of ephemeral ports
|
|
78
|
+
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE, Errno::EADDRNOTAVAIL
|
|
79
|
+
# a retry is sometimes needed:
|
|
80
|
+
# on Windows XP where we may quickly run out of ephemeral ports
|
|
81
|
+
# when the port becomes temporarily unavailable
|
|
81
82
|
#
|
|
82
83
|
# A more robust solution is bumping the MaxUserPort setting
|
|
83
84
|
# as described here:
|
|
@@ -85,13 +86,6 @@ module Selenium
|
|
|
85
86
|
# http://msdn.microsoft.com/en-us/library/aa560610%28v=bts.20%29.aspx
|
|
86
87
|
raise if retries >= MAX_RETRIES
|
|
87
88
|
|
|
88
|
-
retries += 1
|
|
89
|
-
sleep 2
|
|
90
|
-
retry
|
|
91
|
-
rescue Errno::EADDRNOTAVAIL => e
|
|
92
|
-
# a retry is sometimes needed when the port becomes temporarily unavailable
|
|
93
|
-
raise if retries >= MAX_RETRIES
|
|
94
|
-
|
|
95
89
|
retries += 1
|
|
96
90
|
sleep 2
|
|
97
91
|
retry
|
|
@@ -106,6 +100,7 @@ module Selenium
|
|
|
106
100
|
|
|
107
101
|
request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
|
|
108
102
|
else
|
|
103
|
+
WebDriver.logger.debug(" <<< #{response.instance_variable_get(:@header).inspect}", id: :header)
|
|
109
104
|
create_response response.code, response.body, response.content_type
|
|
110
105
|
end
|
|
111
106
|
end
|
|
@@ -142,8 +137,8 @@ module Selenium
|
|
|
142
137
|
|
|
143
138
|
def proxy
|
|
144
139
|
@proxy ||= begin
|
|
145
|
-
proxy = ENV
|
|
146
|
-
no_proxy = ENV
|
|
140
|
+
proxy = ENV.fetch('http_proxy', nil) || ENV.fetch('HTTP_PROXY', nil)
|
|
141
|
+
no_proxy = ENV.fetch('no_proxy', nil) || ENV.fetch('NO_PROXY', nil)
|
|
147
142
|
|
|
148
143
|
if proxy
|
|
149
144
|
proxy = "http://#{proxy}" unless proxy.start_with?('http://')
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# @api private
|
|
26
25
|
#
|
|
@@ -74,7 +73,7 @@ module Selenium
|
|
|
74
73
|
end
|
|
75
74
|
|
|
76
75
|
def backtrace_from_remote(server_trace)
|
|
77
|
-
server_trace.
|
|
76
|
+
server_trace.filter_map do |frame|
|
|
78
77
|
next unless frame.is_a?(Hash)
|
|
79
78
|
|
|
80
79
|
file = frame['fileName']
|
|
@@ -87,7 +86,7 @@ module Selenium
|
|
|
87
86
|
meth = 'unknown' if meth.nil? || meth.empty?
|
|
88
87
|
|
|
89
88
|
"[remote server] #{file}:#{line}:in `#{meth}'"
|
|
90
|
-
|
|
89
|
+
end
|
|
91
90
|
end
|
|
92
91
|
|
|
93
92
|
def process_error
|
|
@@ -27,7 +27,6 @@ module Selenium
|
|
|
27
27
|
autoload :Driver, 'selenium/webdriver/remote/driver'
|
|
28
28
|
autoload :Response, 'selenium/webdriver/remote/response'
|
|
29
29
|
autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
|
|
30
|
-
autoload :COMMANDS, 'selenium/webdriver/remote/commands'
|
|
31
30
|
|
|
32
31
|
module Http
|
|
33
32
|
autoload :Common, 'selenium/webdriver/remote/http/common'
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Safari
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# Driver implementation for Safari.
|
|
26
25
|
# @api private
|
|
@@ -31,6 +30,13 @@ module Selenium
|
|
|
31
30
|
DriverExtensions::HasApplePermissions,
|
|
32
31
|
DriverExtensions::HasWebStorage].freeze
|
|
33
32
|
|
|
33
|
+
include LocalDriver
|
|
34
|
+
|
|
35
|
+
def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
|
|
36
|
+
caps, url = initialize_local_driver(capabilities, options, service, url)
|
|
37
|
+
super(caps: caps, url: url, **opts)
|
|
38
|
+
end
|
|
39
|
+
|
|
34
40
|
def browser
|
|
35
41
|
:safari
|
|
36
42
|
end
|
|
@@ -21,7 +21,6 @@ module Selenium
|
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Safari
|
|
23
23
|
module Features
|
|
24
|
-
|
|
25
24
|
# https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/WebDriverEndpointDoc/Commands/Commands.html
|
|
26
25
|
SAFARI_COMMANDS = {
|
|
27
26
|
get_permissions: [:get, 'session/:session_id/apple/permissions'],
|
|
@@ -44,7 +43,6 @@ module Selenium
|
|
|
44
43
|
def attach_debugger
|
|
45
44
|
execute :attach_debugger, {}, {}
|
|
46
45
|
end
|
|
47
|
-
|
|
48
46
|
end # Bridge
|
|
49
47
|
end # Safari
|
|
50
48
|
end # WebDriver
|
|
@@ -26,7 +26,7 @@ module Selenium
|
|
|
26
26
|
# @see https://developer.apple.com/documentation/webkit/about_webdriver_for_safari
|
|
27
27
|
CAPABILITIES = {automatic_inspection: 'safari:automaticInspection',
|
|
28
28
|
automatic_profiling: 'safari:automaticProfiling'}.freeze
|
|
29
|
-
BROWSER = 'safari'
|
|
29
|
+
BROWSER = Selenium::WebDriver::Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
|
|
30
30
|
|
|
31
31
|
def add_option(name, value = nil)
|
|
32
32
|
key = name.is_a?(Hash) ? name.keys.first : name
|
|
@@ -35,6 +35,10 @@ module Selenium
|
|
|
35
35
|
super
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def as_json(*)
|
|
39
|
+
@options[:browser_name] = Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
|
|
40
|
+
super
|
|
41
|
+
end
|
|
38
42
|
end # Options
|
|
39
43
|
end # Safari
|
|
40
44
|
end # WebDriver
|
|
@@ -23,10 +23,6 @@ module Selenium
|
|
|
23
23
|
class Service < WebDriver::Service
|
|
24
24
|
DEFAULT_PORT = 7050
|
|
25
25
|
EXECUTABLE = 'safaridriver'
|
|
26
|
-
MISSING_TEXT = <<~ERROR
|
|
27
|
-
Unable to find Apple's safaridriver which comes with Safari 10.
|
|
28
|
-
More info at https://webkit.org/blog/6900/webdriver-support-in-safari-10/
|
|
29
|
-
ERROR
|
|
30
26
|
SHUTDOWN_SUPPORTED = false
|
|
31
27
|
end # Service
|
|
32
28
|
end # Safari
|
|
@@ -29,7 +29,7 @@ module Selenium
|
|
|
29
29
|
attr_accessor :use_technology_preview
|
|
30
30
|
|
|
31
31
|
def technology_preview
|
|
32
|
-
|
|
32
|
+
'/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def technology_preview!
|
|
@@ -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
|