selenium-webdriver 4.9.0 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +40 -0
- data/Gemfile +2 -0
- data/README.md +2 -2
- 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 +4 -16
- data/lib/selenium/webdriver/atoms/findElements.js +3 -4
- data/lib/selenium/webdriver/chrome/service.rb +1 -3
- data/lib/selenium/webdriver/chromium/options.rb +0 -18
- data/lib/selenium/webdriver/chromium.rb +0 -1
- data/lib/selenium/webdriver/common/action_builder.rb +0 -8
- data/lib/selenium/webdriver/common/child_process.rb +11 -11
- data/lib/selenium/webdriver/common/driver_finder.rb +10 -8
- 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 +3 -22
- data/lib/selenium/webdriver/common/platform.rb +0 -49
- 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 +50 -27
- data/lib/selenium/webdriver/common/service.rb +11 -13
- 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 +3 -3
- data/lib/selenium/webdriver/devtools.rb +1 -1
- data/lib/selenium/webdriver/edge/options.rb +14 -0
- data/lib/selenium/webdriver/edge/service.rb +1 -3
- data/lib/selenium/webdriver/firefox/options.rb +0 -15
- data/lib/selenium/webdriver/firefox/profile.rb +1 -1
- data/lib/selenium/webdriver/firefox/service.rb +0 -12
- data/lib/selenium/webdriver/ie/options.rb +2 -1
- data/lib/selenium/webdriver/ie/service.rb +0 -16
- data/lib/selenium/webdriver/remote/bridge.rb +6 -5
- data/lib/selenium/webdriver/remote/capabilities.rb +0 -72
- 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 +2 -3
- data/lib/selenium/webdriver/remote/server_error.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 -14
- data/lib/selenium/webdriver/chromium/service.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55c2b164be56b90064957852c6b1f890f9cda063d5c0ef164752b7c67f6e40bb
|
4
|
+
data.tar.gz: 778d0c6d2450a3d178d709762c76b9ef2c24832131d4487f6c84b5789a32b1de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6777b04b259f2e7be27d7c2635f77b0e9006464f931e1e79a1e10f517474b71344534a8b02ba84445801581f4c50cb79901d15ef8e74133c08357625e5ad9de6
|
7
|
+
data.tar.gz: 5f1e3af40a4bbcc3e4e77407321d64b1e6920ca91fcf7605bce780d42138fd587bfc951563205d8cf6e4b63952e7e4e35dd52aba496fcb1e468e6a086c81c92d
|
data/CHANGES
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
4.11.0 (2023-07-31)
|
2
|
+
=========================
|
3
|
+
Ruby:
|
4
|
+
* Made network interception threads fail silently (#12226)
|
5
|
+
* Have Selenium Manager binary locate drivers on PATH (#12345)
|
6
|
+
* Add browser output from selenium manager to options (#12398)
|
7
|
+
* Remove deprecated code (#12417)
|
8
|
+
BiDi:
|
9
|
+
* Released selenium-devtools 0.115.0 (supports CDP v85, v113, v114, v115)
|
10
|
+
Edge:
|
11
|
+
* Adding ignore process match for IE Mode across bindings (#12279)
|
12
|
+
|
13
|
+
4.10.0 (2023-06-07)
|
14
|
+
=========================
|
15
|
+
Ruby:
|
16
|
+
* Implement proxy support for Selenium Manager
|
17
|
+
* Prevent setting driver log level in Safari
|
18
|
+
* Change all Selenium Manager logging to :debug (#12145)
|
19
|
+
* Error messages include links to documentation
|
20
|
+
* Add custom error class for driver location and improve error logic
|
21
|
+
|
22
|
+
BiDi:
|
23
|
+
* Released selenium-devtools 0.114.0 (supports CDP v85, v112, v113, v114)
|
24
|
+
|
25
|
+
Edge:
|
26
|
+
* Add support for webview2
|
27
|
+
|
28
|
+
4.9.1 (2023-05-08)
|
29
|
+
=========================
|
30
|
+
Ruby:
|
31
|
+
* Allow users to specify driver process output in Service class (#11964)
|
32
|
+
* Updated minimum required Ruby version to 3.0
|
33
|
+
* Selenium Logger defaults to :info and all debugging is now logged as :debug (#11967)
|
34
|
+
* Every logging entry can be ignored based on ID, not just warnings
|
35
|
+
* Logging entries can be filtered to allow or ignore specific IDs
|
36
|
+
|
37
|
+
BiDi:
|
38
|
+
* Fix bug with loading devtools (#11931) (thanks Boris Petrov!)
|
39
|
+
* Released selenium-devtools 0.113.0 (supports CDP v85, v111, v112, v113)
|
40
|
+
|
1
41
|
4.9.0 (2023-04-21)
|
2
42
|
=========================
|
3
43
|
Ruby:
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# selenium-webdriver
|
2
2
|
|
3
|
-
This gem provides Ruby bindings for Selenium and supports MRI >=
|
3
|
+
This gem provides Ruby bindings for Selenium and supports MRI >= 3.0.
|
4
4
|
|
5
5
|
## Install
|
6
6
|
|
@@ -15,7 +15,7 @@ This gem provides Ruby bindings for Selenium and supports MRI >= 2.6
|
|
15
15
|
|
16
16
|
## License
|
17
17
|
|
18
|
-
Copyright 2009-
|
18
|
+
Copyright 2009-2023 Software Freedom Conservancy
|
19
19
|
|
20
20
|
Licensed to the Software Freedom Conservancy (SFC) under one
|
21
21
|
or more contributor license agreements. See the NOTICE file
|
data/bin/linux/selenium-manager
CHANGED
Binary file
|
data/bin/macos/selenium-manager
CHANGED
Binary file
|
Binary file
|
data/lib/selenium/server.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
# under the License.
|
19
19
|
|
20
20
|
require 'selenium/webdriver/common/child_process'
|
21
|
+
require 'selenium/webdriver/common/port_prober'
|
21
22
|
require 'selenium/webdriver/common/socket_poller'
|
22
23
|
require 'net/http'
|
23
24
|
|
@@ -165,7 +166,7 @@ module Selenium
|
|
165
166
|
# :standalone, #hub, #node
|
166
167
|
#
|
167
168
|
|
168
|
-
attr_accessor :role, :port, :timeout, :background, :log
|
169
|
+
attr_accessor :role, :host, :port, :timeout, :background, :log
|
169
170
|
|
170
171
|
#
|
171
172
|
# @param [String] jar Path to the server jar.
|
@@ -185,7 +186,7 @@ module Selenium
|
|
185
186
|
@jar = jar
|
186
187
|
@host = '127.0.0.1'
|
187
188
|
@role = opts.fetch(:role, 'standalone')
|
188
|
-
@port = opts.fetch(:port, 4444)
|
189
|
+
@port = opts.fetch(:port, WebDriver::PortProber.above(4444))
|
189
190
|
@timeout = opts.fetch(:timeout, 30)
|
190
191
|
@background = opts.fetch(:background, false)
|
191
192
|
@additional_args = opts.fetch(:args, [])
|
@@ -207,12 +208,6 @@ module Selenium
|
|
207
208
|
end
|
208
209
|
|
209
210
|
def stop
|
210
|
-
begin
|
211
|
-
Net::HTTP.get(@host, '/selenium-server/driver/?cmd=shutDownSeleniumServer', @port)
|
212
|
-
rescue Errno::ECONNREFUSED
|
213
|
-
nil
|
214
|
-
end
|
215
|
-
|
216
211
|
stop_process if @process
|
217
212
|
poll_for_shutdown
|
218
213
|
|
@@ -234,13 +229,7 @@ module Selenium
|
|
234
229
|
private
|
235
230
|
|
236
231
|
def stop_process
|
237
|
-
|
238
|
-
|
239
|
-
begin
|
240
|
-
@process.poll_for_exit(5)
|
241
|
-
rescue WebDriver::ChildProcess::TimeoutError
|
242
|
-
@process.stop
|
243
|
-
end
|
232
|
+
@process.stop
|
244
233
|
rescue Errno::ECHILD
|
245
234
|
# already dead
|
246
235
|
ensure
|
@@ -254,7 +243,6 @@ module Selenium
|
|
254
243
|
args = ['-jar', @jar, @role, '--port', @port.to_s]
|
255
244
|
server_command = ['java'] + properties + args + @additional_args
|
256
245
|
cp = WebDriver::ChildProcess.build(*server_command)
|
257
|
-
WebDriver.logger.debug("Executing Process #{server_command}")
|
258
246
|
|
259
247
|
if @log.is_a?(String)
|
260
248
|
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);}
|
@@ -17,12 +17,10 @@
|
|
17
17
|
# specific language governing permissions and limitations
|
18
18
|
# under the License.
|
19
19
|
|
20
|
-
require 'selenium/webdriver/chromium/service'
|
21
|
-
|
22
20
|
module Selenium
|
23
21
|
module WebDriver
|
24
22
|
module Chrome
|
25
|
-
class Service <
|
23
|
+
class Service < WebDriver::Service
|
26
24
|
DEFAULT_PORT = 9515
|
27
25
|
EXECUTABLE = 'chromedriver'
|
28
26
|
SHUTDOWN_SUPPORTED = true
|
@@ -159,24 +159,6 @@ module Selenium
|
|
159
159
|
@options[:prefs][name] = value
|
160
160
|
end
|
161
161
|
|
162
|
-
#
|
163
|
-
# Run Chrome in headless mode.
|
164
|
-
# Old headless uses a non-production browser and is set with `--headless`
|
165
|
-
# Native headless from v86 - v108 is set with `--headless=chrome`
|
166
|
-
# Native headless from v109+ is set with `--headless=new`
|
167
|
-
#
|
168
|
-
# @example Enable headless mode
|
169
|
-
# options = Selenium::WebDriver::Chrome::Options.new
|
170
|
-
# options.headless!
|
171
|
-
#
|
172
|
-
|
173
|
-
def headless!
|
174
|
-
WebDriver.logger.deprecate('`Options#headless!`',
|
175
|
-
"`Options#add_argument('--headless=new')`",
|
176
|
-
id: :headless)
|
177
|
-
add_argument '--headless'
|
178
|
-
end
|
179
|
-
|
180
162
|
#
|
181
163
|
# Add emulation device information
|
182
164
|
#
|
@@ -26,7 +26,6 @@ module Selenium
|
|
26
26
|
autoload :Driver, 'selenium/webdriver/chromium/driver'
|
27
27
|
autoload :Profile, 'selenium/webdriver/chromium/profile'
|
28
28
|
autoload :Options, 'selenium/webdriver/chromium/options'
|
29
|
-
autoload :Service, 'selenium/webdriver/chromium/service'
|
30
29
|
end # Chromium
|
31
30
|
end # WebDriver
|
32
31
|
end # Selenium
|
@@ -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?
|
@@ -81,20 +81,20 @@ module Selenium
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def exited?
|
84
|
-
return unless @pid
|
84
|
+
return false 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
|
-
return if @status.nil?
|
88
|
+
return false 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
|
@@ -23,19 +23,21 @@ module Selenium
|
|
23
23
|
def self.path(options, klass)
|
24
24
|
path = klass.driver_path
|
25
25
|
path = path.call if path.is_a?(Proc)
|
26
|
-
path ||= Platform.find_binary(klass::EXECUTABLE)
|
27
26
|
|
28
27
|
path ||= begin
|
29
|
-
SeleniumManager.driver_path(options)
|
28
|
+
SeleniumManager.driver_path(options) unless options.is_a?(Remote::Capabilities)
|
30
29
|
rescue StandardError => e
|
31
|
-
|
32
|
-
|
30
|
+
raise Error::NoSuchDriverError, "Unable to obtain #{klass::EXECUTABLE} using Selenium Manager; #{e.message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
Platform.assert_executable(path)
|
35
|
+
rescue TypeError
|
36
|
+
raise Error::NoSuchDriverError, "Unable to locate or obtain #{klass::EXECUTABLE}"
|
37
|
+
rescue Error::WebDriverError => e
|
38
|
+
raise Error::NoSuchDriverError, "#{klass::EXECUTABLE} located, but: #{e.message}"
|
33
39
|
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
40
|
|
38
|
-
Platform.assert_executable path
|
39
41
|
path
|
40
42
|
end
|
41
43
|
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
|
@@ -86,12 +86,6 @@ module Selenium
|
|
86
86
|
|
87
87
|
def add_option(name, value = nil)
|
88
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
89
|
@options[name] = value
|
96
90
|
end
|
97
91
|
|
@@ -113,24 +107,11 @@ module Selenium
|
|
113
107
|
w3c_options = process_w3c_options(options)
|
114
108
|
|
115
109
|
browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
|
116
|
-
|
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
|
-
|
110
|
+
capability_value = options.delete(capability_alias)
|
126
111
|
hash[capability_name] = capability_value unless capability_value.nil?
|
127
112
|
end
|
128
113
|
|
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}")
|
132
|
-
browser_options.merge!(options)
|
133
|
-
end
|
114
|
+
raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?
|
134
115
|
|
135
116
|
browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
|
136
117
|
|
@@ -145,7 +126,7 @@ module Selenium
|
|
145
126
|
end
|
146
127
|
|
147
128
|
def process_w3c_options(options)
|
148
|
-
w3c_options = options.select { |key,
|
129
|
+
w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
|
149
130
|
w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
|
150
131
|
options.delete_if { |key, _val| w3c?(key) }
|
151
132
|
w3c_options
|