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
@@ -56,7 +56,7 @@ module Selenium
|
|
56
56
|
opts[:httpOnly] = http_only if http_only
|
57
57
|
|
58
58
|
obj = opts.delete(:expires)
|
59
|
-
opts[:expiry] = seconds_from(obj).
|
59
|
+
opts[:expiry] = seconds_from(obj).to_int if obj
|
60
60
|
|
61
61
|
@bridge.add_cookie opts
|
62
62
|
end
|
@@ -65,7 +65,7 @@ module Selenium
|
|
65
65
|
# Get the cookie with the given name
|
66
66
|
#
|
67
67
|
# @param [String] name the name of the cookie
|
68
|
-
# @return [Hash
|
68
|
+
# @return [Hash] the cookie, or throws a NoSuchCookieError if it wasn't found.
|
69
69
|
#
|
70
70
|
|
71
71
|
def cookie_named(name)
|
@@ -104,33 +104,6 @@ module Selenium
|
|
104
104
|
@timeouts ||= Timeouts.new(@bridge)
|
105
105
|
end
|
106
106
|
|
107
|
-
def logs
|
108
|
-
WebDriver.logger.deprecate('Manager#logs', 'Chrome::Driver#logs')
|
109
|
-
@logs ||= Logs.new(@bridge)
|
110
|
-
end
|
111
|
-
|
112
|
-
#
|
113
|
-
# @param type [Symbol] Supports two values: :tab and :window.
|
114
|
-
# @return [String] The value of the window handle
|
115
|
-
#
|
116
|
-
def new_window(type = :tab)
|
117
|
-
WebDriver.logger.deprecate('Manager#new_window', 'TargetLocator#new_window', id: :new_window) do
|
118
|
-
'e.g., `driver.switch_to.new_window(:tab)`'
|
119
|
-
end
|
120
|
-
case type
|
121
|
-
when :tab, :window
|
122
|
-
result = @bridge.new_window(type)
|
123
|
-
unless result.key?('handle')
|
124
|
-
raise UnknownError, "the driver did not return a handle. " \
|
125
|
-
"The returned result: #{result.inspect}"
|
126
|
-
end
|
127
|
-
result['handle']
|
128
|
-
else
|
129
|
-
raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
|
130
|
-
"Try :tab or :window"
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
107
|
def window
|
135
108
|
@window ||= Window.new(@bridge)
|
136
109
|
end
|
@@ -0,0 +1,64 @@
|
|
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
|
+
class Network
|
23
|
+
attr_reader :callbacks
|
24
|
+
|
25
|
+
def initialize(bridge)
|
26
|
+
@network = BiDi::Network.new(bridge.bidi)
|
27
|
+
@callbacks = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_authentication_handler(username, password)
|
31
|
+
intercept = @network.add_intercept(phases: [BiDi::Network::PHASES[:auth_required]])
|
32
|
+
auth_id = @network.on(:auth_required) do |event|
|
33
|
+
request_id = event['requestId']
|
34
|
+
@network.continue_with_auth(request_id, username, password)
|
35
|
+
end
|
36
|
+
@callbacks[auth_id] = intercept
|
37
|
+
|
38
|
+
auth_id
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_handler(id)
|
42
|
+
intercept = @callbacks[id]
|
43
|
+
@network.remove_intercept(intercept['intercept'])
|
44
|
+
@callbacks.delete(id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def clear_handlers
|
48
|
+
@callbacks.each_key { |id| remove_handler(id) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_request_handler
|
52
|
+
intercept = @network.add_intercept(phases: [BiDi::Network::PHASES[:before_request]])
|
53
|
+
request_id = @network.on(:before_request) do |event|
|
54
|
+
request_id = event['requestId']
|
55
|
+
@network.continue_with_request(request_id: request_id)
|
56
|
+
end
|
57
|
+
|
58
|
+
@callbacks[request_id] = intercept
|
59
|
+
|
60
|
+
request_id
|
61
|
+
end
|
62
|
+
end # Network
|
63
|
+
end # WebDriver
|
64
|
+
end # Selenium
|
@@ -24,6 +24,8 @@ module Selenium
|
|
24
24
|
set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
|
25
25
|
web_socket_url].freeze
|
26
26
|
|
27
|
+
GRID_OPTIONS = %i[enable_downloads].freeze
|
28
|
+
|
27
29
|
class << self
|
28
30
|
attr_reader :driver_path
|
29
31
|
|
@@ -38,12 +40,12 @@ module Selenium
|
|
38
40
|
def ie(**opts)
|
39
41
|
IE::Options.new(**opts)
|
40
42
|
end
|
41
|
-
|
43
|
+
alias internet_explorer ie
|
42
44
|
|
43
45
|
def edge(**opts)
|
44
46
|
Edge::Options.new(**opts)
|
45
47
|
end
|
46
|
-
|
48
|
+
alias microsoftedge edge
|
47
49
|
|
48
50
|
def safari(**opts)
|
49
51
|
Safari::Options.new(**opts)
|
@@ -57,7 +59,7 @@ module Selenium
|
|
57
59
|
@options[key]
|
58
60
|
end
|
59
61
|
|
60
|
-
define_method "#{key}=" do |value|
|
62
|
+
define_method :"#{key}=" do |value|
|
61
63
|
@options[key] = value
|
62
64
|
end
|
63
65
|
end
|
@@ -66,17 +68,10 @@ module Selenium
|
|
66
68
|
|
67
69
|
attr_accessor :options
|
68
70
|
|
69
|
-
def initialize(
|
71
|
+
def initialize(**opts)
|
70
72
|
self.class.set_capabilities
|
71
73
|
|
72
|
-
@options =
|
73
|
-
WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
|
74
|
-
"custom values directly in #new constructor",
|
75
|
-
id: :options_options)
|
76
|
-
opts.merge(options)
|
77
|
-
else
|
78
|
-
opts
|
79
|
-
end
|
74
|
+
@options = opts
|
80
75
|
@options[:browser_name] = self.class::BROWSER
|
81
76
|
end
|
82
77
|
|
@@ -92,7 +87,7 @@ module Selenium
|
|
92
87
|
#
|
93
88
|
|
94
89
|
def add_option(name, value = nil)
|
95
|
-
|
90
|
+
name, value = name.first if value.nil? && name.is_a?(Hash)
|
96
91
|
@options[name] = value
|
97
92
|
end
|
98
93
|
|
@@ -102,7 +97,7 @@ module Selenium
|
|
102
97
|
as_json == other.as_json
|
103
98
|
end
|
104
99
|
|
105
|
-
|
100
|
+
alias eql? ==
|
106
101
|
|
107
102
|
#
|
108
103
|
# @api private
|
@@ -111,13 +106,18 @@ module Selenium
|
|
111
106
|
def as_json(*)
|
112
107
|
options = @options.dup
|
113
108
|
|
109
|
+
downloads = options.delete(:enable_downloads)
|
110
|
+
options['se:downloadsEnabled'] = downloads unless downloads.nil?
|
114
111
|
w3c_options = process_w3c_options(options)
|
115
112
|
|
116
|
-
self.class::CAPABILITIES.
|
113
|
+
browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
|
117
114
|
capability_value = options.delete(capability_alias)
|
118
|
-
|
115
|
+
hash[capability_name] = capability_value unless capability_value.nil?
|
119
116
|
end
|
120
|
-
|
117
|
+
|
118
|
+
raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?
|
119
|
+
|
120
|
+
browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
|
121
121
|
|
122
122
|
process_browser_options(browser_options)
|
123
123
|
generate_as_json(w3c_options.merge(browser_options))
|
@@ -130,7 +130,7 @@ module Selenium
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def process_w3c_options(options)
|
133
|
-
w3c_options = options.select { |key,
|
133
|
+
w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
|
134
134
|
w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
|
135
135
|
options.delete_if { |key, _val| w3c?(key) }
|
136
136
|
w3c_options
|
@@ -177,7 +177,7 @@ module Selenium
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def camel_case(str)
|
180
|
-
str.gsub(/_([a-z])/) { Regexp.last_match(1)
|
180
|
+
str.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
|
181
181
|
end
|
182
182
|
end # Options
|
183
183
|
end # WebDriver
|
@@ -62,22 +62,14 @@ module Selenium
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
def bitsize
|
66
|
-
@bitsize ||= if defined?(FFI::Platform::ADDRESS_SIZE)
|
67
|
-
FFI::Platform::ADDRESS_SIZE
|
68
|
-
elsif defined?(FFI)
|
69
|
-
FFI.type_size(:pointer) == 4 ? 32 : 64
|
70
|
-
elsif jruby?
|
71
|
-
Integer(ENV_JAVA['sun.arch.data.model'])
|
72
|
-
else
|
73
|
-
1.size == 4 ? 32 : 64
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
65
|
def jruby?
|
78
66
|
engine == :jruby
|
79
67
|
end
|
80
68
|
|
69
|
+
def truffleruby?
|
70
|
+
engine == :truffleruby
|
71
|
+
end
|
72
|
+
|
81
73
|
def ruby_version
|
82
74
|
RUBY_VERSION
|
83
75
|
end
|
@@ -94,6 +86,10 @@ module Selenium
|
|
94
86
|
os == :linux
|
95
87
|
end
|
96
88
|
|
89
|
+
def unix?
|
90
|
+
os == :unix
|
91
|
+
end
|
92
|
+
|
97
93
|
def wsl?
|
98
94
|
return false unless linux?
|
99
95
|
|
@@ -104,8 +100,7 @@ module Selenium
|
|
104
100
|
end
|
105
101
|
|
106
102
|
def cygwin?
|
107
|
-
RUBY_PLATFORM
|
108
|
-
!Regexp.last_match.nil?
|
103
|
+
RUBY_PLATFORM.include?('cygwin')
|
109
104
|
end
|
110
105
|
|
111
106
|
def null_device
|
@@ -116,7 +111,9 @@ module Selenium
|
|
116
111
|
windows? && !cygwin? ? %("#{str}") : str
|
117
112
|
end
|
118
113
|
|
119
|
-
def cygwin_path(path, **opts)
|
114
|
+
def cygwin_path(path, only_cygwin: false, **opts)
|
115
|
+
return path if only_cygwin && !cygwin?
|
116
|
+
|
120
117
|
flags = []
|
121
118
|
opts.each { |k, v| flags << "--#{k}" if v }
|
122
119
|
|
@@ -155,43 +152,6 @@ module Selenium
|
|
155
152
|
at_exit { yield if Process.pid == pid }
|
156
153
|
end
|
157
154
|
|
158
|
-
def find_binary(*binary_names)
|
159
|
-
paths = ENV['PATH'].split(File::PATH_SEPARATOR)
|
160
|
-
|
161
|
-
if windows?
|
162
|
-
binary_names.map! { |n| "#{n}.exe" }
|
163
|
-
binary_names.dup.each { |n| binary_names << n.gsub('exe', 'bat') }
|
164
|
-
end
|
165
|
-
|
166
|
-
binary_names.each do |binary_name|
|
167
|
-
paths.each do |path|
|
168
|
-
full_path = File.join(path, binary_name)
|
169
|
-
full_path = unix_path(full_path) if windows?
|
170
|
-
exe = Dir.glob(full_path).find { |f| File.executable?(f) }
|
171
|
-
return exe if exe
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
nil
|
176
|
-
end
|
177
|
-
|
178
|
-
def find_in_program_files(*binary_names)
|
179
|
-
paths = [
|
180
|
-
ENV['PROGRAMFILES'] || '\\Program Files',
|
181
|
-
ENV['ProgramFiles(x86)'] || '\\Program Files (x86)',
|
182
|
-
ENV['ProgramW6432'] || '\\Program Files'
|
183
|
-
]
|
184
|
-
|
185
|
-
paths.each do |root|
|
186
|
-
binary_names.each do |name|
|
187
|
-
exe = File.join(root, name)
|
188
|
-
return exe if File.executable?(exe)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
nil
|
193
|
-
end
|
194
|
-
|
195
155
|
def localhost
|
196
156
|
info = Socket.getaddrinfo 'localhost', 80, Socket::AF_INET, Socket::SOCK_STREAM
|
197
157
|
|
@@ -34,7 +34,7 @@ module Selenium
|
|
34
34
|
Platform.interfaces.each do |host|
|
35
35
|
TCPServer.new(host, port).close
|
36
36
|
rescue *IGNORED_ERRORS => e
|
37
|
-
WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
|
37
|
+
WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})", id: :driver_service)
|
38
38
|
# ignored - some machines appear unable to bind to some of their interfaces
|
39
39
|
end
|
40
40
|
|
@@ -49,7 +49,7 @@ module Selenium
|
|
49
49
|
proxy = new
|
50
50
|
|
51
51
|
ALLOWED.each do |k, v|
|
52
|
-
proxy.send("#{k}=", data[v]) if data.key?(v)
|
52
|
+
proxy.send(:"#{k}=", data[v]) if data.key?(v)
|
53
53
|
end
|
54
54
|
|
55
55
|
proxy
|
@@ -60,7 +60,7 @@ module Selenium
|
|
60
60
|
|
61
61
|
opts.each do |k, v|
|
62
62
|
if ALLOWED.key?(k)
|
63
|
-
send("#{k}=", v)
|
63
|
+
send(:"#{k}=", v)
|
64
64
|
else
|
65
65
|
not_allowed << k
|
66
66
|
end
|
@@ -74,7 +74,7 @@ module Selenium
|
|
74
74
|
def ==(other)
|
75
75
|
other.is_a?(self.class) && as_json == other.as_json
|
76
76
|
end
|
77
|
-
|
77
|
+
alias eql? ==
|
78
78
|
|
79
79
|
def ftp=(value)
|
80
80
|
self.type = :manual
|
@@ -152,7 +152,7 @@ module Selenium
|
|
152
152
|
'socksUsername' => socks_username,
|
153
153
|
'socksPassword' => socks_password,
|
154
154
|
'socksVersion' => socks_version
|
155
|
-
}.
|
155
|
+
}.compact
|
156
156
|
|
157
157
|
json_result if json_result.length > 1
|
158
158
|
end
|
@@ -0,0 +1,45 @@
|
|
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
|
+
class Script
|
23
|
+
def initialize(bridge)
|
24
|
+
@log_handler = BiDi::LogHandler.new(bridge.bidi)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [int] id of the handler
|
28
|
+
def add_console_message_handler(&)
|
29
|
+
@log_handler.add_message_handler('console', &)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [int] id of the handler
|
33
|
+
def add_javascript_error_handler(&)
|
34
|
+
@log_handler.add_message_handler('javascript', &)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [int] id of the handler previously added
|
38
|
+
def remove_console_message_handler(id)
|
39
|
+
@log_handler.remove_message_handler(id)
|
40
|
+
end
|
41
|
+
|
42
|
+
alias remove_javascript_error_handler remove_console_message_handler
|
43
|
+
end # Script
|
44
|
+
end # WebDriver
|
45
|
+
end # Selenium
|
@@ -35,6 +35,14 @@ module Selenium
|
|
35
35
|
xpath: 'xpath'
|
36
36
|
}.freeze
|
37
37
|
|
38
|
+
class << self
|
39
|
+
attr_accessor :extra_finders
|
40
|
+
|
41
|
+
def finders
|
42
|
+
FINDERS.merge(extra_finders || {})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
38
46
|
#
|
39
47
|
# Find the first element matching the given arguments
|
40
48
|
#
|
@@ -57,13 +65,10 @@ module Selenium
|
|
57
65
|
def find_element(*args)
|
58
66
|
how, what = extract_args(args)
|
59
67
|
|
60
|
-
by =
|
68
|
+
by = SearchContext.finders[how.to_sym]
|
61
69
|
raise ArgumentError, "cannot find element by #{how.inspect}" unless by
|
62
70
|
|
63
71
|
bridge.find_element_by by, what, ref
|
64
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
65
|
-
# Implicit Wait times out in Edge
|
66
|
-
raise Selenium::WebDriver::Error::NoSuchElementError
|
67
72
|
end
|
68
73
|
|
69
74
|
#
|
@@ -75,13 +80,10 @@ module Selenium
|
|
75
80
|
def find_elements(*args)
|
76
81
|
how, what = extract_args(args)
|
77
82
|
|
78
|
-
by =
|
83
|
+
by = SearchContext.finders[how.to_sym]
|
79
84
|
raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
|
80
85
|
|
81
86
|
bridge.find_elements_by by, what, ref
|
82
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
83
|
-
# Implicit Wait times out in Edge
|
84
|
-
[]
|
85
87
|
end
|
86
88
|
|
87
89
|
private
|
@@ -0,0 +1,104 @@
|
|
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
|
+
require 'open3'
|
21
|
+
|
22
|
+
module Selenium
|
23
|
+
module WebDriver
|
24
|
+
#
|
25
|
+
# Wrapper for getting information from the Selenium Manager binaries.
|
26
|
+
# This implementation is still in beta, and may change.
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
class SeleniumManager
|
30
|
+
class << self
|
31
|
+
attr_writer :bin_path
|
32
|
+
|
33
|
+
def bin_path
|
34
|
+
@bin_path ||= '../../../../../bin'
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [Array] arguments what gets sent to to Selenium Manager binary.
|
38
|
+
# @return [Hash] paths to the requested assets.
|
39
|
+
def binary_paths(*arguments)
|
40
|
+
arguments += %w[--language-binding ruby]
|
41
|
+
arguments += %w[--output json]
|
42
|
+
arguments << '--debug' if WebDriver.logger.debug?
|
43
|
+
|
44
|
+
run(binary, *arguments)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# @return [String] the path to the correct selenium manager
|
50
|
+
def binary
|
51
|
+
@binary ||= begin
|
52
|
+
if (location = ENV.fetch('SE_MANAGER_PATH', nil))
|
53
|
+
WebDriver.logger.debug("Selenium Manager set by ENV['SE_MANAGER_PATH']: #{location}")
|
54
|
+
end
|
55
|
+
location ||= platform_location
|
56
|
+
|
57
|
+
Platform.assert_executable(location)
|
58
|
+
WebDriver.logger.debug("Selenium Manager binary found at #{location}", id: :selenium_manager)
|
59
|
+
location
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def run(*command)
|
64
|
+
WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
|
65
|
+
|
66
|
+
begin
|
67
|
+
stdout, stderr, status = Open3.capture3(*command)
|
68
|
+
rescue StandardError => e
|
69
|
+
raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
json_output = stdout.empty? ? {'logs' => [], 'result' => {}} : JSON.parse(stdout)
|
73
|
+
json_output['logs'].each do |log|
|
74
|
+
level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
|
75
|
+
WebDriver.logger.send(level, log['message'], id: :selenium_manager)
|
76
|
+
end
|
77
|
+
|
78
|
+
result = json_output['result']
|
79
|
+
return result unless status.exitstatus.positive? || result.nil?
|
80
|
+
|
81
|
+
raise Error::WebDriverError,
|
82
|
+
"Unsuccessful command executed: #{command} - Code #{status.exitstatus}\n#{result}\n#{stderr}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def platform_location
|
86
|
+
directory = File.expand_path(bin_path, __FILE__)
|
87
|
+
if Platform.windows?
|
88
|
+
"#{directory}/windows/selenium-manager.exe"
|
89
|
+
elsif Platform.mac?
|
90
|
+
"#{directory}/macos/selenium-manager"
|
91
|
+
elsif Platform.linux?
|
92
|
+
"#{directory}/linux/selenium-manager"
|
93
|
+
elsif Platform.unix?
|
94
|
+
WebDriver.logger.warn('Selenium Manager binary may not be compatible with Unix',
|
95
|
+
id: %i[selenium_manager unix_binary])
|
96
|
+
"#{directory}/linux/selenium-manager"
|
97
|
+
else
|
98
|
+
raise Error::WebDriverError, "unsupported platform: #{Platform.os}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end # SeleniumManager
|
103
|
+
end # WebDriver
|
104
|
+
end # Selenium
|
@@ -39,12 +39,13 @@ module Selenium
|
|
39
39
|
def ie(**opts)
|
40
40
|
IE::Service.new(**opts)
|
41
41
|
end
|
42
|
-
|
42
|
+
alias internet_explorer ie
|
43
43
|
|
44
44
|
def edge(**opts)
|
45
45
|
Edge::Service.new(**opts)
|
46
46
|
end
|
47
|
-
|
47
|
+
alias microsoftedge edge
|
48
|
+
alias msedge edge
|
48
49
|
|
49
50
|
def safari(**opts)
|
50
51
|
Safari::Service.new(**opts)
|
@@ -56,8 +57,8 @@ module Selenium
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
|
-
attr_accessor :host
|
60
|
-
|
60
|
+
attr_accessor :host, :executable_path, :port, :log, :args
|
61
|
+
alias extra_args args
|
61
62
|
|
62
63
|
#
|
63
64
|
# End users should use a class method for the desired driver, rather than using this directly.
|
@@ -65,46 +66,43 @@ module Selenium
|
|
65
66
|
# @api private
|
66
67
|
#
|
67
68
|
|
68
|
-
def initialize(path: nil, port: nil, args: nil)
|
69
|
-
path ||= self.class.driver_path
|
69
|
+
def initialize(path: nil, port: nil, log: nil, args: nil)
|
70
70
|
port ||= self.class::DEFAULT_PORT
|
71
71
|
args ||= []
|
72
|
+
path ||= env_path
|
72
73
|
|
73
|
-
@executable_path =
|
74
|
+
@executable_path = path
|
74
75
|
@host = Platform.localhost
|
75
76
|
@port = Integer(port)
|
76
|
-
|
77
|
-
|
77
|
+
@log = case log
|
78
|
+
when :stdout
|
79
|
+
$stdout
|
80
|
+
when :stderr
|
81
|
+
$stderr
|
82
|
+
else
|
83
|
+
log
|
84
|
+
end
|
85
|
+
@args = args
|
78
86
|
|
79
87
|
raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
|
80
88
|
end
|
81
89
|
|
82
90
|
def launch
|
83
|
-
|
84
|
-
|
85
|
-
sm
|
91
|
+
@executable_path ||= env_path || find_driver_path
|
92
|
+
ServiceManager.new(self).tap(&:start)
|
86
93
|
end
|
87
94
|
|
88
95
|
def shutdown_supported
|
89
96
|
self.class::SHUTDOWN_SUPPORTED
|
90
97
|
end
|
91
98
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
driver_opts.key?(:args) ? driver_opts.delete(:args) : []
|
99
|
+
def find_driver_path
|
100
|
+
default_options = WebDriver.const_get("#{self.class.name&.split('::')&.[](2)}::Options").new
|
101
|
+
DriverFinder.new(default_options, self).driver_path
|
96
102
|
end
|
97
103
|
|
98
|
-
|
99
|
-
|
100
|
-
def binary_path(path = nil)
|
101
|
-
path = path.call if path.is_a?(Proc)
|
102
|
-
path ||= Platform.find_binary(self.class::EXECUTABLE)
|
103
|
-
|
104
|
-
raise Error::WebDriverError, self.class::MISSING_TEXT unless path
|
105
|
-
|
106
|
-
Platform.assert_executable path
|
107
|
-
path
|
104
|
+
def env_path
|
105
|
+
ENV.fetch(self.class::DRIVER_PATH_ENV_KEY, nil)
|
108
106
|
end
|
109
107
|
end # Service
|
110
108
|
end # WebDriver
|