selenium-webdriver 3.142.7 → 4.10.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 +5 -5
- data/CHANGES +611 -5
- data/Gemfile +5 -1
- data/LICENSE +1 -1
- data/NOTICE +2 -0
- data/README.md +4 -5
- 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 +94 -79
- data/lib/selenium/webdriver/atoms/findElements.js +121 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +100 -7
- data/lib/selenium/webdriver/atoms/isDisplayed.js +76 -78
- data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
- data/lib/selenium/webdriver/atoms.rb +2 -3
- data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
- data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
- data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
- data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
- data/lib/selenium/webdriver/bidi/session.rb +51 -0
- data/lib/selenium/webdriver/{common/keyboard.rb → bidi.rb} +21 -35
- data/lib/selenium/webdriver/chrome/driver.rb +9 -86
- data/lib/selenium/webdriver/chrome/features.rb +44 -0
- data/lib/selenium/webdriver/chrome/options.rb +9 -158
- data/lib/selenium/webdriver/chrome/profile.rb +3 -80
- data/lib/selenium/webdriver/chrome/service.rb +6 -33
- data/lib/selenium/webdriver/chrome.rb +5 -18
- data/lib/selenium/webdriver/chromium/driver.rb +61 -0
- data/lib/selenium/webdriver/{chrome/bridge.rb → chromium/features.rb} +51 -16
- data/lib/selenium/webdriver/chromium/options.rb +261 -0
- data/lib/selenium/webdriver/chromium/profile.rb +113 -0
- data/lib/selenium/webdriver/chromium/service.rb +42 -0
- data/lib/selenium/webdriver/chromium.rb +32 -0
- data/lib/selenium/webdriver/common/action_builder.rb +128 -238
- data/lib/selenium/webdriver/common/child_process.rb +124 -0
- data/lib/selenium/webdriver/common/driver.rb +94 -43
- data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +42 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +49 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +87 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_touch_screen.rb → has_bidi.rb} +9 -9
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +86 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +36 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +42 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +41 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +36 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -9
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +143 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_logs.rb} +4 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +16 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +69 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -13
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +75 -0
- data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
- data/lib/selenium/webdriver/common/driver_finder.rb +47 -0
- data/lib/selenium/webdriver/common/element.rb +89 -29
- data/lib/selenium/webdriver/common/error.rb +53 -194
- 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 -22
- data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +10 -6
- 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 +71 -82
- data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
- data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
- data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
- data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
- data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
- data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
- data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
- data/lib/selenium/webdriver/common/{w3c_manager.rb → interactions/wheel_input.rb} +14 -17
- data/lib/selenium/webdriver/common/keys.rb +1 -0
- data/lib/selenium/webdriver/common/local_driver.rb +55 -0
- data/lib/selenium/webdriver/common/log_entry.rb +2 -2
- data/lib/selenium/webdriver/common/logger.rb +119 -19
- data/lib/selenium/webdriver/common/manager.rb +11 -38
- data/lib/selenium/webdriver/common/options.rb +169 -23
- data/lib/selenium/webdriver/common/platform.rb +14 -6
- data/lib/selenium/webdriver/common/port_prober.rb +4 -6
- data/lib/selenium/webdriver/common/profile_helper.rb +11 -9
- data/lib/selenium/webdriver/common/proxy.rb +8 -5
- data/lib/selenium/webdriver/common/search_context.rb +7 -9
- data/lib/selenium/webdriver/common/selenium_manager.rb +125 -0
- data/lib/selenium/webdriver/common/service.rb +26 -137
- data/lib/selenium/webdriver/common/service_manager.rb +144 -0
- data/lib/selenium/webdriver/common/shadow_root.rb +86 -0
- data/lib/selenium/webdriver/common/socket_lock.rb +4 -4
- data/lib/selenium/webdriver/common/socket_poller.rb +4 -4
- data/lib/selenium/webdriver/common/takes_screenshot.rb +65 -0
- data/lib/selenium/webdriver/common/target_locator.rb +31 -4
- data/lib/selenium/webdriver/common/timeouts.rb +31 -4
- 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 +164 -0
- data/lib/selenium/webdriver/common/window.rb +6 -10
- data/lib/selenium/webdriver/common/zipper.rb +4 -10
- data/lib/selenium/webdriver/common.rb +42 -18
- data/lib/selenium/webdriver/devtools/console_event.rb +36 -0
- data/lib/selenium/webdriver/devtools/exception_event.rb +34 -0
- data/lib/selenium/webdriver/devtools/mutation_event.rb +35 -0
- data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +57 -0
- data/lib/selenium/webdriver/devtools/request.rb +65 -0
- data/lib/selenium/webdriver/devtools/response.rb +64 -0
- data/lib/selenium/webdriver/devtools.rb +96 -0
- data/lib/selenium/webdriver/edge/driver.rb +11 -27
- data/lib/selenium/webdriver/edge/features.rb +44 -0
- data/lib/selenium/webdriver/edge/options.rb +18 -43
- data/lib/selenium/webdriver/edge/profile.rb +33 -0
- data/lib/selenium/webdriver/edge/service.rb +7 -27
- data/lib/selenium/webdriver/edge.rb +11 -14
- data/lib/selenium/webdriver/firefox/driver.rb +38 -19
- data/lib/selenium/webdriver/firefox/extension.rb +8 -0
- data/lib/selenium/webdriver/firefox/features.rb +66 -0
- data/lib/selenium/webdriver/firefox/options.rb +77 -50
- data/lib/selenium/webdriver/firefox/profile.rb +17 -71
- data/lib/selenium/webdriver/firefox/service.rb +3 -13
- data/lib/selenium/webdriver/firefox/util.rb +1 -1
- data/lib/selenium/webdriver/firefox.rb +17 -28
- data/lib/selenium/webdriver/ie/driver.rb +5 -45
- data/lib/selenium/webdriver/ie/options.rb +15 -46
- data/lib/selenium/webdriver/ie/service.rb +11 -19
- data/lib/selenium/webdriver/ie.rb +3 -16
- data/lib/selenium/webdriver/remote/bridge/commands.rb +170 -0
- data/lib/selenium/webdriver/remote/bridge.rb +592 -87
- data/lib/selenium/webdriver/remote/capabilities.rb +182 -124
- data/lib/selenium/webdriver/remote/driver.rb +30 -15
- data/lib/selenium/webdriver/remote/http/common.rb +3 -8
- data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
- data/lib/selenium/webdriver/remote/http/default.rb +23 -31
- data/lib/selenium/webdriver/remote/response.rb +17 -49
- data/lib/selenium/webdriver/remote.rb +14 -12
- data/lib/selenium/webdriver/safari/driver.rb +7 -29
- data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -5
- data/lib/selenium/webdriver/safari/options.rb +12 -27
- data/lib/selenium/webdriver/safari/service.rb +13 -11
- data/lib/selenium/webdriver/safari.rb +14 -20
- data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
- data/lib/selenium/webdriver/support/color.rb +24 -24
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +87 -0
- data/lib/selenium/webdriver/{firefox/marionette/bridge.rb → support/guards/guard_condition.rb} +21 -20
- data/lib/selenium/webdriver/support/guards.rb +95 -0
- data/lib/selenium/webdriver/support/relative_locator.rb +50 -0
- data/lib/selenium/webdriver/support/select.rb +6 -4
- data/lib/selenium/webdriver/support.rb +1 -0
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +18 -17
- data/selenium-webdriver.gemspec +36 -18
- metadata +159 -89
- data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
- data/lib/selenium/webdriver/common/mouse.rb +0 -89
- data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -78
- data/lib/selenium/webdriver/common/touch_screen.rb +0 -123
- data/lib/selenium/webdriver/common/w3c_action_builder.rb +0 -212
- data/lib/selenium/webdriver/edge/bridge.rb +0 -76
- data/lib/selenium/webdriver/firefox/binary.rb +0 -187
- data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/launcher.rb +0 -111
- data/lib/selenium/webdriver/firefox/legacy/driver.rb +0 -83
- data/lib/selenium/webdriver/firefox/marionette/driver.rb +0 -90
- data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/remote/http/persistent.rb +0 -60
- data/lib/selenium/webdriver/remote/oss/bridge.rb +0 -594
- data/lib/selenium/webdriver/remote/oss/commands.rb +0 -223
- data/lib/selenium/webdriver/remote/w3c/bridge.rb +0 -605
- data/lib/selenium/webdriver/remote/w3c/capabilities.rb +0 -310
- data/lib/selenium/webdriver/remote/w3c/commands.rb +0 -157
@@ -38,15 +38,31 @@ module Selenium
|
|
38
38
|
|
39
39
|
def_delegators :@logger,
|
40
40
|
:close,
|
41
|
-
:debug
|
42
|
-
:info
|
43
|
-
:warn
|
44
|
-
:error
|
41
|
+
:debug?,
|
42
|
+
:info?,
|
43
|
+
:warn?,
|
44
|
+
:error?,
|
45
45
|
:fatal, :fatal?,
|
46
|
-
:level
|
46
|
+
:level
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
#
|
49
|
+
# @param [String] progname Allow child projects to use Selenium's Logger pattern
|
50
|
+
#
|
51
|
+
def initialize(progname = 'Selenium', default_level: nil, ignored: nil, allowed: nil)
|
52
|
+
default_level ||= $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
|
53
|
+
|
54
|
+
@logger = create_logger(progname, level: default_level)
|
55
|
+
@ignored = Array(ignored)
|
56
|
+
@allowed = Array(allowed)
|
57
|
+
@first_warning = false
|
58
|
+
end
|
59
|
+
|
60
|
+
def level=(level)
|
61
|
+
if level == :info && @logger.level == :info
|
62
|
+
info(':info is now the default log level, to see additional logging, set log level to :debug')
|
63
|
+
end
|
64
|
+
|
65
|
+
@logger.level = level
|
50
66
|
end
|
51
67
|
|
52
68
|
#
|
@@ -73,29 +89,101 @@ module Selenium
|
|
73
89
|
@logger.instance_variable_get(:@logdev).dev
|
74
90
|
end
|
75
91
|
|
92
|
+
#
|
93
|
+
# Will not log the provided ID.
|
94
|
+
#
|
95
|
+
# @param [Array, Symbol] ids
|
96
|
+
#
|
97
|
+
def ignore(*ids)
|
98
|
+
@ignored += Array(ids).flatten
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Will only log the provided ID.
|
103
|
+
#
|
104
|
+
# @param [Array, Symbol] ids
|
105
|
+
#
|
106
|
+
def allow(ids)
|
107
|
+
@allowed += Array(ids).flatten
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Used to supply information of interest for debugging a problem
|
112
|
+
# Overrides default #debug to skip ignored messages by provided id
|
113
|
+
#
|
114
|
+
# @param [String] message
|
115
|
+
# @param [Symbol, Array<Sybmol>] id
|
116
|
+
# @yield see #deprecate
|
117
|
+
#
|
118
|
+
def debug(message, id: [], &block)
|
119
|
+
discard_or_log(:debug, message, id, &block)
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Used to supply information of general interest
|
124
|
+
#
|
125
|
+
# @param [String] message
|
126
|
+
# @param [Symbol, Array<Sybmol>] id
|
127
|
+
# @yield see #deprecate
|
128
|
+
#
|
129
|
+
def info(message, id: [], &block)
|
130
|
+
discard_or_log(:info, message, id, &block)
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Used to supply information that suggests an error occurred
|
135
|
+
#
|
136
|
+
# @param [String] message
|
137
|
+
# @param [Symbol, Array<Sybmol>] id
|
138
|
+
# @yield see #deprecate
|
139
|
+
#
|
140
|
+
def error(message, id: [], &block)
|
141
|
+
discard_or_log(:error, message, id, &block)
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# Used to supply information that suggests action be taken by user
|
146
|
+
#
|
147
|
+
# @param [String] message
|
148
|
+
# @param [Symbol, Array<Sybmol>] id
|
149
|
+
# @yield see #deprecate
|
150
|
+
#
|
151
|
+
def warn(message, id: [], &block)
|
152
|
+
discard_or_log(:warn, message, id, &block)
|
153
|
+
end
|
154
|
+
|
76
155
|
#
|
77
156
|
# Marks code as deprecated with/without replacement.
|
78
157
|
#
|
79
158
|
# @param [String] old
|
80
159
|
# @param [String, nil] new
|
160
|
+
# @param [Symbol, Array<Symbol>] id
|
161
|
+
# @param [String] reference
|
162
|
+
# @yield appends additional message to end of provided template
|
81
163
|
#
|
82
|
-
def deprecate(old, new = nil)
|
164
|
+
def deprecate(old, new = nil, id: [], reference: '', &block)
|
165
|
+
id = Array(id)
|
166
|
+
return if @ignored.include?(:deprecations)
|
167
|
+
|
168
|
+
id << :deprecations if @allowed.include?(:deprecations)
|
169
|
+
|
83
170
|
message = +"[DEPRECATION] #{old} is deprecated"
|
84
171
|
message << if new
|
85
172
|
". Use #{new} instead."
|
86
173
|
else
|
87
|
-
' and will be removed in
|
174
|
+
' and will be removed in a future release.'
|
88
175
|
end
|
176
|
+
message << " See explanation for this deprecation: #{reference}." unless reference.empty?
|
89
177
|
|
90
|
-
warn message
|
178
|
+
discard_or_log(:warn, message, id, &block)
|
91
179
|
end
|
92
180
|
|
93
181
|
private
|
94
182
|
|
95
|
-
def create_logger(
|
96
|
-
logger = ::Logger.new(
|
97
|
-
logger.progname =
|
98
|
-
logger.level =
|
183
|
+
def create_logger(name, level:)
|
184
|
+
logger = ::Logger.new($stdout)
|
185
|
+
logger.progname = name
|
186
|
+
logger.level = level
|
99
187
|
logger.formatter = proc do |severity, time, progname, msg|
|
100
188
|
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
101
189
|
end
|
@@ -103,12 +191,24 @@ module Selenium
|
|
103
191
|
logger
|
104
192
|
end
|
105
193
|
|
106
|
-
def
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
194
|
+
def discard_or_log(level, message, id)
|
195
|
+
id = Array(id)
|
196
|
+
return if (@ignored & id).any?
|
197
|
+
return if @allowed.any? && (@allowed & id).none?
|
198
|
+
|
199
|
+
return if ::Logger::Severity.const_get(level.upcase) < @logger.level
|
200
|
+
|
201
|
+
unless @first_warning
|
202
|
+
@first_warning = true
|
203
|
+
info("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
|
204
|
+
"https://selenium.dev/documentation/webdriver/troubleshooting/logging\n"
|
205
|
+
end
|
111
206
|
end
|
207
|
+
|
208
|
+
msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
|
209
|
+
msg += " #{yield}" if block_given?
|
210
|
+
|
211
|
+
@logger.send(level) { msg }
|
112
212
|
end
|
113
213
|
end # Logger
|
114
214
|
end # WebDriver
|
@@ -36,6 +36,7 @@ module Selenium
|
|
36
36
|
# @option opts [String] :value A value
|
37
37
|
# @option opts [String] :path ('/') A path
|
38
38
|
# @option opts [String] :secure (false) A boolean
|
39
|
+
# @option opts [String] :same_site (Strict or Lax) currently supported only in chrome 80+ versions
|
39
40
|
# @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
|
40
41
|
#
|
41
42
|
# @raise [ArgumentError] if :name or :value is not specified
|
@@ -45,9 +46,15 @@ module Selenium
|
|
45
46
|
raise ArgumentError, 'name is required' unless opts[:name]
|
46
47
|
raise ArgumentError, 'value is required' unless opts[:value]
|
47
48
|
|
48
|
-
|
49
|
+
# NOTE: This is required because of https://bugs.chromium.org/p/chromedriver/issues/detail?id=3732
|
49
50
|
opts[:secure] ||= false
|
50
51
|
|
52
|
+
same_site = opts.delete(:same_site)
|
53
|
+
opts[:sameSite] = same_site if same_site
|
54
|
+
|
55
|
+
http_only = opts.delete(:http_only)
|
56
|
+
opts[:httpOnly] = http_only if http_only
|
57
|
+
|
51
58
|
obj = opts.delete(:expires)
|
52
59
|
opts[:expiry] = seconds_from(obj).to_i if obj
|
53
60
|
|
@@ -62,7 +69,7 @@ module Selenium
|
|
62
69
|
#
|
63
70
|
|
64
71
|
def cookie_named(name)
|
65
|
-
|
72
|
+
convert_cookie(@bridge.cookie(name))
|
66
73
|
end
|
67
74
|
|
68
75
|
#
|
@@ -97,42 +104,6 @@ module Selenium
|
|
97
104
|
@timeouts ||= Timeouts.new(@bridge)
|
98
105
|
end
|
99
106
|
|
100
|
-
#
|
101
|
-
# @api beta This API may be changed or removed in a future release.
|
102
|
-
#
|
103
|
-
|
104
|
-
def logs
|
105
|
-
@logs ||= Logs.new(@bridge)
|
106
|
-
end
|
107
|
-
|
108
|
-
#
|
109
|
-
# Create a new top-level browsing context
|
110
|
-
# https://w3c.github.io/webdriver/#new-window
|
111
|
-
# @param type [Symbol] Supports two values: :tab and :window.
|
112
|
-
# Use :tab if you'd like the new window to share an OS-level window
|
113
|
-
# with the current browsing context.
|
114
|
-
# Use :window otherwise
|
115
|
-
# @return [String] The value of the window handle
|
116
|
-
#
|
117
|
-
def new_window(type = :tab)
|
118
|
-
case type
|
119
|
-
when :tab, :window
|
120
|
-
result = @bridge.new_window(type)
|
121
|
-
unless result.key?('handle')
|
122
|
-
raise UnknownError, "the driver did not return a handle. " \
|
123
|
-
"The returned result: #{result.inspect}"
|
124
|
-
end
|
125
|
-
result['handle']
|
126
|
-
else
|
127
|
-
raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
|
128
|
-
"Try :tab or :window"
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
#
|
133
|
-
# @api beta This API may be changed or removed in a future release.
|
134
|
-
#
|
135
|
-
|
136
107
|
def window
|
137
108
|
@window ||= Window.new(@bridge)
|
138
109
|
end
|
@@ -169,6 +140,8 @@ module Selenium
|
|
169
140
|
path: cookie['path'],
|
170
141
|
domain: cookie['domain'] && strip_port(cookie['domain']),
|
171
142
|
expires: cookie['expiry'] && datetime_at(cookie['expiry']),
|
143
|
+
same_site: cookie['sameSite'],
|
144
|
+
http_only: cookie['httpOnly'],
|
172
145
|
secure: cookie['secure']
|
173
146
|
}
|
174
147
|
end
|
@@ -19,35 +19,181 @@
|
|
19
19
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
22
|
+
class Options
|
23
|
+
W3C_OPTIONS = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy
|
24
|
+
set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
|
25
|
+
web_socket_url].freeze
|
26
|
+
|
27
|
+
class << self
|
28
|
+
attr_reader :driver_path
|
29
|
+
|
30
|
+
def chrome(**opts)
|
31
|
+
Chrome::Options.new(**opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
def firefox(**opts)
|
35
|
+
Firefox::Options.new(**opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
def ie(**opts)
|
39
|
+
IE::Options.new(**opts)
|
40
|
+
end
|
41
|
+
alias internet_explorer ie
|
42
|
+
|
43
|
+
def edge(**opts)
|
44
|
+
Edge::Options.new(**opts)
|
45
|
+
end
|
46
|
+
alias microsoftedge edge
|
47
|
+
|
48
|
+
def safari(**opts)
|
49
|
+
Safari::Options.new(**opts)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_capabilities
|
53
|
+
(W3C_OPTIONS + self::CAPABILITIES.keys).each do |key|
|
54
|
+
next if method_defined? key
|
55
|
+
|
56
|
+
define_method key do
|
57
|
+
@options[key]
|
58
|
+
end
|
59
|
+
|
60
|
+
define_method "#{key}=" do |value|
|
61
|
+
@options[key] = value
|
62
|
+
end
|
37
63
|
end
|
38
64
|
end
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_accessor :options
|
68
|
+
|
69
|
+
def initialize(**opts)
|
70
|
+
self.class.set_capabilities
|
71
|
+
|
72
|
+
@options = opts
|
73
|
+
@options[:browser_name] = self.class::BROWSER
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Add a new option not yet handled by bindings.
|
78
|
+
#
|
79
|
+
# @example Leave Chrome open when chromedriver is killed
|
80
|
+
# options = Selenium::WebDriver::Chrome::Options.new
|
81
|
+
# options.add_option(:detach, true)
|
82
|
+
#
|
83
|
+
# @param [String, Symbol] name Name of the option
|
84
|
+
# @param [Boolean, String, Integer] value Value of the option
|
85
|
+
#
|
86
|
+
|
87
|
+
def add_option(name, value = nil)
|
88
|
+
name, value = name.first if value.nil? && name.is_a?(Hash)
|
89
|
+
|
90
|
+
unless name.to_s.include?(':')
|
91
|
+
WebDriver.logger.deprecate('Options#add_option for w3c or browser specific capabilities',
|
92
|
+
'applicable attribute accessors or pass into constructor',
|
93
|
+
id: :add_option)
|
94
|
+
end
|
95
|
+
@options[name] = value
|
96
|
+
end
|
39
97
|
|
40
|
-
|
41
|
-
|
42
|
-
return key if key.is_a?(String)
|
98
|
+
def ==(other)
|
99
|
+
return false unless other.is_a? self.class
|
43
100
|
|
44
|
-
|
101
|
+
as_json == other.as_json
|
102
|
+
end
|
103
|
+
|
104
|
+
alias eql? ==
|
105
|
+
|
106
|
+
#
|
107
|
+
# @api private
|
108
|
+
#
|
109
|
+
|
110
|
+
def as_json(*)
|
111
|
+
options = @options.dup
|
112
|
+
|
113
|
+
w3c_options = process_w3c_options(options)
|
114
|
+
|
115
|
+
browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
|
116
|
+
from_name = options.delete(capability_name)
|
117
|
+
from_alias = options.delete(capability_alias)
|
118
|
+
capability_value = if !from_name.nil? && capability_alias != capability_name
|
119
|
+
WebDriver.logger.deprecate("#{capability_name} as option",
|
120
|
+
capability_alias.to_s, id: :option_symbols)
|
121
|
+
from_name
|
122
|
+
elsif !from_alias.nil?
|
123
|
+
from_alias
|
124
|
+
end
|
125
|
+
|
126
|
+
hash[capability_name] = capability_value unless capability_value.nil?
|
45
127
|
end
|
46
128
|
|
47
|
-
|
48
|
-
|
129
|
+
unless options.empty?
|
130
|
+
msg = 'These options are not w3c compliant and will result in failures in a future release'
|
131
|
+
WebDriver.logger.warn("#{msg}: #{options}", id: :w3c_options)
|
132
|
+
browser_options.merge!(options)
|
49
133
|
end
|
50
|
-
|
51
|
-
|
134
|
+
|
135
|
+
browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
|
136
|
+
|
137
|
+
process_browser_options(browser_options)
|
138
|
+
generate_as_json(w3c_options.merge(browser_options))
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def w3c?(key)
|
144
|
+
W3C_OPTIONS.include?(key) || key.to_s.include?(':')
|
145
|
+
end
|
146
|
+
|
147
|
+
def process_w3c_options(options)
|
148
|
+
w3c_options = options.select { |key, _val| w3c?(key) }
|
149
|
+
w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
|
150
|
+
options.delete_if { |key, _val| w3c?(key) }
|
151
|
+
w3c_options
|
152
|
+
end
|
153
|
+
|
154
|
+
def process_browser_options(_browser_options)
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def camelize?(_key)
|
159
|
+
true
|
160
|
+
end
|
161
|
+
|
162
|
+
def generate_as_json(value, camelize_keys: true)
|
163
|
+
if value.is_a?(Hash)
|
164
|
+
process_json_hash(value, camelize_keys)
|
165
|
+
elsif value.respond_to?(:as_json)
|
166
|
+
value.as_json
|
167
|
+
elsif value.is_a?(Array)
|
168
|
+
value.map { |val| generate_as_json(val, camelize_keys: camelize_keys) }
|
169
|
+
elsif value.is_a?(Symbol)
|
170
|
+
value.to_s
|
171
|
+
else
|
172
|
+
value
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def process_json_hash(value, camelize_keys)
|
177
|
+
value.each_with_object({}) do |(key, val), hash|
|
178
|
+
next if val.respond_to?(:empty?) && val.empty?
|
179
|
+
|
180
|
+
camelize = camelize_keys ? camelize?(key) : false
|
181
|
+
key = convert_json_key(key, camelize: camelize)
|
182
|
+
hash[key] = generate_as_json(val, camelize_keys: camelize)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def convert_json_key(key, camelize: true)
|
187
|
+
key = key.to_s if key.is_a?(Symbol)
|
188
|
+
key = camel_case(key) if camelize
|
189
|
+
return key if key.is_a?(String)
|
190
|
+
|
191
|
+
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
|
192
|
+
end
|
193
|
+
|
194
|
+
def camel_case(str)
|
195
|
+
str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
|
196
|
+
end
|
197
|
+
end # Options
|
52
198
|
end # WebDriver
|
53
199
|
end # Selenium
|
@@ -57,6 +57,8 @@ module Selenium
|
|
57
57
|
:jenkins
|
58
58
|
elsif ENV['APPVEYOR']
|
59
59
|
:appveyor
|
60
|
+
elsif ENV['GITHUB_ACTIONS']
|
61
|
+
:github
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
@@ -76,6 +78,10 @@ module Selenium
|
|
76
78
|
engine == :jruby
|
77
79
|
end
|
78
80
|
|
81
|
+
def truffleruby?
|
82
|
+
engine == :truffleruby
|
83
|
+
end
|
84
|
+
|
79
85
|
def ruby_version
|
80
86
|
RUBY_VERSION
|
81
87
|
end
|
@@ -95,12 +101,14 @@ module Selenium
|
|
95
101
|
def wsl?
|
96
102
|
return false unless linux?
|
97
103
|
|
98
|
-
File.read('/proc/version').include?('
|
104
|
+
File.read('/proc/version').downcase.include?('microsoft')
|
105
|
+
rescue Errno::EACCES
|
106
|
+
# the file cannot be accessed on Linux on DeX
|
107
|
+
false
|
99
108
|
end
|
100
109
|
|
101
110
|
def cygwin?
|
102
|
-
RUBY_PLATFORM
|
103
|
-
!Regexp.last_match.nil?
|
111
|
+
RUBY_PLATFORM.include?('cygwin')
|
104
112
|
end
|
105
113
|
|
106
114
|
def null_device
|
@@ -172,9 +180,9 @@ module Selenium
|
|
172
180
|
|
173
181
|
def find_in_program_files(*binary_names)
|
174
182
|
paths = [
|
175
|
-
ENV
|
176
|
-
ENV
|
177
|
-
ENV
|
183
|
+
ENV.fetch('PROGRAMFILES', '\\Program Files'),
|
184
|
+
ENV.fetch('ProgramFiles(x86)', '\\Program Files (x86)'),
|
185
|
+
ENV.fetch('ProgramW6432', '\\Program Files')
|
178
186
|
]
|
179
187
|
|
180
188
|
paths.each do |root|
|
@@ -32,12 +32,10 @@ module Selenium
|
|
32
32
|
|
33
33
|
def self.free?(port)
|
34
34
|
Platform.interfaces.each do |host|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# ignored - some machines appear unable to bind to some of their interfaces
|
40
|
-
end
|
35
|
+
TCPServer.new(host, port).close
|
36
|
+
rescue *IGNORED_ERRORS => e
|
37
|
+
WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})", id: :driver_service)
|
38
|
+
# ignored - some machines appear unable to bind to some of their interfaces
|
41
39
|
end
|
42
40
|
|
43
41
|
true
|
@@ -31,8 +31,16 @@ module Selenium
|
|
31
31
|
base.extend ClassMethods
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.decoded(json)
|
35
|
+
JSON.parse(json).fetch('zip')
|
36
|
+
end
|
37
|
+
|
38
|
+
def encoded
|
39
|
+
Zipper.zip(layout_on_disk)
|
40
|
+
end
|
41
|
+
|
34
42
|
def as_json(*)
|
35
|
-
{
|
43
|
+
{'zip' => encoded}
|
36
44
|
end
|
37
45
|
|
38
46
|
def to_json(*)
|
@@ -63,18 +71,12 @@ module Selenium
|
|
63
71
|
|
64
72
|
module ClassMethods
|
65
73
|
def from_json(json)
|
66
|
-
data =
|
74
|
+
data = decoded(json)
|
67
75
|
|
68
|
-
|
69
|
-
# can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
|
70
|
-
tmp_dir = Dir.mktmpdir
|
71
|
-
begin
|
72
|
-
zip_path = File.join(tmp_dir, "webdriver-profile-duplicate-#{json.hash}.zip")
|
76
|
+
Tempfile.create do |zip_path|
|
73
77
|
File.open(zip_path, 'wb') { |zip_file| zip_file << Base64.decode64(data) }
|
74
78
|
|
75
79
|
new Zipper.unzip(zip_path)
|
76
|
-
ensure
|
77
|
-
FileUtils.rm_rf tmp_dir
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end # ClassMethods
|
@@ -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
|
@@ -127,7 +127,10 @@ module Selenium
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def type=(type)
|
130
|
-
|
130
|
+
unless TYPES.key? type
|
131
|
+
raise ArgumentError,
|
132
|
+
"invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
|
133
|
+
end
|
131
134
|
|
132
135
|
if defined?(@type) && type != @type
|
133
136
|
raise ArgumentError, "incompatible proxy type #{type.inspect} (already set to #{@type.inspect})"
|
@@ -138,10 +141,10 @@ module Selenium
|
|
138
141
|
|
139
142
|
def as_json(*)
|
140
143
|
json_result = {
|
141
|
-
'proxyType' => TYPES[type],
|
144
|
+
'proxyType' => TYPES[type].downcase,
|
142
145
|
'ftpProxy' => ftp,
|
143
146
|
'httpProxy' => http,
|
144
|
-
'noProxy' => no_proxy,
|
147
|
+
'noProxy' => no_proxy.is_a?(String) ? no_proxy.split(', ') : no_proxy,
|
145
148
|
'proxyAutoconfigUrl' => pac,
|
146
149
|
'sslProxy' => ssl,
|
147
150
|
'autodetect' => auto_detect,
|
@@ -149,7 +152,7 @@ module Selenium
|
|
149
152
|
'socksUsername' => socks_username,
|
150
153
|
'socksPassword' => socks_password,
|
151
154
|
'socksVersion' => socks_version
|
152
|
-
}.
|
155
|
+
}.compact
|
153
156
|
|
154
157
|
json_result if json_result.length > 1
|
155
158
|
end
|
@@ -30,6 +30,7 @@ module Selenium
|
|
30
30
|
link_text: 'link text',
|
31
31
|
name: 'name',
|
32
32
|
partial_link_text: 'partial link text',
|
33
|
+
relative: 'relative',
|
33
34
|
tag_name: 'tag name',
|
34
35
|
xpath: 'xpath'
|
35
36
|
}.freeze
|
@@ -59,10 +60,7 @@ module Selenium
|
|
59
60
|
by = FINDERS[how.to_sym]
|
60
61
|
raise ArgumentError, "cannot find element by #{how.inspect}" unless by
|
61
62
|
|
62
|
-
bridge.find_element_by by, what
|
63
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
64
|
-
# Implicit Wait times out in Edge
|
65
|
-
raise Selenium::WebDriver::Error::NoSuchElementError
|
63
|
+
bridge.find_element_by by, what, ref
|
66
64
|
end
|
67
65
|
|
68
66
|
#
|
@@ -77,10 +75,7 @@ module Selenium
|
|
77
75
|
by = FINDERS[how.to_sym]
|
78
76
|
raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
|
79
77
|
|
80
|
-
bridge.find_elements_by by, what
|
81
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
82
|
-
# Implicit Wait times out in Edge
|
83
|
-
[]
|
78
|
+
bridge.find_elements_by by, what, ref
|
84
79
|
end
|
85
80
|
|
86
81
|
private
|
@@ -92,7 +87,10 @@ module Selenium
|
|
92
87
|
when 1
|
93
88
|
arg = args.first
|
94
89
|
|
95
|
-
|
90
|
+
unless arg.respond_to?(:shift)
|
91
|
+
raise ArgumentError,
|
92
|
+
"expected #{arg.inspect}:#{arg.class} to respond to #shift"
|
93
|
+
end
|
96
94
|
|
97
95
|
# this will be a single-entry hash, so use #shift over #first or #[]
|
98
96
|
arr = arg.dup.shift
|