selenium-webdriver 4.9.0 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +28 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- 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 +1 -1
- data/lib/selenium/webdriver/atoms/findElements.js +3 -4
- 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 +11 -7
- data/lib/selenium/webdriver/common/error.rb +28 -3
- data/lib/selenium/webdriver/common/logger.rb +87 -30
- data/lib/selenium/webdriver/common/options.rb +1 -1
- data/lib/selenium/webdriver/common/port_prober.rb +1 -1
- data/lib/selenium/webdriver/common/proxy.rb +1 -1
- data/lib/selenium/webdriver/common/selenium_manager.rb +42 -25
- 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.rb +1 -1
- data/lib/selenium/webdriver/edge/options.rb +14 -0
- data/lib/selenium/webdriver/firefox/profile.rb +1 -1
- data/lib/selenium/webdriver/remote/bridge.rb +6 -5
- 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/safari/service.rb +10 -0
- 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 +2 -2
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57f5a526cd47137c459f2eb349f03fbebc28b428a4d1eba1aed962cb8b32f0d4
|
4
|
+
data.tar.gz: 0e246eec8fc308f54bb651245cebaf3610a5abf4f6027728a6e96210b72a397e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 679674b291a9b3da8d41a917ed782d14743150b524767a915e464e39751971ce9420e7a21127dcf10ca070f3bd7bff14a61690c028b013daab8d638550f38a61
|
7
|
+
data.tar.gz: a39c8fdecf8a60ad8736aa3392bba7f540c692bdba451546463b8db4e9b967d81d1d30ca665aedb99901e6f173deb3af29fcdfcd7d7c087783b8e24358ae8814
|
data/CHANGES
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
4.10.0 (2023-06-07)
|
2
|
+
=========================
|
3
|
+
Ruby:
|
4
|
+
* Implement proxy support for Selenium Manager
|
5
|
+
* Prevent setting driver log level in Safari
|
6
|
+
* Change all Selenium Manager logging to :debug (#12145)
|
7
|
+
* Error messages include links to documentation
|
8
|
+
* Add custom error class for driver location and improve error logic
|
9
|
+
|
10
|
+
BiDi:
|
11
|
+
* Released selenium-devtools 0.114.0 (supports CDP v85, v112, v113, v114)
|
12
|
+
|
13
|
+
Edge:
|
14
|
+
* Add support for webview2
|
15
|
+
|
16
|
+
4.9.1 (2023-05-08)
|
17
|
+
=========================
|
18
|
+
Ruby:
|
19
|
+
* Allow users to specify driver process output in Service class (#11964)
|
20
|
+
* Updated minimum required Ruby version to 3.0
|
21
|
+
* Selenium Logger defaults to :info and all debugging is now logged as :debug (#11967)
|
22
|
+
* Every logging entry can be ignored based on ID, not just warnings
|
23
|
+
* Logging entries can be filtered to allow or ignore specific IDs
|
24
|
+
|
25
|
+
BiDi:
|
26
|
+
* Fix bug with loading devtools (#11931) (thanks Boris Petrov!)
|
27
|
+
* Released selenium-devtools 0.113.0 (supports CDP v85, v111, v112, v113)
|
28
|
+
|
1
29
|
4.9.0 (2023-04-21)
|
2
30
|
=========================
|
3
31
|
Ruby:
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/bin/linux/selenium-manager
CHANGED
Binary file
|
data/bin/macos/selenium-manager
CHANGED
Binary file
|
Binary file
|
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
|
@@ -113,10 +113,9 @@ function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.repla
|
|
113
113
|
function pd(a,b,c,d,e){if(3==a.nodeType&&c)nd(a,b,d,e);else if(S(a))if(S(a,"CONTENT")||S(a,"SLOT")){for(var f=a;f.parentNode;)f=f.parentNode;f instanceof ShadowRoot?(a=S(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),l(a,function(g){pd(g,b,c,d,e)})):jd(a,b)}else if(S(a,"SHADOW")){for(f=a;f.parentNode;)f=f.parentNode;if(f instanceof ShadowRoot&&(a=f))for(a=a.olderShadowRoot;a;)l(a.childNodes,function(g){pd(g,b,c,d,e)}),a=a.olderShadowRoot}else jd(a,b)}
|
114
114
|
function jd(a,b){a.shadowRoot&&l(a.shadowRoot.childNodes,function(c){pd(c,b,!0,null,null)});ld(a,b,function(c,d,e,f,g){var h=null;1==c.nodeType?h=c:3==c.nodeType&&(h=c);null!=h&&(null!=h.assignedSlot||h.getDestinationInsertionPoints&&0<h.getDestinationInsertionPoints().length)||pd(c,d,e,f,g)})};var qd={C:function(a,b){return!(!a.querySelectorAll||!a.querySelector)&&!/^\d.*/.test(b)},o:function(a,b){var c=eb(b),d="string"===typeof a?c.a.getElementById(a):a;return d?Uc(d,"id")==a&&b!=d&&hb(b,d)?d:ua(mb(c,"*"),function(e){return Uc(e,"id")==a&&b!=e&&hb(b,e)}):null},j:function(a,b){if(!a)return[];if(qd.C(b,a))try{return b.querySelectorAll("#"+qd.T(a))}catch(c){return[]}b=mb(eb(b),"*",null,b);return pa(b,function(c){return Uc(c,"id")==a})},T:function(a){return a.replace(/([\s'"\\#.:;,!?+<>=~*^$|%&@`{}\-\/\[\]\(\)])/g,
|
115
115
|
"\\$1")}};var Y={},rd={};Y.N=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return ua(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.K=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return pa(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.o=function(a,b){return Y.N(a,b,!1)};Y.j=function(a,b){return Y.K(a,b,!1)};rd.o=function(a,b){return Y.N(a,b,!0)};
|
116
|
-
rd.j=function(a,b){return Y.K(a,b,!0)};var Z={F:function(a,b){return function(c){var d=Z.u(a);d=W(d);c=W(c);return b.call(null,d,c)}},R:function(a){return Z.F(a,function(b,c){return c.b+c.height<b.b})},S:function(a){return Z.F(a,function(b,c){return b.b+b.height<c.b})},V:function(a){return Z.F(a,function(b,c){return c.a+c.width<b.a})},aa:function(a){return Z.F(a,function(b,c){return b.a+b.width<c.a})},W:function(a,b){var c;b?c=b:"number"==typeof a.distance&&(c=a.distance);c||(c=
|
117
|
-
|
118
|
-
|
119
|
-
Z.U=function(a,b){var c=[];l(a,function(e){e&&ta(b,function(f){var g=f.kind,h=Z.P[g];if(!h)throw new P(61,"Cannot find filter suitable for "+g);return h.apply(null,f.args)(e)},null)&&c.push(e)},null);a=b[b.length-1];var d=Z.O[a?a.kind:"unknown"];return d?(a=d.apply(null,a.args))?Z.ba(a,c):c:c};
|
116
|
+
rd.j=function(a,b){return Y.K(a,b,!0)};var Z={F:function(a,b){return function(c){var d=Z.u(a);d=W(d);c=W(c);return b.call(null,d,c)}},R:function(a){return Z.F(a,function(b,c){return c.b+c.height<b.b})},S:function(a){return Z.F(a,function(b,c){return b.b+b.height<c.b})},V:function(a){return Z.F(a,function(b,c){return c.a+c.width<b.a})},aa:function(a){return Z.F(a,function(b,c){return b.a+b.width<c.a})},W:function(a,b){var c;b?c=b:"number"==typeof a.distance&&(c=a.distance);c||(c=50);return function(d){var e=Z.u(a);if(e===d)return!1;e=W(e);
|
117
|
+
d=W(d);e=new U(e.a-c,e.b-c,e.width+2*c,e.height+2*c);return e.a<=d.a+d.width&&d.a<=e.a+e.width&&e.b<=d.b+d.height&&d.b<=e.b+e.height}},u:function(a){if(ha(a)&&1==a.nodeType)return a;if(ea(a))return Z.u(a.call(null));if(ha(a)){var b;a:{if(b=sd(a)){var c=td[b];if(c&&ea(c.o)){b=c.o(a[b],Bc.document);break a}}throw new P(61,"Unsupported locator strategy: "+b);}if(!b)throw new P(7,"No element has been found by "+JSON.stringify(a));return b}throw new P(61,"Selector is of wrong type: "+JSON.stringify(a));
|
118
|
+
}};Z.P={left:Z.V,right:Z.aa,above:Z.R,below:Z.S,near:Z.W};Z.O={left:Z.u,right:Z.u,above:Z.u,below:Z.u,near:Z.u};Z.U=function(a,b){var c=[];l(a,function(e){e&&ta(b,function(f){var g=f.kind,h=Z.P[g];if(!h)throw new P(61,"Cannot find filter suitable for "+g);return h.apply(null,f.args)(e)},null)&&c.push(e)},null);a=b[b.length-1];var d=Z.O[a?a.kind:"unknown"];return d?(a=d.apply(null,a.args))?Z.ba(a,c):c:c};
|
120
119
|
Z.ba=function(a,b){function c(f){f=W(f);return Math.sqrt(Math.pow(d-(f.a+Math.max(1,f.width)/2),2)+Math.pow(e-(f.b+Math.max(1,f.height)/2),2))}a=W(a);var d=a.a+Math.max(1,a.width)/2,e=a.b+Math.max(1,a.height)/2;xa(b,function(f,g){return c(f)-c(g)});return b};Z.o=function(a,b){a=Z.j(a,b);return 0==a.length?null:a[0]};
|
121
120
|
Z.j=function(a,b){if(!a.hasOwnProperty("root")||!a.hasOwnProperty("filters"))throw new P(61,"Locator not suitable for relative locators: "+JSON.stringify(a));var c=a.filters,d=da(c);if("array"!=d&&("object"!=d||"number"!=typeof c.length))throw new P(61,"Targets should be an array: "+JSON.stringify(a));var e;S(a.root)?e=[a.root]:e=ud(a.root,b);return 0==e.length?[]:Z.U(e,a.filters)};var vd={o:function(a,b){if(""===a)throw new P(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)[0]||null},j:function(a,b){if(""===a)throw new P(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)}};var td={className:Dc,"class name":Dc,css:Nc,"css selector":Nc,relative:Z,id:qd,linkText:Y,"link text":Y,name:{o:function(a,b){b=mb(eb(b),"*",null,b);return ua(b,function(c){return Uc(c,"name")==a})},j:function(a,b){b=mb(eb(b),"*",null,b);return pa(b,function(c){return Uc(c,"name")==a})}},partialLinkText:rd,"partial link text":rd,tagName:vd,"tag name":vd,xpath:T};function sd(a){for(var b in a)if(a.hasOwnProperty(b))return b;return null}
|
122
121
|
function ud(a,b){var c=sd(a);if(c){var d=td[c];if(d&&ea(d.j))return d.j(a[c],b||Bc.document)}throw new P(61,"Unsupported locator strategy: "+c);};ca("_",ud);; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
|
@@ -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
|
@@ -26,16 +26,20 @@ module Selenium
|
|
26
26
|
path ||= Platform.find_binary(klass::EXECUTABLE)
|
27
27
|
|
28
28
|
path ||= begin
|
29
|
-
SeleniumManager.driver_path(options)
|
29
|
+
SeleniumManager.driver_path(options) unless options.is_a?(Remote::Capabilities)
|
30
30
|
rescue StandardError => e
|
31
|
-
|
32
|
-
|
31
|
+
raise Error::NoSuchDriverError, "Unable to obtain #{klass::EXECUTABLE} using Selenium Manager; #{e.message}"
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
Platform.assert_file(path)
|
36
|
+
Platform.assert_executable(path)
|
37
|
+
rescue TypeError
|
38
|
+
raise Error::NoSuchDriverError, "Unable to locate or obtain #{klass::EXECUTABLE}"
|
39
|
+
rescue Error::WebDriverError => e
|
40
|
+
raise Error::NoSuchDriverError, "#{klass::EXECUTABLE} located, but: #{e.message}"
|
33
41
|
end
|
34
|
-
msg = "Unable to locate the #{klass::EXECUTABLE} executable; for more information on how to install drivers, " \
|
35
|
-
'see https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/'
|
36
|
-
raise Error::WebDriverError, msg unless path
|
37
42
|
|
38
|
-
Platform.assert_executable path
|
39
43
|
path
|
40
44
|
end
|
41
45
|
end
|
@@ -34,13 +34,20 @@ module Selenium
|
|
34
34
|
WebDriverError
|
35
35
|
end
|
36
36
|
|
37
|
+
SUPPORT_MSG = 'For documentation on this error, please visit:'
|
38
|
+
ERROR_URL = 'https://www.selenium.dev/documentation/webdriver/troubleshooting/errors'
|
39
|
+
|
37
40
|
class WebDriverError < StandardError; end
|
38
41
|
|
39
42
|
#
|
40
43
|
# An element could not be located on the page using the given search parameters.
|
41
44
|
#
|
42
45
|
|
43
|
-
class NoSuchElementError < WebDriverError
|
46
|
+
class NoSuchElementError < WebDriverError
|
47
|
+
def initialize(msg = '')
|
48
|
+
super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}#no-such-element-exception")
|
49
|
+
end
|
50
|
+
end
|
44
51
|
|
45
52
|
#
|
46
53
|
# A command to switch to a frame could not be satisfied because the frame could not be found.
|
@@ -58,7 +65,11 @@ module Selenium
|
|
58
65
|
# A command failed because the referenced element is no longer attached to the DOM.
|
59
66
|
#
|
60
67
|
|
61
|
-
class StaleElementReferenceError < WebDriverError
|
68
|
+
class StaleElementReferenceError < WebDriverError
|
69
|
+
def initialize(msg = '')
|
70
|
+
super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}#stale-element-reference-exception")
|
71
|
+
end
|
72
|
+
end
|
62
73
|
|
63
74
|
#
|
64
75
|
# A command failed because the referenced shadow root is no longer attached to the DOM.
|
@@ -132,7 +143,11 @@ module Selenium
|
|
132
143
|
# Argument was an invalid selector.
|
133
144
|
#
|
134
145
|
|
135
|
-
class InvalidSelectorError < WebDriverError
|
146
|
+
class InvalidSelectorError < WebDriverError
|
147
|
+
def initialize(msg = '')
|
148
|
+
super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}#invalid-selector-exception")
|
149
|
+
end
|
150
|
+
end
|
136
151
|
|
137
152
|
#
|
138
153
|
# A new session could not be created.
|
@@ -212,6 +227,16 @@ module Selenium
|
|
212
227
|
#
|
213
228
|
|
214
229
|
class UnsupportedOperationError < WebDriverError; end
|
230
|
+
|
231
|
+
#
|
232
|
+
# Indicates that driver was not specified and could not be located.
|
233
|
+
#
|
234
|
+
|
235
|
+
class NoSuchDriverError < WebDriverError
|
236
|
+
def initialize(msg = '')
|
237
|
+
super("#{msg}; #{SUPPORT_MSG} #{ERROR_URL}/driver_location")
|
238
|
+
end
|
239
|
+
end
|
215
240
|
end # Error
|
216
241
|
end # WebDriver
|
217
242
|
end # Selenium
|
@@ -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
|
-
:error
|
44
|
+
: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,64 @@ module Selenium
|
|
81
92
|
#
|
82
93
|
# Will not log the provided ID.
|
83
94
|
#
|
84
|
-
# @param [Array, Symbol]
|
95
|
+
# @param [Array, Symbol] ids
|
85
96
|
#
|
86
|
-
def ignore(
|
87
|
-
Array(
|
97
|
+
def ignore(*ids)
|
98
|
+
@ignored += Array(ids).flatten
|
88
99
|
end
|
89
100
|
|
90
101
|
#
|
91
|
-
#
|
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
|
92
113
|
#
|
93
114
|
# @param [String] message
|
94
115
|
# @param [Symbol, Array<Sybmol>] id
|
95
116
|
# @yield see #deprecate
|
96
117
|
#
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
warn("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
|
101
|
-
"https://selenium.dev/documentation/webdriver/troubleshooting/logging#ruby\n"
|
102
|
-
end
|
103
|
-
end
|
118
|
+
def debug(message, id: [], &block)
|
119
|
+
discard_or_log(:debug, message, id, &block)
|
120
|
+
end
|
104
121
|
|
105
|
-
|
106
|
-
|
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
|
107
132
|
|
108
|
-
|
109
|
-
|
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
|
110
143
|
|
111
|
-
|
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)
|
112
153
|
end
|
113
154
|
|
114
155
|
#
|
@@ -122,11 +163,11 @@ module Selenium
|
|
122
163
|
#
|
123
164
|
def deprecate(old, new = nil, id: [], reference: '', &block)
|
124
165
|
id = Array(id)
|
125
|
-
return if @ignored.include?(:deprecations)
|
166
|
+
return if @ignored.include?(:deprecations)
|
126
167
|
|
127
|
-
|
168
|
+
id << :deprecations if @allowed.include?(:deprecations)
|
128
169
|
|
129
|
-
message = +"[DEPRECATION] #{
|
170
|
+
message = +"[DEPRECATION] #{old} is deprecated"
|
130
171
|
message << if new
|
131
172
|
". Use #{new} instead."
|
132
173
|
else
|
@@ -134,15 +175,15 @@ module Selenium
|
|
134
175
|
end
|
135
176
|
message << " See explanation for this deprecation: #{reference}." unless reference.empty?
|
136
177
|
|
137
|
-
warn message, &block
|
178
|
+
discard_or_log(:warn, message, id, &block)
|
138
179
|
end
|
139
180
|
|
140
181
|
private
|
141
182
|
|
142
|
-
def create_logger(name)
|
183
|
+
def create_logger(name, level:)
|
143
184
|
logger = ::Logger.new($stdout)
|
144
185
|
logger.progname = name
|
145
|
-
logger.level =
|
186
|
+
logger.level = level
|
146
187
|
logger.formatter = proc do |severity, time, progname, msg|
|
147
188
|
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
148
189
|
end
|
@@ -150,8 +191,24 @@ module Selenium
|
|
150
191
|
logger
|
151
192
|
end
|
152
193
|
|
153
|
-
def
|
154
|
-
|
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
|
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 }
|
155
212
|
end
|
156
213
|
end # Logger
|
157
214
|
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
|
|
@@ -27,19 +27,31 @@ module Selenium
|
|
27
27
|
# @api private
|
28
28
|
#
|
29
29
|
class SeleniumManager
|
30
|
-
BIN_PATH = '../../../../../bin'
|
31
|
-
|
32
30
|
class << self
|
31
|
+
attr_writer :bin_path
|
32
|
+
|
33
|
+
def bin_path
|
34
|
+
@bin_path ||= '../../../../../bin'
|
35
|
+
end
|
36
|
+
|
33
37
|
# @param [Options] options browser options.
|
34
38
|
# @return [String] the path to the correct driver.
|
35
39
|
def driver_path(options)
|
36
|
-
message = 'applicable driver not found; attempting to install with Selenium Manager'
|
37
|
-
WebDriver.logger.
|
40
|
+
message = 'applicable driver not found; attempting to install with Selenium Manager (Beta)'
|
41
|
+
WebDriver.logger.debug(message, id: :selenium_manager)
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
command = generate_command(binary, options)
|
44
|
+
|
45
|
+
location = run(*command)
|
46
|
+
WebDriver.logger.debug("Driver found at #{location}", id: :selenium_manager)
|
47
|
+
Platform.assert_executable location
|
48
|
+
|
49
|
+
location
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
42
53
|
|
54
|
+
def generate_command(binary, options)
|
43
55
|
command = [binary, '--browser', options.browser_name, '--output', 'json']
|
44
56
|
if options.browser_version
|
45
57
|
command << '--browser-version'
|
@@ -49,21 +61,18 @@ module Selenium
|
|
49
61
|
command << '--browser-path'
|
50
62
|
command << options.binary.gsub('\\', '\\\\\\')
|
51
63
|
end
|
64
|
+
if options.proxy
|
65
|
+
command << '--proxy'
|
66
|
+
(command << options.proxy.ssl) || options.proxy.http
|
67
|
+
end
|
52
68
|
command << '--debug' if WebDriver.logger.debug?
|
53
|
-
|
54
|
-
location = run(*command)
|
55
|
-
WebDriver.logger.debug("Driver found at #{location}")
|
56
|
-
Platform.assert_executable location
|
57
|
-
|
58
|
-
location
|
69
|
+
command
|
59
70
|
end
|
60
71
|
|
61
|
-
private
|
62
|
-
|
63
72
|
# @return [String] the path to the correct selenium manager
|
64
73
|
def binary
|
65
74
|
@binary ||= begin
|
66
|
-
path = File.expand_path(
|
75
|
+
path = File.expand_path(bin_path, __FILE__)
|
67
76
|
path << if Platform.windows?
|
68
77
|
'/windows/selenium-manager.exe'
|
69
78
|
elsif Platform.mac?
|
@@ -72,32 +81,40 @@ module Selenium
|
|
72
81
|
'/linux/selenium-manager'
|
73
82
|
end
|
74
83
|
location = File.expand_path(path, __FILE__)
|
75
|
-
|
76
|
-
|
84
|
+
|
85
|
+
begin
|
86
|
+
Platform.assert_file(location)
|
87
|
+
Platform.assert_executable(location)
|
88
|
+
rescue TypeError
|
89
|
+
raise Error::WebDriverError,
|
90
|
+
"Unable to locate or obtain Selenium Manager binary; #{location} is not a valid file object"
|
91
|
+
rescue Error::WebDriverError => e
|
92
|
+
raise Error::WebDriverError, "Selenium Manager binary located, but #{e.message}"
|
77
93
|
end
|
78
94
|
|
79
|
-
WebDriver.logger.debug("Selenium Manager found at #{location}")
|
95
|
+
WebDriver.logger.debug("Selenium Manager binary found at #{location}", id: :selenium_manager)
|
80
96
|
location
|
81
97
|
end
|
82
98
|
end
|
83
99
|
|
84
100
|
def run(*command)
|
85
|
-
WebDriver.logger.debug("Executing Process #{command}")
|
101
|
+
WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
|
86
102
|
|
87
103
|
begin
|
88
104
|
stdout, stderr, status = Open3.capture3(*command)
|
89
105
|
json_output = stdout.empty? ? nil : JSON.parse(stdout)
|
90
106
|
result = json_output&.dig('result', 'message')
|
91
107
|
rescue StandardError => e
|
92
|
-
raise Error::WebDriverError, "Unsuccessful command executed: #{command}
|
108
|
+
raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
|
93
109
|
end
|
94
110
|
|
95
|
-
|
96
|
-
|
111
|
+
(json_output&.fetch('logs') || []).each do |log|
|
112
|
+
level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
|
113
|
+
WebDriver.logger.send(level, log['message'], id: :selenium_manager)
|
97
114
|
end
|
98
115
|
|
99
|
-
|
100
|
-
|
116
|
+
if status.exitstatus.positive?
|
117
|
+
raise Error::WebDriverError, "Unsuccessful command executed: #{command}\n#{result}#{stderr}"
|
101
118
|
end
|
102
119
|
|
103
120
|
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
|
@@ -60,7 +60,7 @@ module Selenium
|
|
60
60
|
"#{namespace}::#{Object.const_get(methods_to_classes)[method]}"
|
61
61
|
else
|
62
62
|
# selenium-devtools 0.112 and older
|
63
|
-
"#{namespace}::#{method.capitalize}
|
63
|
+
"#{namespace}::#{method.capitalize}"
|
64
64
|
end
|
65
65
|
|
66
66
|
return unless Object.const_defined?(desired_class)
|
@@ -26,6 +26,20 @@ module Selenium
|
|
26
26
|
KEY = 'ms:edgeOptions'
|
27
27
|
BROWSER = 'MicrosoftEdge'
|
28
28
|
|
29
|
+
#
|
30
|
+
# Changes the browser name enable webview2
|
31
|
+
# see: https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/webdriver
|
32
|
+
# Automation of WebView2 apps with Microsoft Edge WebDriver
|
33
|
+
#
|
34
|
+
# @example Enable webview2
|
35
|
+
# options = Selenium::WebDriver::Edge::Options.new
|
36
|
+
# options.webview2!
|
37
|
+
#
|
38
|
+
|
39
|
+
def webview2!
|
40
|
+
@options[:browser_name] = 'webview2'
|
41
|
+
end
|
42
|
+
|
29
43
|
private
|
30
44
|
|
31
45
|
def enable_logging(browser_options)
|
@@ -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.
|
@@ -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
|
@@ -24,6 +24,16 @@ module Selenium
|
|
24
24
|
DEFAULT_PORT = 7050
|
25
25
|
EXECUTABLE = 'safaridriver'
|
26
26
|
SHUTDOWN_SUPPORTED = false
|
27
|
+
|
28
|
+
def initialize(path: nil, port: nil, log: nil, args: nil)
|
29
|
+
raise Error::WebDriverError, 'Safari Service does not support setting log output' if log
|
30
|
+
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def log=(*)
|
35
|
+
raise Error::WebDriverError, 'Safari Service does not support setting log output'
|
36
|
+
end
|
27
37
|
end # Service
|
28
38
|
end # Safari
|
29
39
|
end # WebDriver
|
@@ -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,8 +53,8 @@ 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']
|
57
|
+
s.add_development_dependency 'rake', ['~> 13.0']
|
58
58
|
s.add_development_dependency 'rspec', ['~> 3.0']
|
59
59
|
s.add_development_dependency 'rubocop', ['~> 1.42']
|
60
60
|
s.add_development_dependency 'rubocop-performance', ['~> 1.15']
|
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.10.0
|
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-06-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rexml
|
@@ -67,33 +67,33 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rack
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0
|
75
|
+
version: '2.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0
|
82
|
+
version: '2.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '13.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '13.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -389,7 +389,7 @@ metadata:
|
|
389
389
|
github_repo: ssh://github.com/SeleniumHQ/selenium
|
390
390
|
source_code_uri: https://github.com/SeleniumHQ/selenium/tree/trunk/rb
|
391
391
|
rubygems_mfa_required: 'true'
|
392
|
-
post_install_message:
|
392
|
+
post_install_message:
|
393
393
|
rdoc_options: []
|
394
394
|
require_paths:
|
395
395
|
- lib
|
@@ -397,15 +397,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
397
397
|
requirements:
|
398
398
|
- - ">="
|
399
399
|
- !ruby/object:Gem::Version
|
400
|
-
version: '
|
400
|
+
version: '3.0'
|
401
401
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
402
402
|
requirements:
|
403
403
|
- - ">"
|
404
404
|
- !ruby/object:Gem::Version
|
405
405
|
version: 1.3.1
|
406
406
|
requirements: []
|
407
|
-
rubygems_version: 3.
|
408
|
-
signing_key:
|
407
|
+
rubygems_version: 3.2.33
|
408
|
+
signing_key:
|
409
409
|
specification_version: 4
|
410
410
|
summary: Selenium is a browser automation tool for automated testing of webapps and
|
411
411
|
more
|