selenium-webdriver 4.1.0 → 4.14.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 +295 -1
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +2 -2
- 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 -39
- data/lib/selenium/webdriver/atoms/findElements.js +3 -4
- 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 +5 -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/{common/driver_extensions/has_location.rb → bidi/log/filter_by.rb} +14 -11
- 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 +4 -19
- data/lib/selenium/webdriver/chrome.rb +0 -16
- data/lib/selenium/webdriver/chromium/driver.rb +60 -0
- data/lib/selenium/webdriver/chromium/features.rb +103 -0
- data/lib/selenium/webdriver/chromium/options.rb +243 -0
- data/lib/selenium/webdriver/chromium/profile.rb +113 -0
- data/lib/selenium/webdriver/chromium.rb +29 -0
- data/lib/selenium/webdriver/common/action_builder.rb +62 -22
- data/lib/selenium/webdriver/common/child_process.rb +124 -0
- data/lib/selenium/webdriver/common/driver.rb +31 -81
- 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_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 +45 -0
- data/lib/selenium/webdriver/common/element.rb +8 -8
- data/lib/selenium/webdriver/common/error.rb +28 -5
- 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/{driver_extensions/has_network_connection.rb → interactions/pointer_cancel.rb} +19 -11
- 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 +46 -0
- data/lib/selenium/webdriver/common/logger.rb +90 -25
- data/lib/selenium/webdriver/common/manager.rb +0 -27
- data/lib/selenium/webdriver/common/options.rb +13 -17
- data/lib/selenium/webdriver/common/platform.rb +5 -51
- 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 +2 -2
- data/lib/selenium/webdriver/common/search_context.rb +0 -6
- data/lib/selenium/webdriver/common/selenium_manager.rb +134 -0
- data/lib/selenium/webdriver/common/service.rb +21 -30
- 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 -5
- 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 +17 -5
- data/lib/selenium/webdriver/edge/profile.rb +2 -2
- data/lib/selenium/webdriver/edge/service.rb +8 -7
- data/lib/selenium/webdriver/edge.rb +0 -2
- 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 +7 -16
- data/lib/selenium/webdriver/firefox/profile.rb +8 -12
- data/lib/selenium/webdriver/firefox/service.rb +0 -18
- 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/options.rb +4 -3
- data/lib/selenium/webdriver/ie/service.rb +0 -22
- 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 +3 -53
- data/lib/selenium/webdriver/remote/driver.rb +31 -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 +8 -14
- data/lib/selenium/webdriver/remote/response.rb +2 -3
- data/lib/selenium/webdriver/remote/server_error.rb +1 -1
- 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 +10 -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 +6 -4
- data/selenium-webdriver.gemspec +14 -12
- metadata +73 -65
- 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
|
@@ -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,
|
|
@@ -55,60 +53,11 @@ module Selenium
|
|
|
55
53
|
end
|
|
56
54
|
end
|
|
57
55
|
|
|
58
|
-
#
|
|
59
|
-
# Backward compatibility
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
alias_method :version, :browser_version
|
|
63
|
-
alias_method :version=, :browser_version=
|
|
64
|
-
alias_method :platform, :platform_name
|
|
65
|
-
alias_method :platform=, :platform_name=
|
|
66
|
-
|
|
67
56
|
#
|
|
68
57
|
# Convenience methods for the common choices.
|
|
69
58
|
#
|
|
70
59
|
|
|
71
60
|
class << self
|
|
72
|
-
def chrome(opts = {})
|
|
73
|
-
new({
|
|
74
|
-
browser_name: 'chrome'
|
|
75
|
-
}.merge(opts))
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def edge(opts = {})
|
|
79
|
-
new({
|
|
80
|
-
browser_name: 'MicrosoftEdge'
|
|
81
|
-
}.merge(opts))
|
|
82
|
-
end
|
|
83
|
-
alias_method :microsoftedge, :edge
|
|
84
|
-
|
|
85
|
-
def firefox(opts = {})
|
|
86
|
-
new({
|
|
87
|
-
browser_name: 'firefox'
|
|
88
|
-
}.merge(opts))
|
|
89
|
-
end
|
|
90
|
-
alias_method :ff, :firefox
|
|
91
|
-
|
|
92
|
-
def safari(opts = {})
|
|
93
|
-
new({
|
|
94
|
-
browser_name: Selenium::WebDriver::Safari.technology_preview? ? "Safari Technology Preview" : 'safari'
|
|
95
|
-
}.merge(opts))
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def htmlunit(opts = {})
|
|
99
|
-
new({
|
|
100
|
-
browser_name: 'htmlunit'
|
|
101
|
-
}.merge(opts))
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def internet_explorer(opts = {})
|
|
105
|
-
new({
|
|
106
|
-
browser_name: 'internet explorer',
|
|
107
|
-
platform_name: :windows
|
|
108
|
-
}.merge(opts))
|
|
109
|
-
end
|
|
110
|
-
alias_method :ie, :internet_explorer
|
|
111
|
-
|
|
112
61
|
def always_match(capabilities)
|
|
113
62
|
new(always_match: capabilities)
|
|
114
63
|
end
|
|
@@ -134,7 +83,8 @@ module Selenium
|
|
|
134
83
|
|
|
135
84
|
# Remote Server Specific
|
|
136
85
|
if data.key?('webdriver.remote.sessionid')
|
|
137
|
-
caps[:remote_session_id] =
|
|
86
|
+
caps[:remote_session_id] =
|
|
87
|
+
data.delete('webdriver.remote.sessionid')
|
|
138
88
|
end
|
|
139
89
|
|
|
140
90
|
KNOWN.each do |cap|
|
|
@@ -269,7 +219,7 @@ module Selenium
|
|
|
269
219
|
as_json == other.as_json
|
|
270
220
|
end
|
|
271
221
|
|
|
272
|
-
|
|
222
|
+
alias eql? ==
|
|
273
223
|
|
|
274
224
|
protected
|
|
275
225
|
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Remote
|
|
23
|
-
|
|
24
23
|
#
|
|
25
24
|
# Driver implementation for remote server.
|
|
26
25
|
# @api private
|
|
@@ -29,19 +28,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,32 @@ 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)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def generate_capabilities(capabilities)
|
|
65
|
+
Array(capabilities).map { |cap|
|
|
66
|
+
if cap.is_a? Symbol
|
|
67
|
+
cap = WebDriver::Options.send(cap)
|
|
68
|
+
elsif !cap.respond_to? :as_json
|
|
69
|
+
msg = ":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not"
|
|
70
|
+
raise ArgumentError, msg
|
|
71
|
+
end
|
|
72
|
+
cap.as_json
|
|
73
|
+
}.inject(:merge)
|
|
57
74
|
end
|
|
58
75
|
end # Driver
|
|
59
76
|
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
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
# KIND, either express or implied. See the License for the
|
|
17
17
|
# specific language governing permissions and limitations
|
|
18
18
|
# under the License.
|
|
19
|
-
|
|
20
|
-
require 'net/https'
|
|
21
19
|
require 'ipaddr'
|
|
22
20
|
|
|
23
21
|
module Selenium
|
|
@@ -75,9 +73,10 @@ module Selenium
|
|
|
75
73
|
begin
|
|
76
74
|
request = new_request_for(verb, url, headers, payload)
|
|
77
75
|
response = response_for(request)
|
|
78
|
-
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE
|
|
79
|
-
# a retry is sometimes needed
|
|
80
|
-
# run out of ephemeral ports
|
|
76
|
+
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE, Errno::EADDRNOTAVAIL
|
|
77
|
+
# a retry is sometimes needed:
|
|
78
|
+
# on Windows XP where we may quickly run out of ephemeral ports
|
|
79
|
+
# when the port becomes temporarily unavailable
|
|
81
80
|
#
|
|
82
81
|
# A more robust solution is bumping the MaxUserPort setting
|
|
83
82
|
# as described here:
|
|
@@ -85,13 +84,6 @@ module Selenium
|
|
|
85
84
|
# http://msdn.microsoft.com/en-us/library/aa560610%28v=bts.20%29.aspx
|
|
86
85
|
raise if retries >= MAX_RETRIES
|
|
87
86
|
|
|
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
87
|
retries += 1
|
|
96
88
|
sleep 2
|
|
97
89
|
retry
|
|
@@ -102,10 +94,12 @@ module Selenium
|
|
|
102
94
|
end
|
|
103
95
|
|
|
104
96
|
if response.is_a? Net::HTTPRedirection
|
|
97
|
+
WebDriver.logger.debug("Redirect to #{response['Location']}; times: #{redirects}")
|
|
105
98
|
raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
|
|
106
99
|
|
|
107
100
|
request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
|
|
108
101
|
else
|
|
102
|
+
WebDriver.logger.debug(" <<< #{response.instance_variable_get(:@header).inspect}", id: :header)
|
|
109
103
|
create_response response.code, response.body, response.content_type
|
|
110
104
|
end
|
|
111
105
|
end
|
|
@@ -142,8 +136,8 @@ module Selenium
|
|
|
142
136
|
|
|
143
137
|
def proxy
|
|
144
138
|
@proxy ||= begin
|
|
145
|
-
proxy = ENV
|
|
146
|
-
no_proxy = ENV
|
|
139
|
+
proxy = ENV.fetch('http_proxy', nil) || ENV.fetch('HTTP_PROXY', nil)
|
|
140
|
+
no_proxy = ENV.fetch('no_proxy', nil) || ENV.fetch('NO_PROXY', nil)
|
|
147
141
|
|
|
148
142
|
if proxy
|
|
149
143
|
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(options: nil, service: nil, url: nil, **opts)
|
|
36
|
+
caps, url = initialize_local_driver(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,11 +23,17 @@ 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
|
|
27
|
+
|
|
28
|
+
def initialize(path: nil, port: nil, log: nil, args: nil)
|
|
29
|
+
raise Error::WebDriverError, 'Safari Service does not support setting log output' if log
|
|
30
|
+
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def log=(*)
|
|
35
|
+
raise Error::WebDriverError, 'Safari Service does not support setting log output'
|
|
36
|
+
end
|
|
31
37
|
end # Service
|
|
32
38
|
end # Safari
|
|
33
39
|
end # WebDriver
|
|
@@ -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
|