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.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +234 -1
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/README.md +1 -1
  7. data/bin/linux/selenium-manager +0 -0
  8. data/bin/macos/selenium-manager +0 -0
  9. data/bin/windows/selenium-manager.exe +0 -0
  10. data/lib/selenium/server.rb +36 -27
  11. data/lib/selenium/webdriver/atoms/findElements.js +0 -0
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  14. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  15. data/lib/selenium/webdriver/atoms.rb +2 -3
  16. data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
  17. data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  19. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  20. data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
  21. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  22. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  23. data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
  24. data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
  25. data/lib/selenium/webdriver/bidi/session.rb +51 -0
  26. data/lib/selenium/webdriver/bidi.rb +56 -0
  27. data/lib/selenium/webdriver/chrome/driver.rb +9 -29
  28. data/lib/selenium/webdriver/chrome/features.rb +6 -68
  29. data/lib/selenium/webdriver/chrome/options.rb +3 -223
  30. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  31. data/lib/selenium/webdriver/chrome/service.rb +3 -23
  32. data/lib/selenium/webdriver/chrome.rb +0 -14
  33. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  34. data/lib/selenium/webdriver/chromium/features.rb +103 -0
  35. data/lib/selenium/webdriver/chromium/options.rb +261 -0
  36. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  37. data/lib/selenium/webdriver/chromium/service.rb +42 -0
  38. data/lib/selenium/webdriver/chromium.rb +32 -0
  39. data/lib/selenium/webdriver/common/action_builder.rb +64 -22
  40. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  41. data/lib/selenium/webdriver/common/driver.rb +36 -74
  42. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  43. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  44. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  47. data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +10 -5
  48. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
  49. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
  51. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
  55. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -2
  56. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  57. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -69
  58. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  59. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
  60. data/lib/selenium/webdriver/common/driver_finder.rb +44 -0
  61. data/lib/selenium/webdriver/common/element.rb +8 -8
  62. data/lib/selenium/webdriver/common/error.rb +1 -3
  63. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  64. data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
  65. data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
  66. data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
  67. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
  68. data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
  69. data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
  70. data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
  71. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
  72. data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
  73. data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
  74. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
  75. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
  76. data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
  77. data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
  78. data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
  79. data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
  80. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
  81. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
  82. data/lib/selenium/webdriver/common/keys.rb +1 -0
  83. data/lib/selenium/webdriver/common/local_driver.rb +55 -0
  84. data/lib/selenium/webdriver/common/logger.rb +76 -24
  85. data/lib/selenium/webdriver/common/manager.rb +0 -27
  86. data/lib/selenium/webdriver/common/options.rb +32 -17
  87. data/lib/selenium/webdriver/common/platform.rb +8 -5
  88. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  89. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  90. data/lib/selenium/webdriver/common/proxy.rb +1 -1
  91. data/lib/selenium/webdriver/common/search_context.rb +0 -6
  92. data/lib/selenium/webdriver/common/selenium_manager.rb +108 -0
  93. data/lib/selenium/webdriver/common/service.rb +20 -23
  94. data/lib/selenium/webdriver/common/service_manager.rb +8 -15
  95. data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
  96. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  97. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  98. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  99. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  100. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  101. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
  102. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
  103. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  104. data/lib/selenium/webdriver/common/websocket_connection.rb +164 -0
  105. data/lib/selenium/webdriver/common/window.rb +6 -6
  106. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  107. data/lib/selenium/webdriver/common.rb +21 -3
  108. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  109. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  110. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  111. data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
  112. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  113. data/lib/selenium/webdriver/devtools/request.rb +1 -3
  114. data/lib/selenium/webdriver/devtools/response.rb +1 -3
  115. data/lib/selenium/webdriver/devtools.rb +17 -114
  116. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  117. data/lib/selenium/webdriver/edge/features.rb +4 -4
  118. data/lib/selenium/webdriver/edge/options.rb +3 -5
  119. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  120. data/lib/selenium/webdriver/edge/service.rb +2 -6
  121. data/lib/selenium/webdriver/firefox/driver.rb +9 -2
  122. data/lib/selenium/webdriver/firefox/features.rb +6 -6
  123. data/lib/selenium/webdriver/firefox/options.rb +9 -3
  124. data/lib/selenium/webdriver/firefox/profile.rb +8 -12
  125. data/lib/selenium/webdriver/firefox/service.rb +0 -6
  126. data/lib/selenium/webdriver/firefox/util.rb +46 -0
  127. data/lib/selenium/webdriver/firefox.rb +1 -14
  128. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  129. data/lib/selenium/webdriver/ie/service.rb +1 -7
  130. data/lib/selenium/webdriver/ie.rb +0 -14
  131. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +15 -8
  132. data/lib/selenium/webdriver/remote/bridge.rb +65 -35
  133. data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
  134. data/lib/selenium/webdriver/remote/driver.rb +19 -14
  135. data/lib/selenium/webdriver/remote/http/common.rb +3 -3
  136. data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
  137. data/lib/selenium/webdriver/remote/http/default.rb +7 -12
  138. data/lib/selenium/webdriver/remote/response.rb +2 -3
  139. data/lib/selenium/webdriver/remote.rb +0 -1
  140. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  141. data/lib/selenium/webdriver/safari/features.rb +0 -2
  142. data/lib/selenium/webdriver/safari/options.rb +5 -1
  143. data/lib/selenium/webdriver/safari/service.rb +0 -4
  144. data/lib/selenium/webdriver/safari.rb +1 -15
  145. data/lib/selenium/webdriver/support/color.rb +22 -22
  146. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  147. data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
  148. data/lib/selenium/webdriver/support/guards.rb +1 -1
  149. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  150. data/lib/selenium/webdriver/support/select.rb +3 -1
  151. data/lib/selenium/webdriver/version.rb +1 -1
  152. data/lib/selenium/webdriver.rb +5 -4
  153. data/selenium-webdriver.gemspec +13 -12
  154. metadata +70 -73
  155. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
  156. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  157. 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] :url url for the remote server
34
- # @param [Object] :http_client an HTTP client instance that implements the same protocol as Http::Default
34
+ # @param [String, URI] url url for the remote server
35
+ # @param [Object] http_client an HTTP client instance that implements the same protocol as Http::Default
35
36
  # @api private
36
37
  #
37
38
 
@@ -118,7 +119,7 @@ module Selenium
118
119
  end
119
120
 
120
121
  def alert=(keys)
121
- execute :send_alert_text, {}, {value: keys.split(//), text: keys}
122
+ execute :send_alert_text, {}, {value: keys.chars, text: keys}
122
123
  end
123
124
 
124
125
  def alert_text
@@ -146,9 +147,7 @@ module Selenium
146
147
  end
147
148
 
148
149
  def page_source
149
- execute_script('var source = document.documentElement.outerHTML;' \
150
- 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
151
- 'return source;')
150
+ execute :get_page_source
152
151
  end
153
152
 
154
153
  #
@@ -188,6 +187,7 @@ module Selenium
188
187
  execute :delete_session
189
188
  http.close
190
189
  rescue *QUIT_ERRORS
190
+ nil
191
191
  end
192
192
 
193
193
  def close
@@ -369,21 +369,10 @@ module Selenium
369
369
  # actions
370
370
  #
371
371
 
372
- def action(async = false)
373
- ActionBuilder.new self,
374
- Interactions.pointer(:mouse, name: 'mouse'),
375
- Interactions.key('keyboard'),
376
- async
377
- end
378
- alias_method :actions, :action
379
-
380
- def mouse
381
- raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead'
382
- end
383
-
384
- def keyboard
385
- raise Error::UnsupportedOperationError, '#keyboard is no longer supported, use #action instead'
372
+ def action(async: false, devices: [], duration: 250)
373
+ ActionBuilder.new self, async: async, devices: devices, duration: duration
386
374
  end
375
+ alias actions action
387
376
 
388
377
  def send_actions(data)
389
378
  execute :actions, {}, {actions: data}
@@ -405,20 +394,21 @@ module Selenium
405
394
  # TODO: rework file detectors before Selenium 4.0
406
395
  if @file_detector
407
396
  local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
408
- if local_files.any?
397
+ if local_files&.any?
409
398
  keys = local_files.map { |local_file| upload(local_file) }
410
399
  keys = Array(keys.join("\n"))
411
400
  end
412
401
  end
413
402
 
414
403
  # Keep .split(//) for backward compatibility for now
415
- text = keys.join('')
416
- execute :element_send_keys, {id: element}, {value: text.split(//), text: text}
404
+ text = keys.join
405
+ execute :element_send_keys, {id: element}, {value: text.chars, text: text}
417
406
  end
418
407
 
419
408
  def upload(local_file)
420
409
  unless File.file?(local_file)
421
- WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
410
+ WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!",
411
+ id: :file_detector)
422
412
  raise Error::WebDriverError, "You are trying to work with something that isn't a file."
423
413
  end
424
414
 
@@ -430,10 +420,19 @@ module Selenium
430
420
  end
431
421
 
432
422
  def submit_element(element)
433
- form = find_element_by('xpath', "./ancestor-or-self::form", [:element, element])
434
- execute_script("var e = arguments[0].ownerDocument.createEvent('Event');" \
435
- "e.initEvent('submit', true, true);" \
436
- 'if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }', form.as_json)
423
+ script = "/* submitForm */ var form = arguments[0];\n" \
424
+ "while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
425
+ "form = form.parentNode;\n" \
426
+ "}\n" \
427
+ "if (!form) { throw Error('Unable to find containing form element'); }\n" \
428
+ "if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" \
429
+ "var e = form.ownerDocument.createEvent('Event');\n" \
430
+ "e.initEvent('submit', true, true);\n" \
431
+ "if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n"
432
+
433
+ execute_script(script, Element::ELEMENT_KEY => element)
434
+ rescue Error::JavascriptError
435
+ raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
437
436
  end
438
437
 
439
438
  #
@@ -445,7 +444,7 @@ module Selenium
445
444
  end
446
445
 
447
446
  def element_attribute(element, name)
448
- WebDriver.logger.info "Using script for :getAttribute of #{name}"
447
+ WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
449
448
  execute_atom :getAttribute, element, name
450
449
  end
451
450
 
@@ -505,7 +504,7 @@ module Selenium
505
504
  end
506
505
 
507
506
  def element_displayed?(element)
508
- WebDriver.logger.info 'Using script for :isDisplayed'
507
+ WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
509
508
  execute_atom :isDisplayed, element
510
509
  end
511
510
 
@@ -521,7 +520,7 @@ module Selenium
521
520
  Element.new self, element_id_from(execute(:get_active_element))
522
521
  end
523
522
 
524
- alias_method :switch_to_active_element, :active_element
523
+ alias switch_to_active_element active_element
525
524
 
526
525
  def find_element_by(how, what, parent_ref = [])
527
526
  how, what = convert_locator(how, what)
@@ -564,6 +563,39 @@ module Selenium
564
563
  ShadowRoot.new self, shadow_root_id_from(id)
565
564
  end
566
565
 
566
+ #
567
+ # virtual-authenticator
568
+ #
569
+
570
+ def add_virtual_authenticator(options)
571
+ authenticator_id = execute :add_virtual_authenticator, {}, options.as_json
572
+ VirtualAuthenticator.new(self, authenticator_id, options)
573
+ end
574
+
575
+ def remove_virtual_authenticator(id)
576
+ execute :remove_virtual_authenticator, {authenticatorId: id}
577
+ end
578
+
579
+ def add_credential(credential, id)
580
+ execute :add_credential, {authenticatorId: id}, credential
581
+ end
582
+
583
+ def credentials(authenticator_id)
584
+ execute :get_credentials, {authenticatorId: authenticator_id}
585
+ end
586
+
587
+ def remove_credential(credential_id, authenticator_id)
588
+ execute :remove_credential, {credentialId: credential_id, authenticatorId: authenticator_id}
589
+ end
590
+
591
+ def remove_all_credentials(authenticator_id)
592
+ execute :remove_all_credentials, {authenticatorId: authenticator_id}
593
+ end
594
+
595
+ def user_verified(verified, authenticator_id)
596
+ execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
597
+ end
598
+
567
599
  private
568
600
 
569
601
  #
@@ -584,7 +616,7 @@ module Selenium
584
616
  raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
585
617
  end
586
618
 
587
- WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
619
+ WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
588
620
  http.call(verb, path, command_hash)['value']
589
621
  end
590
622
 
@@ -639,8 +671,6 @@ module Selenium
639
671
  when 'name'
640
672
  how = 'css selector'
641
673
  what = "*[name='#{escape_css(what.to_s)}']"
642
- when 'tag name'
643
- how = 'css selector'
644
674
  end
645
675
 
646
676
  if what.is_a?(Hash)
@@ -653,7 +683,7 @@ module Selenium
653
683
  [how, what]
654
684
  end
655
685
 
656
- ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/.freeze
686
+ ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
657
687
  UNICODE_CODE_POINT = 30
658
688
 
659
689
  # Escapes invalid characters in CSS selector.
@@ -20,14 +20,12 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
-
24
23
  #
25
24
  # Specification of the desired and/or actual capabilities of the browser that the
26
25
  # server is being asked to create.
27
26
  #
28
27
 
29
28
  class Capabilities
30
-
31
29
  KNOWN = [
32
30
  :browser_name,
33
31
  :browser_version,
@@ -59,10 +57,25 @@ module Selenium
59
57
  # Backward compatibility
60
58
  #
61
59
 
62
- alias_method :version, :browser_version
63
- alias_method :version=, :browser_version=
64
- alias_method :platform, :platform_name
65
- alias_method :platform=, :platform_name=
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
- alias_method :microsoftedge, :edge
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
- alias_method :ff, :firefox
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? ? "Safari Technology Preview" : 'safari'
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
- alias_method :ie, :internet_explorer
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] = data.delete('webdriver.remote.sessionid')
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
- alias_method :eql?, :==
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(bridge: nil, listener: nil, **opts)
35
- desired_capabilities = opts[:desired_capabilities]
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
- opts[:desired_capabilities] = Remote::Capabilities.__send__(desired_capabilities)
42
- end
43
- opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
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
- raise(Error::WebDriverError, "DevTools is not supported by the Remote Server")
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.info(" >>> #{url} | #{payload}")
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.info("<- #{body}")
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.info?
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 on Windows XP where we may quickly
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['http_proxy'] || ENV['HTTP_PROXY']
146
- no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
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.map { |frame|
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
- }.compact
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
- "/Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver"
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