selenium-webdriver 4.1.0 → 4.28.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 +446 -1
- data/Gemfile +4 -0
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +3 -3
- 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 +41 -43
- data/lib/selenium/webdriver/atoms/findElements.js +52 -50
- data/lib/selenium/webdriver/atoms/getAttribute.js +6 -100
- data/lib/selenium/webdriver/atoms/isDisplayed.js +24 -96
- 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 +100 -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_handler.rb +65 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +147 -0
- data/lib/selenium/webdriver/bidi/network.rb +82 -0
- data/lib/selenium/webdriver/bidi/session.rb +51 -0
- data/lib/selenium/webdriver/bidi/struct.rb +42 -0
- data/lib/selenium/webdriver/bidi.rb +67 -0
- data/lib/selenium/webdriver/chrome/driver.rb +9 -29
- data/lib/selenium/webdriver/chrome/features.rb +9 -67
- 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 +5 -19
- data/lib/selenium/webdriver/chrome.rb +0 -16
- data/lib/selenium/webdriver/chromium/driver.rb +61 -0
- data/lib/selenium/webdriver/chromium/features.rb +99 -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 +60 -22
- data/lib/selenium/webdriver/common/child_process.rb +136 -0
- data/lib/selenium/webdriver/common/driver.rb +54 -89
- 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_fedcm_dialog.rb +55 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb +65 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +9 -3
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +8 -68
- 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 +97 -0
- data/lib/selenium/webdriver/common/element.rb +8 -8
- data/lib/selenium/webdriver/common/error.rb +29 -4
- data/lib/selenium/webdriver/common/fedcm/account.rb +49 -0
- data/lib/selenium/webdriver/common/fedcm/dialog.rb +74 -0
- data/lib/selenium/webdriver/common/fedcm.rb +27 -0
- 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 -71
- 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 +114 -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 +53 -0
- data/lib/selenium/webdriver/common/logger.rb +93 -28
- data/lib/selenium/webdriver/common/manager.rb +2 -29
- data/lib/selenium/webdriver/common/network.rb +64 -0
- data/lib/selenium/webdriver/common/options.rb +19 -19
- data/lib/selenium/webdriver/common/platform.rb +12 -52
- 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 +4 -4
- data/lib/selenium/webdriver/common/script.rb +45 -0
- data/lib/selenium/webdriver/common/search_context.rb +10 -8
- data/lib/selenium/webdriver/common/selenium_manager.rb +104 -0
- data/lib/selenium/webdriver/common/service.rb +24 -26
- data/lib/selenium/webdriver/common/service_manager.rb +9 -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 +3 -3
- data/lib/selenium/webdriver/common/takes_screenshot.rb +6 -5
- data/lib/selenium/webdriver/common/target_locator.rb +5 -5
- 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/wait.rb +1 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +176 -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 +27 -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 +8 -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 +11 -7
- data/lib/selenium/webdriver/firefox/options.rb +10 -16
- data/lib/selenium/webdriver/firefox/profile.rb +21 -17
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +1 -1
- data/lib/selenium/webdriver/firefox/service.rb +1 -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/features.rb +34 -0
- data/lib/selenium/webdriver/ie/options.rb +6 -4
- data/lib/selenium/webdriver/ie/service.rb +1 -22
- data/lib/selenium/webdriver/ie.rb +4 -17
- data/lib/selenium/webdriver/remote/bidi_bridge.rb +66 -0
- data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +22 -9
- data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
- data/lib/selenium/webdriver/remote/bridge.rb +158 -100
- data/lib/selenium/webdriver/remote/capabilities.rb +5 -55
- data/lib/selenium/webdriver/remote/driver.rb +35 -14
- data/lib/selenium/webdriver/remote/features.rb +75 -0
- data/lib/selenium/webdriver/remote/http/common.rb +26 -6
- data/lib/selenium/webdriver/remote/http/curb.rb +10 -6
- data/lib/selenium/webdriver/remote/http/default.rb +8 -14
- data/lib/selenium/webdriver/remote/response.rb +14 -22
- data/lib/selenium/webdriver/remote/server_error.rb +2 -2
- data/lib/selenium/webdriver/remote.rb +3 -2
- data/lib/selenium/webdriver/safari/driver.rb +7 -1
- data/lib/selenium/webdriver/safari/features.rb +5 -3
- 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/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +14 -14
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
- data/lib/selenium/webdriver/support/guards.rb +4 -4
- 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 +7 -5
- data/selenium-webdriver.gemspec +22 -16
- metadata +137 -47
- data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module Remote
|
23
|
+
class Bridge
|
24
|
+
class LocatorConverter
|
25
|
+
ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
|
26
|
+
UNICODE_CODE_POINT = 30
|
27
|
+
|
28
|
+
#
|
29
|
+
# Converts a locator to a specification compatible one.
|
30
|
+
# @param [String, Symbol] how
|
31
|
+
# @param [String] what
|
32
|
+
#
|
33
|
+
|
34
|
+
def convert(how, what)
|
35
|
+
how = SearchContext.finders[how.to_sym] || how
|
36
|
+
|
37
|
+
case how
|
38
|
+
when 'class name'
|
39
|
+
how = 'css selector'
|
40
|
+
what = ".#{escape_css(what.to_s)}"
|
41
|
+
when 'id'
|
42
|
+
how = 'css selector'
|
43
|
+
what = "##{escape_css(what.to_s)}"
|
44
|
+
when 'name'
|
45
|
+
how = 'css selector'
|
46
|
+
what = "*[name='#{escape_css(what.to_s)}']"
|
47
|
+
end
|
48
|
+
|
49
|
+
if what.is_a?(Hash)
|
50
|
+
what = what.each_with_object({}) do |(h, w), hash|
|
51
|
+
h, w = convert(h.to_s, w)
|
52
|
+
hash[h] = w
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
[how, what]
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
#
|
62
|
+
# Escapes invalid characters in CSS selector.
|
63
|
+
# @see https://mathiasbynens.be/notes/css-escapes
|
64
|
+
#
|
65
|
+
|
66
|
+
def escape_css(string)
|
67
|
+
string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
|
68
|
+
string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
|
69
|
+
|
70
|
+
string
|
71
|
+
end
|
72
|
+
end # LocatorConverter
|
73
|
+
end # Bridge
|
74
|
+
end # Remote
|
75
|
+
end # WebDriver
|
76
|
+
end # Selenium
|
@@ -21,6 +21,9 @@ module Selenium
|
|
21
21
|
module WebDriver
|
22
22
|
module Remote
|
23
23
|
class Bridge
|
24
|
+
autoload :COMMANDS, 'selenium/webdriver/remote/bridge/commands'
|
25
|
+
autoload :LocatorConverter, 'selenium/webdriver/remote/bridge/locator_converter'
|
26
|
+
|
24
27
|
include Atoms
|
25
28
|
|
26
29
|
PORT = 4444
|
@@ -28,10 +31,29 @@ module Selenium
|
|
28
31
|
attr_accessor :http, :file_detector
|
29
32
|
attr_reader :capabilities
|
30
33
|
|
34
|
+
class << self
|
35
|
+
attr_reader :extra_commands
|
36
|
+
attr_writer :element_class, :locator_converter
|
37
|
+
|
38
|
+
def add_command(name, verb, url, &)
|
39
|
+
@extra_commands ||= {}
|
40
|
+
@extra_commands[name] = [verb, url]
|
41
|
+
define_method(name, &)
|
42
|
+
end
|
43
|
+
|
44
|
+
def locator_converter
|
45
|
+
@locator_converter ||= LocatorConverter.new
|
46
|
+
end
|
47
|
+
|
48
|
+
def element_class
|
49
|
+
@element_class ||= Element
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
31
53
|
#
|
32
54
|
# Initializes the bridge with the given server URL
|
33
|
-
# @param [String, URI]
|
34
|
-
# @param [Object]
|
55
|
+
# @param [String, URI] url url for the remote server
|
56
|
+
# @param [Object] http_client an HTTP client instance that implements the same protocol as Http::Default
|
35
57
|
# @api private
|
36
58
|
#
|
37
59
|
|
@@ -42,6 +64,8 @@ module Selenium
|
|
42
64
|
@http = http_client || Http::Default.new
|
43
65
|
@http.server_url = uri
|
44
66
|
@file_detector = nil
|
67
|
+
|
68
|
+
@locator_converter = self.class.locator_converter
|
45
69
|
end
|
46
70
|
|
47
71
|
#
|
@@ -59,14 +83,16 @@ module Selenium
|
|
59
83
|
@capabilities = Capabilities.json_create(capabilities)
|
60
84
|
|
61
85
|
case @capabilities[:browser_name]
|
62
|
-
when 'chrome'
|
86
|
+
when 'chrome', 'chrome-headless-shell'
|
63
87
|
extend(WebDriver::Chrome::Features)
|
64
88
|
when 'firefox'
|
65
89
|
extend(WebDriver::Firefox::Features)
|
66
|
-
when 'msedge'
|
90
|
+
when 'msedge', 'MicrosoftEdge'
|
67
91
|
extend(WebDriver::Edge::Features)
|
68
92
|
when 'Safari', 'Safari Technology Preview'
|
69
93
|
extend(WebDriver::Safari::Features)
|
94
|
+
when 'internet explorer'
|
95
|
+
extend(WebDriver::IE::Features)
|
70
96
|
end
|
71
97
|
end
|
72
98
|
|
@@ -81,7 +107,7 @@ module Selenium
|
|
81
107
|
def browser
|
82
108
|
@browser ||= begin
|
83
109
|
name = @capabilities.browser_name
|
84
|
-
name ? name.tr(' ', '_').downcase.to_sym : 'unknown'
|
110
|
+
name ? name.tr(' -', '_').downcase.to_sym : 'unknown'
|
85
111
|
end
|
86
112
|
end
|
87
113
|
|
@@ -118,7 +144,7 @@ module Selenium
|
|
118
144
|
end
|
119
145
|
|
120
146
|
def alert=(keys)
|
121
|
-
execute :send_alert_text, {}, {value: keys.
|
147
|
+
execute :send_alert_text, {}, {value: keys.chars, text: keys}
|
122
148
|
end
|
123
149
|
|
124
150
|
def alert_text
|
@@ -146,9 +172,7 @@ module Selenium
|
|
146
172
|
end
|
147
173
|
|
148
174
|
def page_source
|
149
|
-
|
150
|
-
'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
|
151
|
-
'return source;')
|
175
|
+
execute :get_page_source
|
152
176
|
end
|
153
177
|
|
154
178
|
#
|
@@ -188,6 +212,7 @@ module Selenium
|
|
188
212
|
execute :delete_session
|
189
213
|
http.close
|
190
214
|
rescue *QUIT_ERRORS
|
215
|
+
nil
|
191
216
|
end
|
192
217
|
|
193
218
|
def close
|
@@ -276,6 +301,7 @@ module Selenium
|
|
276
301
|
#
|
277
302
|
|
278
303
|
def local_storage_item(key, value = nil)
|
304
|
+
WebDriver.logger.deprecate('local_storage_item(key, value)', id: :local_storage_item)
|
279
305
|
if value
|
280
306
|
execute_script("localStorage.setItem('#{key}', '#{value}')")
|
281
307
|
else
|
@@ -284,22 +310,27 @@ module Selenium
|
|
284
310
|
end
|
285
311
|
|
286
312
|
def remove_local_storage_item(key)
|
313
|
+
WebDriver.logger.deprecate('remove_local_storage_item(key)', id: :remove_local_storage_item)
|
287
314
|
execute_script("localStorage.removeItem('#{key}')")
|
288
315
|
end
|
289
316
|
|
290
317
|
def local_storage_keys
|
318
|
+
WebDriver.logger.deprecate('local_storage_keys', id: :local_storage_keys)
|
291
319
|
execute_script('return Object.keys(localStorage)')
|
292
320
|
end
|
293
321
|
|
294
322
|
def clear_local_storage
|
323
|
+
WebDriver.logger.deprecate('clear_local_storage', id: :clear_local_storage)
|
295
324
|
execute_script('localStorage.clear()')
|
296
325
|
end
|
297
326
|
|
298
327
|
def local_storage_size
|
328
|
+
WebDriver.logger.deprecate('local_storage_size', id: :local_storage_size)
|
299
329
|
execute_script('return localStorage.length')
|
300
330
|
end
|
301
331
|
|
302
332
|
def session_storage_item(key, value = nil)
|
333
|
+
WebDriver.logger.deprecate('session_storage_item(key, value)', id: :session_storage_item)
|
303
334
|
if value
|
304
335
|
execute_script("sessionStorage.setItem('#{key}', '#{value}')")
|
305
336
|
else
|
@@ -308,18 +339,22 @@ module Selenium
|
|
308
339
|
end
|
309
340
|
|
310
341
|
def remove_session_storage_item(key)
|
342
|
+
WebDriver.logger.deprecate('remove_session_storage_item(key)', id: :remove_session_storage_item)
|
311
343
|
execute_script("sessionStorage.removeItem('#{key}')")
|
312
344
|
end
|
313
345
|
|
314
346
|
def session_storage_keys
|
347
|
+
WebDriver.logger.deprecate('session_storage_keys', id: :session_storage_keys)
|
315
348
|
execute_script('return Object.keys(sessionStorage)')
|
316
349
|
end
|
317
350
|
|
318
351
|
def clear_session_storage
|
352
|
+
WebDriver.logger.deprecate('clear_session_storage', id: :clear_session_storage)
|
319
353
|
execute_script('sessionStorage.clear()')
|
320
354
|
end
|
321
355
|
|
322
356
|
def session_storage_size
|
357
|
+
WebDriver.logger.deprecate('session_storage_size', id: :session_storage_size)
|
323
358
|
execute_script('return sessionStorage.length')
|
324
359
|
end
|
325
360
|
|
@@ -369,21 +404,10 @@ module Selenium
|
|
369
404
|
# actions
|
370
405
|
#
|
371
406
|
|
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'
|
407
|
+
def action(async: false, devices: [], duration: 250)
|
408
|
+
ActionBuilder.new self, async: async, devices: devices, duration: duration
|
386
409
|
end
|
410
|
+
alias actions action
|
387
411
|
|
388
412
|
def send_actions(data)
|
389
413
|
execute :actions, {}, {actions: data}
|
@@ -402,27 +426,9 @@ module Selenium
|
|
402
426
|
end
|
403
427
|
|
404
428
|
def send_keys_to_element(element, keys)
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
if local_files.any?
|
409
|
-
keys = local_files.map { |local_file| upload(local_file) }
|
410
|
-
keys = Array(keys.join("\n"))
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
# Keep .split(//) for backward compatibility for now
|
415
|
-
text = keys.join('')
|
416
|
-
execute :element_send_keys, {id: element}, {value: text.split(//), text: text}
|
417
|
-
end
|
418
|
-
|
419
|
-
def upload(local_file)
|
420
|
-
unless File.file?(local_file)
|
421
|
-
WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
|
422
|
-
raise Error::WebDriverError, "You are trying to work with something that isn't a file."
|
423
|
-
end
|
424
|
-
|
425
|
-
execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
|
429
|
+
keys = upload_if_necessary(keys) if @file_detector
|
430
|
+
text = keys.join
|
431
|
+
execute :element_send_keys, {id: element}, {value: text.chars, text: text}
|
426
432
|
end
|
427
433
|
|
428
434
|
def clear_element(element)
|
@@ -430,10 +436,19 @@ module Selenium
|
|
430
436
|
end
|
431
437
|
|
432
438
|
def submit_element(element)
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
439
|
+
script = "/* submitForm */ var form = arguments[0];\n" \
|
440
|
+
"while (form.nodeName != \"FORM\" && form.parentNode) {\n " \
|
441
|
+
"form = form.parentNode;\n" \
|
442
|
+
"}\n" \
|
443
|
+
"if (!form) { throw Error('Unable to find containing form element'); }\n" \
|
444
|
+
"if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" \
|
445
|
+
"var e = form.ownerDocument.createEvent('Event');\n" \
|
446
|
+
"e.initEvent('submit', true, true);\n" \
|
447
|
+
"if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n"
|
448
|
+
|
449
|
+
execute_script(script, Bridge.element_class::ELEMENT_KEY => element)
|
450
|
+
rescue Error::JavascriptError
|
451
|
+
raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
|
437
452
|
end
|
438
453
|
|
439
454
|
#
|
@@ -445,7 +460,7 @@ module Selenium
|
|
445
460
|
end
|
446
461
|
|
447
462
|
def element_attribute(element, name)
|
448
|
-
WebDriver.logger.
|
463
|
+
WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
|
449
464
|
execute_atom :getAttribute, element, name
|
450
465
|
end
|
451
466
|
|
@@ -505,7 +520,7 @@ module Selenium
|
|
505
520
|
end
|
506
521
|
|
507
522
|
def element_displayed?(element)
|
508
|
-
WebDriver.logger.
|
523
|
+
WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
|
509
524
|
execute_atom :isDisplayed, element
|
510
525
|
end
|
511
526
|
|
@@ -518,13 +533,13 @@ module Selenium
|
|
518
533
|
#
|
519
534
|
|
520
535
|
def active_element
|
521
|
-
|
536
|
+
Bridge.element_class.new self, element_id_from(execute(:get_active_element))
|
522
537
|
end
|
523
538
|
|
524
|
-
|
539
|
+
alias switch_to_active_element active_element
|
525
540
|
|
526
541
|
def find_element_by(how, what, parent_ref = [])
|
527
|
-
how, what =
|
542
|
+
how, what = @locator_converter.convert(how, what)
|
528
543
|
|
529
544
|
return execute_atom(:findElements, Support::RelativeLocator.new(what).as_json).first if how == 'relative'
|
530
545
|
|
@@ -538,11 +553,11 @@ module Selenium
|
|
538
553
|
execute :find_element, {}, {using: how, value: what.to_s}
|
539
554
|
end
|
540
555
|
|
541
|
-
|
556
|
+
Bridge.element_class.new self, element_id_from(id)
|
542
557
|
end
|
543
558
|
|
544
559
|
def find_elements_by(how, what, parent_ref = [])
|
545
|
-
how, what =
|
560
|
+
how, what = @locator_converter.convert(how, what)
|
546
561
|
|
547
562
|
return execute_atom :findElements, Support::RelativeLocator.new(what).as_json if how == 'relative'
|
548
563
|
|
@@ -556,7 +571,7 @@ module Selenium
|
|
556
571
|
execute :find_elements, {}, {using: how, value: what.to_s}
|
557
572
|
end
|
558
573
|
|
559
|
-
ids.map { |id|
|
574
|
+
ids.map { |id| Bridge.element_class.new self, element_id_from(id) }
|
560
575
|
end
|
561
576
|
|
562
577
|
def shadow_root(element)
|
@@ -564,6 +579,88 @@ module Selenium
|
|
564
579
|
ShadowRoot.new self, shadow_root_id_from(id)
|
565
580
|
end
|
566
581
|
|
582
|
+
#
|
583
|
+
# virtual-authenticator
|
584
|
+
#
|
585
|
+
|
586
|
+
def add_virtual_authenticator(options)
|
587
|
+
authenticator_id = execute :add_virtual_authenticator, {}, options.as_json
|
588
|
+
VirtualAuthenticator.new(self, authenticator_id, options)
|
589
|
+
end
|
590
|
+
|
591
|
+
def remove_virtual_authenticator(id)
|
592
|
+
execute :remove_virtual_authenticator, {authenticatorId: id}
|
593
|
+
end
|
594
|
+
|
595
|
+
def add_credential(credential, id)
|
596
|
+
execute :add_credential, {authenticatorId: id}, credential
|
597
|
+
end
|
598
|
+
|
599
|
+
def credentials(authenticator_id)
|
600
|
+
execute :get_credentials, {authenticatorId: authenticator_id}
|
601
|
+
end
|
602
|
+
|
603
|
+
def remove_credential(credential_id, authenticator_id)
|
604
|
+
execute :remove_credential, {credentialId: credential_id, authenticatorId: authenticator_id}
|
605
|
+
end
|
606
|
+
|
607
|
+
def remove_all_credentials(authenticator_id)
|
608
|
+
execute :remove_all_credentials, {authenticatorId: authenticator_id}
|
609
|
+
end
|
610
|
+
|
611
|
+
def user_verified(verified, authenticator_id)
|
612
|
+
execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
|
613
|
+
end
|
614
|
+
|
615
|
+
#
|
616
|
+
# federated-credential management
|
617
|
+
#
|
618
|
+
|
619
|
+
def cancel_fedcm_dialog
|
620
|
+
execute :cancel_fedcm_dialog
|
621
|
+
end
|
622
|
+
|
623
|
+
def select_fedcm_account(index)
|
624
|
+
execute :select_fedcm_account, {}, {accountIndex: index}
|
625
|
+
end
|
626
|
+
|
627
|
+
def fedcm_dialog_type
|
628
|
+
execute :get_fedcm_dialog_type
|
629
|
+
end
|
630
|
+
|
631
|
+
def fedcm_title
|
632
|
+
execute(:get_fedcm_title).fetch('title')
|
633
|
+
end
|
634
|
+
|
635
|
+
def fedcm_subtitle
|
636
|
+
execute(:get_fedcm_title).fetch('subtitle', nil)
|
637
|
+
end
|
638
|
+
|
639
|
+
def fedcm_account_list
|
640
|
+
execute :get_fedcm_account_list
|
641
|
+
end
|
642
|
+
|
643
|
+
def fedcm_delay(enabled)
|
644
|
+
execute :set_fedcm_delay, {}, {enabled: enabled}
|
645
|
+
end
|
646
|
+
|
647
|
+
def reset_fedcm_cooldown
|
648
|
+
execute :reset_fedcm_cooldown
|
649
|
+
end
|
650
|
+
|
651
|
+
def click_fedcm_dialog_button
|
652
|
+
execute :click_fedcm_dialog_button, {}, {dialogButton: 'ConfirmIdpLoginContinue'}
|
653
|
+
end
|
654
|
+
|
655
|
+
def bidi
|
656
|
+
msg = 'BiDi must be enabled by setting #web_socket_url to true in options class'
|
657
|
+
raise(WebDriver::Error::WebDriverError, msg)
|
658
|
+
end
|
659
|
+
|
660
|
+
def command_list
|
661
|
+
COMMANDS
|
662
|
+
end
|
663
|
+
|
567
664
|
private
|
568
665
|
|
569
666
|
#
|
@@ -584,16 +681,16 @@ module Selenium
|
|
584
681
|
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
585
682
|
end
|
586
683
|
|
587
|
-
WebDriver.logger.
|
684
|
+
WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
|
588
685
|
http.call(verb, path, command_hash)['value']
|
589
686
|
end
|
590
687
|
|
591
688
|
def escaper
|
592
|
-
@escaper ||= defined?(URI::
|
689
|
+
@escaper ||= defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
|
593
690
|
end
|
594
691
|
|
595
692
|
def commands(command)
|
596
|
-
|
693
|
+
command_list[command] || Bridge.extra_commands[command]
|
597
694
|
end
|
598
695
|
|
599
696
|
def unwrap_script_result(arg)
|
@@ -602,7 +699,7 @@ module Selenium
|
|
602
699
|
arg.map { |e| unwrap_script_result(e) }
|
603
700
|
when Hash
|
604
701
|
element_id = element_id_from(arg)
|
605
|
-
return
|
702
|
+
return Bridge.element_class.new(self, element_id) if element_id
|
606
703
|
|
607
704
|
shadow_root_id = shadow_root_id_from(arg)
|
608
705
|
return ShadowRoot.new self, shadow_root_id if shadow_root_id
|
@@ -614,7 +711,7 @@ module Selenium
|
|
614
711
|
end
|
615
712
|
|
616
713
|
def element_id_from(id)
|
617
|
-
id['ELEMENT'] || id[
|
714
|
+
id['ELEMENT'] || id[Bridge.element_class::ELEMENT_KEY]
|
618
715
|
end
|
619
716
|
|
620
717
|
def shadow_root_id_from(id)
|
@@ -625,45 +722,6 @@ module Selenium
|
|
625
722
|
capabilities = {alwaysMatch: capabilities} if !capabilities['alwaysMatch'] && !capabilities['firstMatch']
|
626
723
|
{capabilities: capabilities}
|
627
724
|
end
|
628
|
-
|
629
|
-
def convert_locator(how, what)
|
630
|
-
how = SearchContext::FINDERS[how.to_sym] || how
|
631
|
-
|
632
|
-
case how
|
633
|
-
when 'class name'
|
634
|
-
how = 'css selector'
|
635
|
-
what = ".#{escape_css(what.to_s)}"
|
636
|
-
when 'id'
|
637
|
-
how = 'css selector'
|
638
|
-
what = "##{escape_css(what.to_s)}"
|
639
|
-
when 'name'
|
640
|
-
how = 'css selector'
|
641
|
-
what = "*[name='#{escape_css(what.to_s)}']"
|
642
|
-
when 'tag name'
|
643
|
-
how = 'css selector'
|
644
|
-
end
|
645
|
-
|
646
|
-
if what.is_a?(Hash)
|
647
|
-
what = what.each_with_object({}) do |(h, w), hash|
|
648
|
-
h, w = convert_locator(h.to_s, w)
|
649
|
-
hash[h] = w
|
650
|
-
end
|
651
|
-
end
|
652
|
-
|
653
|
-
[how, what]
|
654
|
-
end
|
655
|
-
|
656
|
-
ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/.freeze
|
657
|
-
UNICODE_CODE_POINT = 30
|
658
|
-
|
659
|
-
# Escapes invalid characters in CSS selector.
|
660
|
-
# @see https://mathiasbynens.be/notes/css-escapes
|
661
|
-
def escape_css(string)
|
662
|
-
string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
|
663
|
-
string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
|
664
|
-
|
665
|
-
string
|
666
|
-
end
|
667
725
|
end # Bridge
|
668
726
|
end # Remote
|
669
727
|
end # WebDriver
|
@@ -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,
|
@@ -50,65 +48,16 @@ module Selenium
|
|
50
48
|
@capabilities[key]
|
51
49
|
end
|
52
50
|
|
53
|
-
define_method "#{key}=" do |value|
|
51
|
+
define_method :"#{key}=" do |value|
|
54
52
|
@capabilities[key] = value
|
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|
|
@@ -149,7 +99,7 @@ module Selenium
|
|
149
99
|
end
|
150
100
|
|
151
101
|
def camel_case(str_or_sym)
|
152
|
-
str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1)
|
102
|
+
str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
|
153
103
|
end
|
154
104
|
|
155
105
|
private
|
@@ -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
|
|