selenium-webdriver 4.9.1 → 4.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +27 -0
  3. data/README.md +1 -1
  4. data/bin/linux/selenium-manager +0 -0
  5. data/bin/macos/selenium-manager +0 -0
  6. data/bin/windows/selenium-manager.exe +0 -0
  7. data/lib/selenium/server.rb +4 -16
  8. data/lib/selenium/webdriver/atoms/findElements.js +3 -4
  9. data/lib/selenium/webdriver/chrome/service.rb +1 -3
  10. data/lib/selenium/webdriver/chromium/options.rb +0 -18
  11. data/lib/selenium/webdriver/chromium.rb +0 -1
  12. data/lib/selenium/webdriver/common/child_process.rb +2 -2
  13. data/lib/selenium/webdriver/common/driver_finder.rb +10 -9
  14. data/lib/selenium/webdriver/common/error.rb +28 -3
  15. data/lib/selenium/webdriver/common/logger.rb +21 -8
  16. data/lib/selenium/webdriver/common/options.rb +3 -22
  17. data/lib/selenium/webdriver/common/platform.rb +0 -49
  18. data/lib/selenium/webdriver/common/proxy.rb +1 -1
  19. data/lib/selenium/webdriver/common/selenium_manager.rb +49 -26
  20. data/lib/selenium/webdriver/common/service.rb +1 -11
  21. data/lib/selenium/webdriver/common/websocket_connection.rb +1 -1
  22. data/lib/selenium/webdriver/edge/options.rb +14 -0
  23. data/lib/selenium/webdriver/edge/service.rb +1 -3
  24. data/lib/selenium/webdriver/firefox/options.rb +0 -15
  25. data/lib/selenium/webdriver/firefox/service.rb +0 -12
  26. data/lib/selenium/webdriver/ie/options.rb +2 -1
  27. data/lib/selenium/webdriver/ie/service.rb +0 -16
  28. data/lib/selenium/webdriver/remote/capabilities.rb +0 -72
  29. data/lib/selenium/webdriver/remote/http/default.rb +1 -2
  30. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  31. data/lib/selenium/webdriver/safari/service.rb +10 -0
  32. data/lib/selenium/webdriver/version.rb +1 -1
  33. data/selenium-webdriver.gemspec +1 -0
  34. metadata +16 -3
  35. data/lib/selenium/webdriver/chromium/service.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 382f56851a268a1f44ed42a9a0ec85d5136540df32711606657bf8961a95b6b1
4
- data.tar.gz: edbf74e77ed56b92fe01cfe6493b8db901ebc7cdb3df9b4d561f03cb5a91dcda
3
+ metadata.gz: 55c2b164be56b90064957852c6b1f890f9cda063d5c0ef164752b7c67f6e40bb
4
+ data.tar.gz: 778d0c6d2450a3d178d709762c76b9ef2c24832131d4487f6c84b5789a32b1de
5
5
  SHA512:
6
- metadata.gz: 84260d58d81b2be75717e10d597bdeaf7c7b36bec5483d664fe19a6c5891967a176ef26d8806ea160a4f229b051d1ede4fa20d244e4b0c08f8409ccac8f640ca
7
- data.tar.gz: 40af1b4e6fa0f6a85b608ce485336b0b7ba10ad35e7c8749c81c78808ba506d5a6294933b5771b3b5cb413f2b57b447af62dd236ce3e6ca4ed25f1949cc07bf6
6
+ metadata.gz: 6777b04b259f2e7be27d7c2635f77b0e9006464f931e1e79a1e10f517474b71344534a8b02ba84445801581f4c50cb79901d15ef8e74133c08357625e5ad9de6
7
+ data.tar.gz: 5f1e3af40a4bbcc3e4e77407321d64b1e6920ca91fcf7605bce780d42138fd587bfc951563205d8cf6e4b63952e7e4e35dd52aba496fcb1e468e6a086c81c92d
data/CHANGES CHANGED
@@ -1,3 +1,30 @@
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
+
1
28
  4.9.1 (2023-05-08)
2
29
  =========================
3
30
  Ruby:
data/README.md CHANGED
@@ -15,7 +15,7 @@ This gem provides Ruby bindings for Selenium and supports MRI >= 3.0.
15
15
 
16
16
  ## License
17
17
 
18
- Copyright 2009-2021 Software Freedom Conservancy
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
Binary file
Binary file
Binary file
@@ -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
- return unless @process.alive?
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}", id: :server)
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=100);return function(d){var e=Z.u(a);if(e===d)return!1;e=
117
- W(e);d=W(d);var f=Math.abs(e.a+e.width-d.a),g=Math.abs(e.b+e.height-d.b);g=Math.abs(e.b-(d.b+d.height))<=c||g<=c;return(Math.abs(e.a-(d.a+d.width))<=c||f<=c)&&g?!0:Math.sqrt(Math.pow(Math.abs(e.a+e.width/2-(d.a+d.width/2)),2)+Math.pow(Math.abs(e.b+e.height/2-(d.b+d.height/2)),2))<=c}},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: "+
118
- 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));}};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};
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 < Chromium::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
@@ -81,11 +81,11 @@ module Selenium
81
81
  end
82
82
 
83
83
  def exited?
84
- return unless @pid
84
+ return false unless @pid
85
85
 
86
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
91
  WebDriver.logger.debug(" -> exit code is #{exit_code.inspect}", id: :process)
@@ -23,20 +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
- WebDriver.logger.warn("Unable to obtain driver using Selenium Manager\n #{e.message}",
32
- id: :selenium_manager)
33
- nil
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}"
34
39
  end
35
- msg = "Unable to locate the #{klass::EXECUTABLE} executable; for more information on how to install drivers, " \
36
- 'see https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/'
37
- raise Error::WebDriverError, msg unless path
38
40
 
39
- Platform.assert_executable path
40
41
  path
41
42
  end
42
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; end
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; end
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; end
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
@@ -41,7 +41,7 @@ module Selenium
41
41
  :debug?,
42
42
  :info?,
43
43
  :warn?,
44
- :error, :error?,
44
+ :error?,
45
45
  :fatal, :fatal?,
46
46
  :level
47
47
 
@@ -127,16 +127,20 @@ module Selenium
127
127
  # @yield see #deprecate
128
128
  #
129
129
  def info(message, id: [], &block)
130
- unless @first_warning
131
- @first_warning = true
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"
134
- end
135
- end
136
-
137
130
  discard_or_log(:info, message, id, &block)
138
131
  end
139
132
 
133
+ #
134
+ # Used to supply information that suggests an error occurred
135
+ #
136
+ # @param [String] message
137
+ # @param [Symbol, Array<Sybmol>] id
138
+ # @yield see #deprecate
139
+ #
140
+ def error(message, id: [], &block)
141
+ discard_or_log(:error, message, id, &block)
142
+ end
143
+
140
144
  #
141
145
  # Used to supply information that suggests action be taken by user
142
146
  #
@@ -192,6 +196,15 @@ module Selenium
192
196
  return if (@ignored & id).any?
193
197
  return if @allowed.any? && (@allowed & id).none?
194
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
+
195
208
  msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
196
209
  msg += " #{yield}" if block_given?
197
210
 
@@ -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
- from_name = options.delete(capability_name)
117
- from_alias = options.delete(capability_alias)
118
- capability_value = if !from_name.nil? && capability_alias != capability_name
119
- WebDriver.logger.deprecate("#{capability_name} as option",
120
- capability_alias.to_s, id: :option_symbols)
121
- from_name
122
- elsif !from_alias.nil?
123
- from_alias
124
- end
125
-
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}", id: :w3c_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, _val| w3c?(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
@@ -62,18 +62,6 @@ module Selenium
62
62
  end
63
63
  end
64
64
 
65
- def bitsize
66
- @bitsize ||= if defined?(FFI::Platform::ADDRESS_SIZE)
67
- FFI::Platform::ADDRESS_SIZE
68
- elsif defined?(FFI)
69
- FFI.type_size(:pointer) == 4 ? 32 : 64
70
- elsif jruby?
71
- Integer(ENV_JAVA['sun.arch.data.model'])
72
- else
73
- 1.size == 4 ? 32 : 64
74
- end
75
- end
76
-
77
65
  def jruby?
78
66
  engine == :jruby
79
67
  end
@@ -158,43 +146,6 @@ module Selenium
158
146
  at_exit { yield if Process.pid == pid }
159
147
  end
160
148
 
161
- def find_binary(*binary_names)
162
- paths = ENV['PATH'].split(File::PATH_SEPARATOR)
163
-
164
- if windows?
165
- binary_names.map! { |n| "#{n}.exe" }
166
- binary_names.dup.each { |n| binary_names << n.gsub('exe', 'bat') }
167
- end
168
-
169
- binary_names.each do |binary_name|
170
- paths.each do |path|
171
- full_path = File.join(path, binary_name)
172
- full_path = unix_path(full_path) if windows?
173
- exe = Dir.glob(full_path).find { |f| File.executable?(f) }
174
- return exe if exe
175
- end
176
- end
177
-
178
- nil
179
- end
180
-
181
- def find_in_program_files(*binary_names)
182
- paths = [
183
- ENV.fetch('PROGRAMFILES', '\\Program Files'),
184
- ENV.fetch('ProgramFiles(x86)', '\\Program Files (x86)'),
185
- ENV.fetch('ProgramW6432', '\\Program Files')
186
- ]
187
-
188
- paths.each do |root|
189
- binary_names.each do |name|
190
- exe = File.join(root, name)
191
- return exe if File.executable?(exe)
192
- end
193
- end
194
-
195
- nil
196
- end
197
-
198
149
  def localhost
199
150
  info = Socket.getaddrinfo 'localhost', 80, Socket::AF_INET, Socket::SOCK_STREAM
200
151
 
@@ -152,7 +152,7 @@ module Selenium
152
152
  'socksUsername' => socks_username,
153
153
  'socksPassword' => socks_password,
154
154
  'socksVersion' => socks_version
155
- }.delete_if { |_k, v| v.nil? }
155
+ }.compact
156
156
 
157
157
  json_result if json_result.length > 1
158
158
  end
@@ -27,20 +27,36 @@ 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 (Beta)'
37
- WebDriver.logger.info(message, id: :selenium_manager)
40
+ command = generate_command(binary, options)
41
+
42
+ output = run(*command)
43
+
44
+ browser_path = output['browser_path']
45
+ driver_path = output['driver_path']
46
+ Platform.assert_executable driver_path
38
47
 
39
- unless options.is_a?(Options)
40
- raise ArgumentError, "SeleniumManager requires a WebDriver::Options instance, not #{options.inspect}"
48
+ if options.respond_to? :binary
49
+ options.binary = browser_path
50
+ options.browser_version = nil
41
51
  end
42
52
 
43
- command = [binary, '--browser', options.browser_name, '--output', 'json']
53
+ driver_path
54
+ end
55
+
56
+ private
57
+
58
+ def generate_command(binary, options)
59
+ command = [binary, '--browser', options.browser_name]
44
60
  if options.browser_version
45
61
  command << '--browser-version'
46
62
  command << options.browser_version
@@ -49,21 +65,17 @@ module Selenium
49
65
  command << '--browser-path'
50
66
  command << options.binary.gsub('\\', '\\\\\\')
51
67
  end
52
- command << '--debug' if WebDriver.logger.debug?
53
-
54
- location = run(*command)
55
- WebDriver.logger.debug("Driver found at #{location}", id: :selenium_manager)
56
- Platform.assert_executable location
57
-
58
- location
68
+ if options.proxy
69
+ command << '--proxy'
70
+ (command << options.proxy.ssl) || options.proxy.http
71
+ end
72
+ command
59
73
  end
60
74
 
61
- private
62
-
63
75
  # @return [String] the path to the correct selenium manager
64
76
  def binary
65
77
  @binary ||= begin
66
- path = File.expand_path(BIN_PATH, __FILE__)
78
+ path = File.expand_path(bin_path, __FILE__)
67
79
  path << if Platform.windows?
68
80
  '/windows/selenium-manager.exe'
69
81
  elsif Platform.mac?
@@ -72,32 +84,43 @@ module Selenium
72
84
  '/linux/selenium-manager'
73
85
  end
74
86
  location = File.expand_path(path, __FILE__)
75
- unless location.is_a?(String) && File.exist?(location) && File.executable?(location)
76
- raise Error::WebDriverError, 'Unable to obtain Selenium Manager'
87
+
88
+ begin
89
+ Platform.assert_file(location)
90
+ Platform.assert_executable(location)
91
+ rescue TypeError
92
+ raise Error::WebDriverError,
93
+ "Unable to locate or obtain Selenium Manager binary; #{location} is not a valid file object"
94
+ rescue Error::WebDriverError => e
95
+ raise Error::WebDriverError, "Selenium Manager binary located, but #{e.message}"
77
96
  end
78
97
 
79
- WebDriver.logger.debug("Selenium Manager found at #{location}", id: :selenium_manager)
98
+ WebDriver.logger.debug("Selenium Manager binary found at #{location}", id: :selenium_manager)
80
99
  location
81
100
  end
82
101
  end
83
102
 
84
103
  def run(*command)
104
+ command += %w[--output json]
105
+ command << '--debug' if WebDriver.logger.debug?
106
+
85
107
  WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
86
108
 
87
109
  begin
88
110
  stdout, stderr, status = Open3.capture3(*command)
89
111
  json_output = stdout.empty? ? nil : JSON.parse(stdout)
90
- result = json_output&.dig('result', 'message')
112
+ result = json_output['result']
91
113
  rescue StandardError => e
92
- raise Error::WebDriverError, "Unsuccessful command executed: #{command}", e.message
114
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
93
115
  end
94
116
 
95
- if status.exitstatus.positive?
96
- raise Error::WebDriverError, "Unsuccessful command executed: #{command}\n#{result}#{stderr}"
117
+ (json_output&.fetch('logs') || []).each do |log|
118
+ level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
119
+ WebDriver.logger.send(level, log['message'], id: :selenium_manager)
97
120
  end
98
121
 
99
- json_output['logs'].each do |log|
100
- WebDriver.logger.send(log['level'].downcase, log['message'], id: :selenium_manager)
122
+ if status.exitstatus.positive?
123
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}\n#{result}#{stderr}"
101
124
  end
102
125
 
103
126
  result
@@ -81,8 +81,7 @@ module Selenium
81
81
  else
82
82
  log
83
83
  end
84
-
85
- @args = args.is_a?(Hash) ? extract_service_args(args) : args
84
+ @args = args
86
85
 
87
86
  raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
88
87
  end
@@ -94,15 +93,6 @@ module Selenium
94
93
  def shutdown_supported
95
94
  self.class::SHUTDOWN_SUPPORTED
96
95
  end
97
-
98
- protected
99
-
100
- def extract_service_args(driver_opts)
101
- WebDriver.logger.deprecate('initializing Service class with :args using Hash',
102
- ':args parameter with an Array of String values',
103
- id: :driver_opts)
104
- driver_opts.key?(:args) ? driver_opts.delete(:args) : []
105
- end
106
96
  end # Service
107
97
  end # WebDriver
108
98
  end # Selenium
@@ -129,7 +129,7 @@ module Selenium
129
129
  Thread.current.report_on_exception = true
130
130
 
131
131
  yield params
132
- rescue *CONNECTION_ERRORS
132
+ rescue Error::WebDriverError, *CONNECTION_ERRORS
133
133
  Thread.stop
134
134
  end
135
135
  end
@@ -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)
@@ -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 Edge
25
- class Service < Chromium::Service
23
+ class Service < WebDriver::Service
26
24
  DEFAULT_PORT = 9515
27
25
  EXECUTABLE = 'msedgedriver'
28
26
  SHUTDOWN_SUPPORTED = true
@@ -99,21 +99,6 @@ module Selenium
99
99
  @options[:prefs][name] = value
100
100
  end
101
101
 
102
- #
103
- # Run Firefox in headless mode.
104
- #
105
- # @example Enable headless mode
106
- # options = Selenium::WebDriver::Firefox::Options.new
107
- # options.headless!
108
- #
109
-
110
- def headless!
111
- WebDriver.logger.deprecate('`Options#headless!`',
112
- "`Options#add_argument('-headless')`",
113
- id: :headless)
114
- add_argument '-headless'
115
- end
116
-
117
102
  #
118
103
  # Sets Firefox profile.
119
104
  #
@@ -24,18 +24,6 @@ module Selenium
24
24
  DEFAULT_PORT = 4444
25
25
  EXECUTABLE = 'geckodriver'
26
26
  SHUTDOWN_SUPPORTED = false
27
-
28
- private
29
-
30
- def extract_service_args(driver_opts)
31
- driver_args = super
32
- driver_opts = driver_opts.dup
33
- driver_args << "--binary=#{driver_opts[:binary]}" if driver_opts.key?(:binary)
34
- driver_args << "--log=#{driver_opts[:log]}" if driver_opts.key?(:log)
35
- driver_args << "--marionette-port=#{driver_opts[:marionette_port]}" if driver_opts.key?(:marionette_port)
36
- driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
37
- driver_args
38
- end
39
27
  end # Service
40
28
  end # Firefox
41
29
  end # WebDriver
@@ -41,7 +41,8 @@ module Selenium
41
41
  use_per_process_proxy: 'ie.usePerProcessProxy',
42
42
  use_legacy_file_upload_dialog_handling: 'ie.useLegacyFileUploadDialogHandling',
43
43
  attach_to_edge_chrome: 'ie.edgechromium',
44
- edge_executable_path: 'ie.edgepath'
44
+ edge_executable_path: 'ie.edgepath',
45
+ ignore_process_match: 'ie.ignoreprocessmatch'
45
46
  }.freeze
46
47
  BROWSER = 'internet explorer'
47
48
 
@@ -24,22 +24,6 @@ module Selenium
24
24
  DEFAULT_PORT = 5555
25
25
  EXECUTABLE = 'IEDriverServer'
26
26
  SHUTDOWN_SUPPORTED = true
27
-
28
- private
29
-
30
- def extract_service_args(driver_opts)
31
- driver_args = super
32
- driver_opts = driver_opts.dup
33
- driver_args << "--log-level=#{driver_opts[:log_level].to_s.upcase}" if driver_opts.key?(:log_level)
34
- driver_args << "--log-file=#{driver_opts[:log_file]}" if driver_opts.key?(:log_file)
35
- if driver_opts.key?(:implementation)
36
- driver_args << "--implementation=#{driver_opts[:implementation].to_s.upcase}"
37
- end
38
- driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
39
- driver_args << "--extract_path=#{driver_opts[:extract_path]}" if driver_opts.key?(:extract_path)
40
- driver_args << '--silent' if driver_opts[:silent] == true
41
- driver_args
42
- end
43
27
  end # Server
44
28
  end # IE
45
29
  end # WebDriver
@@ -53,83 +53,11 @@ module Selenium
53
53
  end
54
54
  end
55
55
 
56
- #
57
- # Backward compatibility
58
- #
59
-
60
- def version
61
- WebDriver.logger.deprecate('`Capabilities#version`', '`Capabilities#browser_version`', id: :jwp_caps)
62
- browser_version
63
- end
64
-
65
- def version=(value)
66
- WebDriver.logger.deprecate('`Capabilities#version=`', '`Capabilities#browser_version=`', id: :jwp_caps)
67
- self.browser_version = value
68
- end
69
-
70
- def platform
71
- WebDriver.logger.deprecate('`Capabilities#platform`', '`Capabilities#platform_name`', id: :jwp_caps)
72
- platform_name
73
- end
74
-
75
- def platform=(value)
76
- WebDriver.logger.deprecate('`Capabilities#platform=`', '`Capabilities#platform_name=`', id: :jwp_caps)
77
- self.platform_name = value
78
- end
79
-
80
56
  #
81
57
  # Convenience methods for the common choices.
82
58
  #
83
59
 
84
60
  class << self
85
- def chrome(opts = {})
86
- WebDriver.logger.deprecate('Remote::Capabilities.chrome', 'Options.chrome', id: :caps_browsers)
87
- new({
88
- browser_name: 'chrome'
89
- }.merge(opts))
90
- end
91
-
92
- def edge(opts = {})
93
- WebDriver.logger.deprecate('Remote::Capabilities.edge', 'Options.edge', id: :caps_browsers)
94
- new({
95
- browser_name: 'MicrosoftEdge'
96
- }.merge(opts))
97
- end
98
- alias microsoftedge edge
99
-
100
- def firefox(opts = {})
101
- WebDriver.logger.deprecate('Remote::Capabilities.firefox', 'Options.firefox', id: :caps_browsers)
102
- new({
103
- browser_name: 'firefox'
104
- }.merge(opts))
105
- end
106
- alias ff firefox
107
-
108
- def safari(opts = {})
109
- WebDriver.logger.deprecate('Remote::Capabilities.safari', 'Options.safari', id: :caps_browsers)
110
- new({
111
- browser_name: Selenium::WebDriver::Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
112
- }.merge(opts))
113
- end
114
-
115
- def htmlunit(opts = {})
116
- WebDriver.logger.deprecate('Remote::Capabilities.htmlunit',
117
- 'as argument in constructor',
118
- id: :caps_browsers)
119
- new({
120
- browser_name: 'htmlunit'
121
- }.merge(opts))
122
- end
123
-
124
- def internet_explorer(opts = {})
125
- WebDriver.logger.deprecate('Remote::Capabilities.ie', 'Options.ie', id: :caps_browsers)
126
- new({
127
- browser_name: 'internet explorer',
128
- platform_name: :windows
129
- }.merge(opts))
130
- end
131
- alias ie internet_explorer
132
-
133
61
  def always_match(capabilities)
134
62
  new(always_match: capabilities)
135
63
  end
@@ -16,8 +16,6 @@
16
16
  # KIND, either express or implied. See the License for the
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
-
20
- require 'net/https'
21
19
  require 'ipaddr'
22
20
 
23
21
  module Selenium
@@ -96,6 +94,7 @@ module Selenium
96
94
  end
97
95
 
98
96
  if response.is_a? Net::HTTPRedirection
97
+ WebDriver.logger.debug("Redirect to #{response['Location']}; times: #{redirects}")
99
98
  raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
100
99
 
101
100
  request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
@@ -25,7 +25,7 @@ module Selenium
25
25
  if response.is_a? String
26
26
  super(response)
27
27
  else
28
- super("status code #{response.code}")
28
+ super("status code #{response.code}; payload #{response.payload}")
29
29
  end
30
30
  end
31
31
  end # ServerError
@@ -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
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.9.1'
22
+ VERSION = '4.11.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -54,6 +54,7 @@ Gem::Specification.new do |s|
54
54
  s.add_runtime_dependency 'websocket', ['~> 1.0']
55
55
 
56
56
  s.add_development_dependency 'rack', ['~> 2.0']
57
+ s.add_development_dependency 'rake', ['~> 13.0']
57
58
  s.add_development_dependency 'rspec', ['~> 3.0']
58
59
  s.add_development_dependency 'rubocop', ['~> 1.42']
59
60
  s.add_development_dependency 'rubocop-performance', ['~> 1.15']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.9.1
4
+ version: 4.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rodionov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-05-08 00:00:00.000000000 Z
13
+ date: 2023-07-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rexml
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '13.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '13.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -228,7 +242,6 @@ files:
228
242
  - lib/selenium/webdriver/chromium/features.rb
229
243
  - lib/selenium/webdriver/chromium/options.rb
230
244
  - lib/selenium/webdriver/chromium/profile.rb
231
- - lib/selenium/webdriver/chromium/service.rb
232
245
  - lib/selenium/webdriver/common.rb
233
246
  - lib/selenium/webdriver/common/action_builder.rb
234
247
  - lib/selenium/webdriver/common/alert.rb
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Licensed to the Software Freedom Conservancy (SFC) under one
4
- # or more contributor license agreements. See the NOTICE file
5
- # distributed with this work for additional information
6
- # regarding copyright ownership. The SFC licenses this file
7
- # to you under the Apache License, Version 2.0 (the
8
- # "License"); you may not use this file except in compliance
9
- # with the License. You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing,
14
- # software distributed under the License is distributed on an
15
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
- # KIND, either express or implied. See the License for the
17
- # specific language governing permissions and limitations
18
- # under the License.
19
-
20
- module Selenium
21
- module WebDriver
22
- module Chromium
23
- class Service < WebDriver::Service
24
- protected
25
-
26
- def extract_service_args(driver_opts)
27
- driver_args = super
28
- driver_opts = driver_opts.dup
29
- driver_args << "--log-path=#{driver_opts.delete(:log_path)}" if driver_opts.key?(:log_path)
30
- driver_args << "--url-base=#{driver_opts.delete(:url_base)}" if driver_opts.key?(:url_base)
31
- driver_args << "--port-server=#{driver_opts.delete(:port_server)}" if driver_opts.key?(:port_server)
32
- if driver_opts.key?(:whitelisted_ips)
33
- driver_args << "--whitelisted-ips=#{driver_opts.delete(:whitelisted_ips)}"
34
- end
35
- driver_args << '--verbose' if driver_opts.key?(:verbose)
36
- driver_args << '--silent' if driver_opts.key?(:silent)
37
- driver_args
38
- end
39
- end # Service
40
- end # Chromium
41
- end # WebDriver
42
- end # Selenium