selenium-webdriver 4.8.6 → 4.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +22 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/lib/selenium/server.rb +1 -1
- data/lib/selenium/webdriver/common/action_builder.rb +0 -8
- data/lib/selenium/webdriver/common/child_process.rb +9 -9
- data/lib/selenium/webdriver/common/driver_finder.rb +2 -1
- data/lib/selenium/webdriver/common/logger.rb +70 -26
- data/lib/selenium/webdriver/common/options.rb +1 -1
- data/lib/selenium/webdriver/common/port_prober.rb +1 -1
- data/lib/selenium/webdriver/common/selenium_manager.rb +7 -7
- data/lib/selenium/webdriver/common/service.rb +10 -2
- data/lib/selenium/webdriver/common/service_manager.rb +4 -2
- data/lib/selenium/webdriver/common/socket_lock.rb +1 -1
- data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +2 -2
- data/lib/selenium/webdriver/devtools/network_interceptor.rb +1 -1
- data/lib/selenium/webdriver/devtools.rb +11 -1
- data/lib/selenium/webdriver/firefox/profile.rb +1 -1
- data/lib/selenium/webdriver/remote/bridge.rb +6 -5
- data/lib/selenium/webdriver/remote/driver.rb +4 -2
- data/lib/selenium/webdriver/remote/http/common.rb +3 -3
- data/lib/selenium/webdriver/remote/http/curb.rb +1 -1
- data/lib/selenium/webdriver/remote/http/default.rb +1 -1
- data/lib/selenium/webdriver/support/color.rb +8 -8
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +2 -1
- data/selenium-webdriver.gemspec +1 -2
- metadata +7 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 382f56851a268a1f44ed42a9a0ec85d5136540df32711606657bf8961a95b6b1
|
4
|
+
data.tar.gz: edbf74e77ed56b92fe01cfe6493b8db901ebc7cdb3df9b4d561f03cb5a91dcda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84260d58d81b2be75717e10d597bdeaf7c7b36bec5483d664fe19a6c5891967a176ef26d8806ea160a4f229b051d1ede4fa20d244e4b0c08f8409ccac8f640ca
|
7
|
+
data.tar.gz: 40af1b4e6fa0f6a85b608ce485336b0b7ba10ad35e7c8749c81c78808ba506d5a6294933b5771b3b5cb413f2b57b447af62dd236ce3e6ca4ed25f1949cc07bf6
|
data/CHANGES
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
4.9.1 (2023-05-08)
|
2
|
+
=========================
|
3
|
+
Ruby:
|
4
|
+
* Allow users to specify driver process output in Service class (#11964)
|
5
|
+
* Updated minimum required Ruby version to 3.0
|
6
|
+
* Selenium Logger defaults to :info and all debugging is now logged as :debug (#11967)
|
7
|
+
* Every logging entry can be ignored based on ID, not just warnings
|
8
|
+
* Logging entries can be filtered to allow or ignore specific IDs
|
9
|
+
|
10
|
+
BiDi:
|
11
|
+
* Fix bug with loading devtools (#11931) (thanks Boris Petrov!)
|
12
|
+
* Released selenium-devtools 0.113.0 (supports CDP v85, v111, v112, v113)
|
13
|
+
|
14
|
+
4.9.0 (2023-04-21)
|
15
|
+
=========================
|
16
|
+
Ruby:
|
17
|
+
* Fix devtools version fallback (#11869)
|
18
|
+
* Fix bug in selenium manager escaping back slashes in Windows (#11884)
|
19
|
+
|
20
|
+
BiDi:
|
21
|
+
* Released selenium-devtools 0.112.0 (supports CDP v85, v110, v111, v112)
|
22
|
+
|
1
23
|
4.8.6 (2023-03-29)
|
2
24
|
=========================
|
3
25
|
Ruby:
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/lib/selenium/server.rb
CHANGED
@@ -254,7 +254,7 @@ module Selenium
|
|
254
254
|
args = ['-jar', @jar, @role, '--port', @port.to_s]
|
255
255
|
server_command = ['java'] + properties + args + @additional_args
|
256
256
|
cp = WebDriver::ChildProcess.build(*server_command)
|
257
|
-
WebDriver.logger.debug("Executing Process #{server_command}")
|
257
|
+
WebDriver.logger.debug("Executing Process #{server_command}", id: :server)
|
258
258
|
|
259
259
|
if @log.is_a?(String)
|
260
260
|
cp.io = @log
|
@@ -250,14 +250,6 @@ module Selenium
|
|
250
250
|
@devices << device
|
251
251
|
device
|
252
252
|
end
|
253
|
-
|
254
|
-
def deprecate_method(device = nil, duration = nil, number = nil, method: :pause)
|
255
|
-
return unless device || number || duration
|
256
|
-
|
257
|
-
WebDriver.logger.deprecate "ActionBuilder##{method} with ordered parameters",
|
258
|
-
':device, :duration, :number keywords',
|
259
|
-
id: method
|
260
|
-
end
|
261
253
|
end # ActionBuilder
|
262
254
|
end # WebDriver
|
263
255
|
end # Selenium
|
@@ -53,9 +53,9 @@ module Selenium
|
|
53
53
|
options = {%i[out err] => io}
|
54
54
|
options[:pgroup] = true unless Platform.windows? # NOTE: this is a bug only in Windows 7
|
55
55
|
|
56
|
-
WebDriver.logger.debug("Starting process: #{@command} with #{options}")
|
56
|
+
WebDriver.logger.debug("Starting process: #{@command} with #{options}", id: :process)
|
57
57
|
@pid = Process.spawn(*@command, options)
|
58
|
-
WebDriver.logger.debug(" -> pid: #{@pid}")
|
58
|
+
WebDriver.logger.debug(" -> pid: #{@pid}", id: :process)
|
59
59
|
|
60
60
|
Process.detach(@pid) if detach
|
61
61
|
end
|
@@ -64,16 +64,16 @@ module Selenium
|
|
64
64
|
return unless @pid
|
65
65
|
return if exited?
|
66
66
|
|
67
|
-
WebDriver.logger.debug("Sending TERM to process: #{@pid}")
|
67
|
+
WebDriver.logger.debug("Sending TERM to process: #{@pid}", id: :process)
|
68
68
|
terminate(@pid)
|
69
69
|
poll_for_exit(timeout)
|
70
70
|
|
71
|
-
WebDriver.logger.debug(" -> stopped #{@pid}")
|
71
|
+
WebDriver.logger.debug(" -> stopped #{@pid}", id: :process)
|
72
72
|
rescue TimeoutError, Errno::EINVAL
|
73
|
-
WebDriver.logger.debug(" -> sending KILL to process: #{@pid}")
|
73
|
+
WebDriver.logger.debug(" -> sending KILL to process: #{@pid}", id: :process)
|
74
74
|
kill(@pid)
|
75
75
|
wait
|
76
|
-
WebDriver.logger.debug(" -> killed #{@pid}")
|
76
|
+
WebDriver.logger.debug(" -> killed #{@pid}", id: :process)
|
77
77
|
end
|
78
78
|
|
79
79
|
def alive?
|
@@ -83,18 +83,18 @@ module Selenium
|
|
83
83
|
def exited?
|
84
84
|
return unless @pid
|
85
85
|
|
86
|
-
WebDriver.logger.debug("Checking if #{@pid} is exited:")
|
86
|
+
WebDriver.logger.debug("Checking if #{@pid} is exited:", id: :process)
|
87
87
|
_, @status = Process.waitpid2(@pid, Process::WNOHANG | Process::WUNTRACED) if @status.nil?
|
88
88
|
return if @status.nil?
|
89
89
|
|
90
90
|
exit_code = @status.exitstatus || @status.termsig
|
91
|
-
WebDriver.logger.debug(" -> exit code is #{exit_code.inspect}")
|
91
|
+
WebDriver.logger.debug(" -> exit code is #{exit_code.inspect}", id: :process)
|
92
92
|
|
93
93
|
!!exit_code
|
94
94
|
end
|
95
95
|
|
96
96
|
def poll_for_exit(timeout)
|
97
|
-
WebDriver.logger.debug("Polling #{timeout} seconds for exit of #{@pid}")
|
97
|
+
WebDriver.logger.debug("Polling #{timeout} seconds for exit of #{@pid}", id: :process)
|
98
98
|
|
99
99
|
end_time = Time.now + timeout
|
100
100
|
sleep POLL_INTERVAL until exited? || Time.now > end_time
|
@@ -28,7 +28,8 @@ module Selenium
|
|
28
28
|
path ||= begin
|
29
29
|
SeleniumManager.driver_path(options)
|
30
30
|
rescue StandardError => e
|
31
|
-
WebDriver.logger.warn("Unable obtain driver using Selenium Manager\n #{e.message}"
|
31
|
+
WebDriver.logger.warn("Unable to obtain driver using Selenium Manager\n #{e.message}",
|
32
|
+
id: :selenium_manager)
|
32
33
|
nil
|
33
34
|
end
|
34
35
|
msg = "Unable to locate the #{klass::EXECUTABLE} executable; for more information on how to install drivers, " \
|
@@ -38,22 +38,33 @@ module Selenium
|
|
38
38
|
|
39
39
|
def_delegators :@logger,
|
40
40
|
:close,
|
41
|
-
:debug
|
42
|
-
:info
|
41
|
+
:debug?,
|
42
|
+
:info?,
|
43
43
|
:warn?,
|
44
44
|
:error, :error?,
|
45
45
|
:fatal, :fatal?,
|
46
|
-
:level
|
46
|
+
:level
|
47
47
|
|
48
48
|
#
|
49
49
|
# @param [String] progname Allow child projects to use Selenium's Logger pattern
|
50
50
|
#
|
51
|
-
def initialize(progname = 'Selenium', ignored: nil)
|
52
|
-
|
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)
|
53
55
|
@ignored = Array(ignored)
|
56
|
+
@allowed = Array(allowed)
|
54
57
|
@first_warning = false
|
55
58
|
end
|
56
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
|
66
|
+
end
|
67
|
+
|
57
68
|
#
|
58
69
|
# Changes logger output to a new IO.
|
59
70
|
#
|
@@ -81,34 +92,60 @@ module Selenium
|
|
81
92
|
#
|
82
93
|
# Will not log the provided ID.
|
83
94
|
#
|
84
|
-
# @param [Array, Symbol]
|
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
|
85
117
|
#
|
86
|
-
def
|
87
|
-
|
118
|
+
def debug(message, id: [], &block)
|
119
|
+
discard_or_log(:debug, message, id, &block)
|
88
120
|
end
|
89
121
|
|
90
122
|
#
|
91
|
-
#
|
123
|
+
# Used to supply information of general interest
|
92
124
|
#
|
93
125
|
# @param [String] message
|
94
126
|
# @param [Symbol, Array<Sybmol>] id
|
95
127
|
# @yield see #deprecate
|
96
128
|
#
|
97
|
-
def
|
129
|
+
def info(message, id: [], &block)
|
98
130
|
unless @first_warning
|
99
131
|
@first_warning = true
|
100
|
-
|
101
|
-
"https://selenium.dev/documentation/webdriver/troubleshooting/logging
|
132
|
+
info("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
|
133
|
+
"https://selenium.dev/documentation/webdriver/troubleshooting/logging\n"
|
102
134
|
end
|
103
135
|
end
|
104
136
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
|
109
|
-
msg += " #{yield}" if block_given?
|
137
|
+
discard_or_log(:info, message, id, &block)
|
138
|
+
end
|
110
139
|
|
111
|
-
|
140
|
+
#
|
141
|
+
# Used to supply information that suggests action be taken by user
|
142
|
+
#
|
143
|
+
# @param [String] message
|
144
|
+
# @param [Symbol, Array<Sybmol>] id
|
145
|
+
# @yield see #deprecate
|
146
|
+
#
|
147
|
+
def warn(message, id: [], &block)
|
148
|
+
discard_or_log(:warn, message, id, &block)
|
112
149
|
end
|
113
150
|
|
114
151
|
#
|
@@ -122,11 +159,11 @@ module Selenium
|
|
122
159
|
#
|
123
160
|
def deprecate(old, new = nil, id: [], reference: '', &block)
|
124
161
|
id = Array(id)
|
125
|
-
return if @ignored.include?(:deprecations)
|
162
|
+
return if @ignored.include?(:deprecations)
|
126
163
|
|
127
|
-
|
164
|
+
id << :deprecations if @allowed.include?(:deprecations)
|
128
165
|
|
129
|
-
message = +"[DEPRECATION] #{
|
166
|
+
message = +"[DEPRECATION] #{old} is deprecated"
|
130
167
|
message << if new
|
131
168
|
". Use #{new} instead."
|
132
169
|
else
|
@@ -134,15 +171,15 @@ module Selenium
|
|
134
171
|
end
|
135
172
|
message << " See explanation for this deprecation: #{reference}." unless reference.empty?
|
136
173
|
|
137
|
-
warn message, &block
|
174
|
+
discard_or_log(:warn, message, id, &block)
|
138
175
|
end
|
139
176
|
|
140
177
|
private
|
141
178
|
|
142
|
-
def create_logger(name)
|
179
|
+
def create_logger(name, level:)
|
143
180
|
logger = ::Logger.new($stdout)
|
144
181
|
logger.progname = name
|
145
|
-
logger.level =
|
182
|
+
logger.level = level
|
146
183
|
logger.formatter = proc do |severity, time, progname, msg|
|
147
184
|
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
148
185
|
end
|
@@ -150,8 +187,15 @@ module Selenium
|
|
150
187
|
logger
|
151
188
|
end
|
152
189
|
|
153
|
-
def
|
154
|
-
|
190
|
+
def discard_or_log(level, message, id)
|
191
|
+
id = Array(id)
|
192
|
+
return if (@ignored & id).any?
|
193
|
+
return if @allowed.any? && (@allowed & id).none?
|
194
|
+
|
195
|
+
msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
|
196
|
+
msg += " #{yield}" if block_given?
|
197
|
+
|
198
|
+
@logger.send(level) { msg }
|
155
199
|
end
|
156
200
|
end # Logger
|
157
201
|
end # WebDriver
|
@@ -128,7 +128,7 @@ module Selenium
|
|
128
128
|
|
129
129
|
unless options.empty?
|
130
130
|
msg = 'These options are not w3c compliant and will result in failures in a future release'
|
131
|
-
WebDriver.logger.warn("#{msg}: #{options}")
|
131
|
+
WebDriver.logger.warn("#{msg}: #{options}", id: :w3c_options)
|
132
132
|
browser_options.merge!(options)
|
133
133
|
end
|
134
134
|
|
@@ -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
|
|
@@ -33,8 +33,8 @@ module Selenium
|
|
33
33
|
# @param [Options] options browser options.
|
34
34
|
# @return [String] the path to the correct driver.
|
35
35
|
def driver_path(options)
|
36
|
-
message = 'applicable driver not found; attempting to install with Selenium Manager'
|
37
|
-
WebDriver.logger.
|
36
|
+
message = 'applicable driver not found; attempting to install with Selenium Manager (Beta)'
|
37
|
+
WebDriver.logger.info(message, id: :selenium_manager)
|
38
38
|
|
39
39
|
unless options.is_a?(Options)
|
40
40
|
raise ArgumentError, "SeleniumManager requires a WebDriver::Options instance, not #{options.inspect}"
|
@@ -47,12 +47,12 @@ module Selenium
|
|
47
47
|
end
|
48
48
|
if options.respond_to?(:binary) && !options.binary.nil?
|
49
49
|
command << '--browser-path'
|
50
|
-
command << options.binary
|
50
|
+
command << options.binary.gsub('\\', '\\\\\\')
|
51
51
|
end
|
52
52
|
command << '--debug' if WebDriver.logger.debug?
|
53
53
|
|
54
54
|
location = run(*command)
|
55
|
-
WebDriver.logger.debug("Driver found at #{location}")
|
55
|
+
WebDriver.logger.debug("Driver found at #{location}", id: :selenium_manager)
|
56
56
|
Platform.assert_executable location
|
57
57
|
|
58
58
|
location
|
@@ -76,13 +76,13 @@ module Selenium
|
|
76
76
|
raise Error::WebDriverError, 'Unable to obtain Selenium Manager'
|
77
77
|
end
|
78
78
|
|
79
|
-
WebDriver.logger.debug("Selenium Manager found at #{location}")
|
79
|
+
WebDriver.logger.debug("Selenium Manager found at #{location}", id: :selenium_manager)
|
80
80
|
location
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
def run(*command)
|
85
|
-
WebDriver.logger.debug("Executing Process #{command}")
|
85
|
+
WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
|
86
86
|
|
87
87
|
begin
|
88
88
|
stdout, stderr, status = Open3.capture3(*command)
|
@@ -97,7 +97,7 @@ module Selenium
|
|
97
97
|
end
|
98
98
|
|
99
99
|
json_output['logs'].each do |log|
|
100
|
-
WebDriver.logger.send(log['level'].downcase, log['message'])
|
100
|
+
WebDriver.logger.send(log['level'].downcase, log['message'], id: :selenium_manager)
|
101
101
|
end
|
102
102
|
|
103
103
|
result
|
@@ -57,7 +57,7 @@ module Selenium
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
attr_accessor :host, :executable_path, :port, :args
|
60
|
+
attr_accessor :host, :executable_path, :port, :log, :args
|
61
61
|
alias extra_args args
|
62
62
|
|
63
63
|
#
|
@@ -66,13 +66,21 @@ module Selenium
|
|
66
66
|
# @api private
|
67
67
|
#
|
68
68
|
|
69
|
-
def initialize(path: nil, port: nil, args: nil)
|
69
|
+
def initialize(path: nil, port: nil, log: nil, args: nil)
|
70
70
|
port ||= self.class::DEFAULT_PORT
|
71
71
|
args ||= []
|
72
72
|
|
73
73
|
@executable_path = path
|
74
74
|
@host = Platform.localhost
|
75
75
|
@port = Integer(port)
|
76
|
+
@log = case log
|
77
|
+
when :stdout
|
78
|
+
$stdout
|
79
|
+
when :stderr
|
80
|
+
$stderr
|
81
|
+
else
|
82
|
+
log
|
83
|
+
end
|
76
84
|
|
77
85
|
@args = args.is_a?(Hash) ? extract_service_args(args) : args
|
78
86
|
|
@@ -41,6 +41,7 @@ module Selenium
|
|
41
41
|
@host = Platform.localhost
|
42
42
|
@port = config.port
|
43
43
|
@extra_args = config.args
|
44
|
+
@io = config.log
|
44
45
|
@shutdown_supported = config.shutdown_supported
|
45
46
|
|
46
47
|
raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
|
@@ -77,9 +78,10 @@ module Selenium
|
|
77
78
|
private
|
78
79
|
|
79
80
|
def build_process(*command)
|
80
|
-
WebDriver.logger.debug("Executing Process #{command}")
|
81
|
+
WebDriver.logger.debug("Executing Process #{command}", id: :driver_service)
|
81
82
|
@process = ChildProcess.build(*command)
|
82
|
-
@
|
83
|
+
@io ||= WebDriver.logger.io if WebDriver.logger.debug?
|
84
|
+
@process.io = @io if @io
|
83
85
|
|
84
86
|
@process
|
85
87
|
end
|
@@ -93,7 +93,7 @@ module Selenium
|
|
93
93
|
true
|
94
94
|
rescue *NOT_CONNECTED_ERRORS
|
95
95
|
sock&.close
|
96
|
-
WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
|
96
|
+
WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}", id: :driver_service)
|
97
97
|
false
|
98
98
|
end
|
99
99
|
end
|
@@ -55,7 +55,7 @@ module Selenium
|
|
55
55
|
def send_cmd(**payload)
|
56
56
|
id = next_id
|
57
57
|
data = payload.merge(id: id)
|
58
|
-
WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE]
|
58
|
+
WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE], id: :bidi
|
59
59
|
data = JSON.generate(data)
|
60
60
|
out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text')
|
61
61
|
socket.write(out_frame.to_s)
|
@@ -112,7 +112,7 @@ module Selenium
|
|
112
112
|
|
113
113
|
message = JSON.parse(message)
|
114
114
|
messages[message['id']] = message
|
115
|
-
WebDriver.logger.debug "WebSocket <- #{message}"[...MAX_LOG_MESSAGE_SIZE]
|
115
|
+
WebDriver.logger.debug "WebSocket <- #{message}"[...MAX_LOG_MESSAGE_SIZE], id: :bidi
|
116
116
|
|
117
117
|
message
|
118
118
|
end
|
@@ -134,7 +134,7 @@ module Selenium
|
|
134
134
|
request_id: request.id,
|
135
135
|
url: request.url,
|
136
136
|
method: request.method,
|
137
|
-
post_data: request.post_data,
|
137
|
+
post_data: (Base64.strict_encode64(request.post_data) if request.post_data),
|
138
138
|
headers: request.headers.map do |k, v|
|
139
139
|
{name: k, value: v}
|
140
140
|
end
|
@@ -52,7 +52,17 @@ module Selenium
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def method_missing(method, *_args)
|
55
|
-
|
55
|
+
namespace = "Selenium::DevTools::V#{Selenium::DevTools.version}"
|
56
|
+
methods_to_classes = "#{namespace}::METHODS_TO_CLASSES"
|
57
|
+
|
58
|
+
desired_class = if Object.const_defined?(methods_to_classes)
|
59
|
+
# selenium-devtools 0.113 and newer
|
60
|
+
"#{namespace}::#{Object.const_get(methods_to_classes)[method]}"
|
61
|
+
else
|
62
|
+
# selenium-devtools 0.112 and older
|
63
|
+
"#{namespace}::#{method.capitalize}"
|
64
|
+
end
|
65
|
+
|
56
66
|
return unless Object.const_defined?(desired_class)
|
57
67
|
|
58
68
|
self.class.class_eval do
|
@@ -160,7 +160,7 @@ module Selenium
|
|
160
160
|
destination = File.join(directory, 'extensions')
|
161
161
|
|
162
162
|
@extensions.each do |name, extension|
|
163
|
-
WebDriver.logger.debug({
|
163
|
+
WebDriver.logger.debug({extension: name}.inspect, id: :firefox_profile)
|
164
164
|
extension.write_to(destination)
|
165
165
|
end
|
166
166
|
end
|
@@ -407,7 +407,8 @@ module Selenium
|
|
407
407
|
|
408
408
|
def upload(local_file)
|
409
409
|
unless File.file?(local_file)
|
410
|
-
WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!"
|
410
|
+
WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!",
|
411
|
+
id: :file_detector)
|
411
412
|
raise Error::WebDriverError, "You are trying to work with something that isn't a file."
|
412
413
|
end
|
413
414
|
|
@@ -443,7 +444,7 @@ module Selenium
|
|
443
444
|
end
|
444
445
|
|
445
446
|
def element_attribute(element, name)
|
446
|
-
WebDriver.logger.
|
447
|
+
WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
|
447
448
|
execute_atom :getAttribute, element, name
|
448
449
|
end
|
449
450
|
|
@@ -503,7 +504,7 @@ module Selenium
|
|
503
504
|
end
|
504
505
|
|
505
506
|
def element_displayed?(element)
|
506
|
-
WebDriver.logger.
|
507
|
+
WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
|
507
508
|
execute_atom :isDisplayed, element
|
508
509
|
end
|
509
510
|
|
@@ -615,7 +616,7 @@ module Selenium
|
|
615
616
|
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
616
617
|
end
|
617
618
|
|
618
|
-
WebDriver.logger.
|
619
|
+
WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
|
619
620
|
http.call(verb, path, command_hash)['value']
|
620
621
|
end
|
621
622
|
|
@@ -682,7 +683,7 @@ module Selenium
|
|
682
683
|
[how, what]
|
683
684
|
end
|
684
685
|
|
685
|
-
ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])
|
686
|
+
ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
|
686
687
|
UNICODE_CODE_POINT = 30
|
687
688
|
|
688
689
|
# Escapes invalid characters in CSS selector.
|
@@ -45,8 +45,10 @@ module Selenium
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def devtools_version
|
48
|
-
capabilities['se:cdpVersion']&.split('.')&.first
|
49
|
-
|
48
|
+
cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
|
49
|
+
raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
|
50
|
+
|
51
|
+
Integer(cdp_version)
|
50
52
|
end
|
51
53
|
|
52
54
|
def process_options(options, capabilities)
|
@@ -49,8 +49,8 @@ module Selenium
|
|
49
49
|
payload = JSON.generate(command_hash)
|
50
50
|
headers['Content-Length'] = payload.bytesize.to_s if %i[post put].include?(verb)
|
51
51
|
|
52
|
-
WebDriver.logger.
|
53
|
-
WebDriver.logger.debug(" > #{headers.inspect}")
|
52
|
+
WebDriver.logger.debug(" >>> #{url} | #{payload}", id: :command)
|
53
|
+
WebDriver.logger.debug(" > #{headers.inspect}", id: :header)
|
54
54
|
elsif verb == :post
|
55
55
|
payload = '{}'
|
56
56
|
headers['Content-Length'] = '2'
|
@@ -75,7 +75,7 @@ module Selenium
|
|
75
75
|
code = code.to_i
|
76
76
|
body = body.to_s.strip
|
77
77
|
content_type = content_type.to_s
|
78
|
-
WebDriver.logger.
|
78
|
+
WebDriver.logger.debug("<- #{body}", id: :command)
|
79
79
|
|
80
80
|
if content_type.include? CONTENT_TYPE
|
81
81
|
raise Error::WebDriverError, "empty body: #{content_type.inspect} (#{code})\n#{body}" if body.empty?
|
@@ -100,7 +100,7 @@ module Selenium
|
|
100
100
|
|
101
101
|
request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
|
102
102
|
else
|
103
|
-
WebDriver.logger.debug(" <<< #{response.instance_variable_get(:@header).inspect}")
|
103
|
+
WebDriver.logger.debug(" <<< #{response.instance_variable_get(:@header).inspect}", id: :header)
|
104
104
|
create_response response.code, response.body, response.content_type
|
105
105
|
end
|
106
106
|
end
|
@@ -23,27 +23,27 @@ module Selenium
|
|
23
23
|
class Color
|
24
24
|
RGB_PATTERN = /^\s*rgb\(\s*(\d{1,3})\s*,
|
25
25
|
\s*(\d{1,3})\s*,
|
26
|
-
\s*(\d{1,3})\s*\)\s*$/x
|
26
|
+
\s*(\d{1,3})\s*\)\s*$/x
|
27
27
|
RGB_PCT_PATTERN = /^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
|
28
28
|
\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
|
29
|
-
\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$/x
|
29
|
+
\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$/x
|
30
30
|
RGBA_PATTERN = /^\s*rgba\(\s*(\d{1,3})\s*,
|
31
31
|
\s*(\d{1,3})\s*,
|
32
32
|
\s*(\d{1,3})\s*,
|
33
|
-
\s*(0|1|0\.\d+)\s*\)\s*$/x
|
33
|
+
\s*(0|1|0\.\d+)\s*\)\s*$/x
|
34
34
|
RGBA_PCT_PATTERN = /^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)
|
35
35
|
%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)
|
36
36
|
%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)
|
37
|
-
%\s*,\s*(0|1|0\.\d+)\s*\)\s*$/x
|
38
|
-
HEX_PATTERN = /#(\h{2})(\h{2})(\h{2})
|
39
|
-
HEX3_PATTERN = /#(\h)(\h)(\h)
|
37
|
+
%\s*,\s*(0|1|0\.\d+)\s*\)\s*$/x
|
38
|
+
HEX_PATTERN = /#(\h{2})(\h{2})(\h{2})/
|
39
|
+
HEX3_PATTERN = /#(\h)(\h)(\h)/
|
40
40
|
HSL_PATTERN = /^\s*hsl\(\s*(\d{1,3})\s*,
|
41
41
|
\s*(\d{1,3})%\s*,
|
42
|
-
\s*(\d{1,3})%\s*\)\s*$/x
|
42
|
+
\s*(\d{1,3})%\s*\)\s*$/x
|
43
43
|
HSLA_PATTERN = /^\s*hsla\(\s*(\d{1,3})\s*,
|
44
44
|
\s*(\d{1,3})%\s*,
|
45
45
|
\s*(\d{1,3})%\s*,
|
46
|
-
\s*(0|1|0\.\d+)\s*\)\s*$/x
|
46
|
+
\s*(0|1|0\.\d+)\s*\)\s*$/x
|
47
47
|
|
48
48
|
attr_reader :red, :green, :blue, :alpha
|
49
49
|
|
data/lib/selenium/webdriver.rb
CHANGED
@@ -95,7 +95,8 @@ module Selenium
|
|
95
95
|
#
|
96
96
|
|
97
97
|
def self.logger(**opts)
|
98
|
-
|
98
|
+
level = $DEBUG || ENV.key?('DEBUG') ? :debug : :info
|
99
|
+
@logger ||= WebDriver::Logger.new('Selenium', default_level: level, **opts)
|
99
100
|
end
|
100
101
|
end # WebDriver
|
101
102
|
end # Selenium
|
data/selenium-webdriver.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
}
|
31
31
|
|
32
32
|
s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
|
33
|
-
s.required_ruby_version = Gem::Requirement.new('>=
|
33
|
+
s.required_ruby_version = Gem::Requirement.new('>= 3.0')
|
34
34
|
|
35
35
|
s.files = [
|
36
36
|
'CHANGES',
|
@@ -53,7 +53,6 @@ Gem::Specification.new do |s|
|
|
53
53
|
s.add_runtime_dependency 'rubyzip', ['>= 1.2.2', '< 3.0']
|
54
54
|
s.add_runtime_dependency 'websocket', ['~> 1.0']
|
55
55
|
|
56
|
-
s.add_development_dependency 'pry', ['~> 0.14']
|
57
56
|
s.add_development_dependency 'rack', ['~> 2.0']
|
58
57
|
s.add_development_dependency 'rspec', ['~> 3.0']
|
59
58
|
s.add_development_dependency 'rubocop', ['~> 1.42']
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selenium-webdriver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Rodionov
|
8
8
|
- Titus Fortner
|
9
9
|
- Thomas Walpole
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-05-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rexml
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: pry
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0.14'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0.14'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: rack
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -389,7 +375,7 @@ metadata:
|
|
389
375
|
github_repo: ssh://github.com/SeleniumHQ/selenium
|
390
376
|
source_code_uri: https://github.com/SeleniumHQ/selenium/tree/trunk/rb
|
391
377
|
rubygems_mfa_required: 'true'
|
392
|
-
post_install_message:
|
378
|
+
post_install_message:
|
393
379
|
rdoc_options: []
|
394
380
|
require_paths:
|
395
381
|
- lib
|
@@ -397,15 +383,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
397
383
|
requirements:
|
398
384
|
- - ">="
|
399
385
|
- !ruby/object:Gem::Version
|
400
|
-
version: '
|
386
|
+
version: '3.0'
|
401
387
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
402
388
|
requirements:
|
403
389
|
- - ">"
|
404
390
|
- !ruby/object:Gem::Version
|
405
391
|
version: 1.3.1
|
406
392
|
requirements: []
|
407
|
-
rubygems_version: 3.
|
408
|
-
signing_key:
|
393
|
+
rubygems_version: 3.2.33
|
394
|
+
signing_key:
|
409
395
|
specification_version: 4
|
410
396
|
summary: Selenium is a browser automation tool for automated testing of webapps and
|
411
397
|
more
|