selenium-webdriver 4.9.2 → 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.
@@ -22,38 +22,23 @@
22
22
  */
23
23
 
24
24
  const { driverLocation } = require('./seleniumManager')
25
- const fs = require('fs')
26
25
 
27
26
  /**
28
27
  * Determines the path of the correct Selenium Manager binary
29
- * @returns {string}
28
+ * @returns {{browserPath: string, driverPath: string}} path of the driver
29
+ * and browser location
30
30
  */
31
- function getPath(service, capabilities) {
31
+ function getPath(capabilities) {
32
32
  try {
33
- return pathExists(service.getExecutable()) || driverLocation(capabilities)
33
+ return driverLocation(capabilities)
34
34
  } catch (e) {
35
- throw Error(
36
- `Unable to obtain browser driver.
35
+ throw Error(
36
+ `Unable to obtain browser driver.
37
37
  For more information on how to install drivers see
38
- https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/. ${e}`
39
- )
38
+ https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location/. ${e}`
39
+ )
40
40
  }
41
41
  }
42
42
 
43
- /**
44
- * _Synchronously_ attempts to locate the driver executable on the current
45
- * system.
46
- *
47
- * @param {!string} driverPath
48
- *
49
- * @return {?string} the located executable, or `null`.
50
- */
51
- function pathExists(driverPath) {
52
- if (!driverPath || !fs.existsSync(driverPath)) {
53
- return null
54
- }
55
- return driverPath
56
- }
57
-
58
43
  // PUBLIC API
59
44
  module.exports = { getPath }
@@ -26,11 +26,7 @@ const path = require('path')
26
26
  const fs = require('fs')
27
27
  const spawnSync = require('child_process').spawnSync
28
28
 
29
- /**
30
- * currently supported browsers for selenium-manager
31
- * @type {string[]}
32
- */
33
- const Browser = ['chrome', 'firefox', 'edge', 'MicrosoftEdge', 'iexplorer']
29
+ let debugMessagePrinted = false;
34
30
 
35
31
  /**
36
32
  * Determines the path of the correct Selenium Manager binary
@@ -47,12 +43,7 @@ function getBinary() {
47
43
  const file =
48
44
  directory === 'windows' ? 'selenium-manager.exe' : 'selenium-manager'
49
45
 
50
- let seleniumManagerBasePath
51
- if (process.env.SELENIUM_MANAGER_BASE_PATH) {
52
- seleniumManagerBasePath = process.env.SELENIUM_MANAGER_BASE_PATH
53
- } else {
54
- seleniumManagerBasePath = path.join(__dirname, '..', '/bin')
55
- }
46
+ let seleniumManagerBasePath = path.join(__dirname, '..', '/bin')
56
47
 
57
48
  const filePath = path.join(seleniumManagerBasePath, directory, file)
58
49
 
@@ -60,32 +51,50 @@ function getBinary() {
60
51
  throw new Error(`Unable to obtain Selenium Manager`)
61
52
  }
62
53
 
54
+ if (!debugMessagePrinted) {
55
+ console.debug(`Selenium Manager binary found at ${filePath}`)
56
+ debugMessagePrinted = true; // Set the flag to true after printing the debug message
57
+ }
58
+
63
59
  return filePath
64
60
  }
65
61
 
66
62
  /**
67
63
  * Determines the path of the correct driver
68
64
  * @param {Capabilities} options browser options to fetch the driver
69
- * @returns {string} path of the driver location
65
+ * @returns {{browserPath: string, driverPath: string}} path of the driver and
66
+ * browser location
70
67
  */
71
68
 
72
69
  function driverLocation(options) {
73
- if (!Browser.includes(options.getBrowserName().toLocaleString())) {
74
- throw new Error(
75
- `Unable to locate driver associated with browser name: ${options.getBrowserName()}`
76
- )
77
- }
78
-
79
70
  let args = ['--browser', options.getBrowserName(), '--output', 'json']
80
71
 
81
- if (options.getBrowserVersion() && options.getBrowserVersion() !== "") {
82
- args.push("--browser-version", options.getBrowserVersion())
72
+ if (options.getBrowserVersion() && options.getBrowserVersion() !== '') {
73
+ args.push('--browser-version', options.getBrowserVersion())
83
74
  }
84
75
 
85
- const vendorOptions = options.get('goog:chromeOptions') || options.get('ms:edgeOptions')
86
- || options.get('moz:firefoxOptions')
87
- if (vendorOptions && vendorOptions.binary && vendorOptions.binary !== "") {
88
- args.push("--browser-path", '"' + vendorOptions.binary + '"')
76
+ const vendorOptions =
77
+ options.get('goog:chromeOptions') ||
78
+ options.get('ms:edgeOptions') ||
79
+ options.get('moz:firefoxOptions')
80
+ if (vendorOptions && vendorOptions.binary && vendorOptions.binary !== '') {
81
+ args.push('--browser-path', '"' + vendorOptions.binary + '"')
82
+ }
83
+
84
+ const proxyOptions = options.getProxy();
85
+
86
+ // Check if proxyOptions exists and has properties
87
+ if (proxyOptions && Object.keys(proxyOptions).length > 0) {
88
+ const httpProxy = proxyOptions['httpProxy'];
89
+ const sslProxy = proxyOptions['sslProxy'];
90
+
91
+ if (httpProxy !== undefined) {
92
+ args.push('--proxy', httpProxy);
93
+ }
94
+
95
+ else if (sslProxy !== undefined) {
96
+ args.push('--proxy', sslProxy);
97
+ }
89
98
  }
90
99
 
91
100
  const smBinary = getBinary()
@@ -99,27 +108,40 @@ function driverLocation(options) {
99
108
  if (spawnResult.stdout.toString()) {
100
109
  try {
101
110
  output = JSON.parse(spawnResult.stdout.toString())
111
+ logOutput(output)
102
112
  errorMessage = output.result.message
103
113
  } catch (e) {
104
114
  errorMessage = e.toString()
105
115
  }
106
116
  }
107
- throw new Error(`Error executing command for ${smBinary} with ${args}: ${errorMessage}`)
117
+ throw new Error(
118
+ `Error executing command for ${smBinary} with ${args}: ${errorMessage}`
119
+ )
108
120
  }
109
121
  try {
110
122
  output = JSON.parse(spawnResult.stdout.toString())
111
123
  } catch (e) {
112
- throw new Error(`Error executing command for ${smBinary} with ${args}: ${e.toString()}`)
124
+ throw new Error(
125
+ `Error executing command for ${smBinary} with ${args}: ${e.toString()}`
126
+ )
113
127
  }
114
128
 
129
+ logOutput(output)
130
+ return {
131
+ driverPath: output.result.driver_path,
132
+ browserPath: output.result.browser_path,
133
+ }
134
+ }
115
135
 
136
+ function logOutput (output) {
116
137
  for (const key in output.logs) {
117
138
  if (output.logs[key].level === 'WARN') {
118
139
  console.warn(`${output.logs[key].message}`)
119
140
  }
141
+ if (['DEBUG', 'INFO'].includes(output.logs[key].level)) {
142
+ console.debug(`${output.logs[key].message}`)
143
+ }
120
144
  }
121
-
122
- return output.result.message
123
145
  }
124
146
 
125
147
  // PUBLIC API
package/edge.js CHANGED
@@ -78,16 +78,8 @@
78
78
  'use strict'
79
79
 
80
80
  const { Browser } = require('./lib/capabilities')
81
- const io = require('./io')
82
81
  const chromium = require('./chromium')
83
-
84
- /**
85
- * Name of the EdgeDriver executable.
86
- * @type {string}
87
- * @const
88
- */
89
- const EDGEDRIVER_CHROMIUM_EXE =
90
- process.platform === 'win32' ? 'msedgedriver.exe' : 'msedgedriver'
82
+ const EDGE_CAPABILITY_KEY = 'ms:edgeOptions'
91
83
 
92
84
  /** @type {remote.DriverService} */
93
85
 
@@ -105,8 +97,7 @@ class ServiceBuilder extends chromium.ServiceBuilder {
105
97
  * cannot be found on the PATH.
106
98
  */
107
99
  constructor(opt_exe) {
108
- let exe = opt_exe || locateSynchronously()
109
- super(exe)
100
+ super(opt_exe)
110
101
  this.setLoopback(true)
111
102
  }
112
103
  }
@@ -127,6 +118,19 @@ class Options extends chromium.Options {
127
118
  setEdgeChromiumBinaryPath(path) {
128
119
  return this.setBinaryPath(path)
129
120
  }
121
+
122
+ /**
123
+ * Changes the browser name to 'webview2' to enable
124
+ * <a href="https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/webdriver">
125
+ * test automation of WebView2 apps with Microsoft Edge WebDriver
126
+ * </a>
127
+ *
128
+ * @param {boolean} enable flag to enable or disable the 'webview2' usage
129
+ */
130
+ useWebView(enable) {
131
+ const browserName = enable ? 'webview2' : Browser.EDGE
132
+ return this.setBrowserName(browserName)
133
+ }
130
134
  }
131
135
 
132
136
  /**
@@ -144,7 +148,7 @@ class Driver extends chromium.Driver {
144
148
  static createSession(opt_config, opt_serviceExecutor) {
145
149
  let caps = opt_config || new Options()
146
150
  return /** @type {!Driver} */ (
147
- super.createSession(caps, opt_serviceExecutor)
151
+ super.createSession(caps, opt_serviceExecutor, 'ms', EDGE_CAPABILITY_KEY)
148
152
  )
149
153
  }
150
154
 
@@ -164,19 +168,8 @@ class Driver extends chromium.Driver {
164
168
  setFileDetector() {}
165
169
  }
166
170
 
167
- /**
168
- * _Synchronously_ attempts to locate the chromedriver executable on the current
169
- * system.
170
- *
171
- * @return {?string} the located executable, or `null`.
172
- */
173
- function locateSynchronously() {
174
- return io.findInPath(EDGEDRIVER_CHROMIUM_EXE, true)
175
- }
176
-
177
171
  Options.prototype.BROWSER_NAME_VALUE = Browser.EDGE
178
- Options.prototype.CAPABILITY_KEY = 'ms:edgeOptions'
179
- Driver.prototype.VENDOR_CAPABILITY_PREFIX = 'ms'
172
+ Options.prototype.CAPABILITY_KEY = EDGE_CAPABILITY_KEY
180
173
 
181
174
  // PUBLIC API
182
175
 
@@ -184,5 +177,4 @@ module.exports = {
184
177
  Driver,
185
178
  Options,
186
179
  ServiceBuilder,
187
- locateSynchronously,
188
180
  }
package/firefox.js CHANGED
@@ -128,6 +128,7 @@ const zip = require('./io/zip')
128
128
  const { Browser, Capabilities } = require('./lib/capabilities')
129
129
  const { Zip } = require('./io/zip')
130
130
  const { getPath } = require('./common/driverFinder')
131
+ const FIREFOX_CAPABILITY_KEY = 'moz:firefoxOptions'
131
132
 
132
133
  /**
133
134
  * Thrown when there an add-on is malformed.
@@ -263,10 +264,10 @@ class Options extends Capabilities {
263
264
  * @private
264
265
  */
265
266
  firefoxOptions_() {
266
- let options = this.get('moz:firefoxOptions')
267
+ let options = this.get(FIREFOX_CAPABILITY_KEY)
267
268
  if (!options) {
268
269
  options = {}
269
- this.set('moz:firefoxOptions', options)
270
+ this.set(FIREFOX_CAPABILITY_KEY, options)
270
271
  }
271
272
  return options
272
273
  }
@@ -453,27 +454,6 @@ const Context = {
453
454
  CHROME: 'chrome',
454
455
  }
455
456
 
456
- const GECKO_DRIVER_EXE =
457
- process.platform === 'win32' ? 'geckodriver.exe' : 'geckodriver'
458
-
459
- /**
460
- * _Synchronously_ attempts to locate the geckodriver executable on the current
461
- * system.
462
- *
463
- * @return {?string} the located executable, or `null`.
464
- */
465
- function locateSynchronously() {
466
- return io.findInPath(GECKO_DRIVER_EXE, true)
467
- }
468
-
469
- /**
470
- * @return {string} .
471
- * @throws {Error}
472
- */
473
- function findGeckoDriver() {
474
- return locateSynchronously()
475
- }
476
-
477
457
  /**
478
458
  * @param {string} file Path to the file to find, relative to the program files
479
459
  * root.
@@ -555,7 +535,7 @@ class ServiceBuilder extends remote.DriverService.Builder {
555
535
  * the builder will attempt to locate the geckodriver on the system PATH.
556
536
  */
557
537
  constructor(opt_exe) {
558
- super(opt_exe || findGeckoDriver())
538
+ super(opt_exe)
559
539
  this.setLoopback(true) // Required.
560
540
  }
561
541
 
@@ -601,6 +581,8 @@ class Driver extends webdriver.WebDriver {
601
581
  let caps =
602
582
  opt_config instanceof Capabilities ? opt_config : new Options(opt_config)
603
583
 
584
+ let firefoxBrowserPath = null
585
+
604
586
  let executor
605
587
  let onQuit
606
588
 
@@ -609,19 +591,33 @@ class Driver extends webdriver.WebDriver {
609
591
  configureExecutor(executor)
610
592
  } else if (opt_executor instanceof remote.DriverService) {
611
593
  if (!opt_executor.getExecutable()) {
612
- opt_executor.setExecutable(getPath(opt_executor, opt_config))
594
+ const {driverPath, browserPath} = getPath(caps)
595
+ opt_executor.setExecutable(driverPath)
596
+ firefoxBrowserPath = browserPath
613
597
  }
614
598
  executor = createExecutor(opt_executor.start())
615
599
  onQuit = () => opt_executor.kill()
616
600
  } else {
617
601
  let service = new ServiceBuilder().build()
618
602
  if (!service.getExecutable()) {
619
- service.setExecutable(getPath(service, opt_config))
603
+ const {driverPath, browserPath} = getPath(caps)
604
+ service.setExecutable(driverPath)
605
+ firefoxBrowserPath = browserPath
620
606
  }
621
607
  executor = createExecutor(service.start())
622
608
  onQuit = () => service.kill()
623
609
  }
624
610
 
611
+ if (firefoxBrowserPath) {
612
+ const vendorOptions = caps.get(FIREFOX_CAPABILITY_KEY)
613
+ if (vendorOptions) {
614
+ vendorOptions['binary'] = firefoxBrowserPath
615
+ caps.set(FIREFOX_CAPABILITY_KEY, vendorOptions)
616
+ } else {
617
+ caps.set(FIREFOX_CAPABILITY_KEY, {binary: firefoxBrowserPath})
618
+ }
619
+ }
620
+
625
621
  return /** @type {!Driver} */ (super.createSession(executor, caps, onQuit))
626
622
  }
627
623
 
@@ -832,5 +828,4 @@ module.exports = {
832
828
  Driver,
833
829
  Options,
834
830
  ServiceBuilder,
835
- locateSynchronously,
836
831
  }
package/ie.js CHANGED
@@ -27,9 +27,7 @@
27
27
 
28
28
  'use strict'
29
29
 
30
- const fs = require('fs')
31
30
  const http = require('./http')
32
- const io = require('./io')
33
31
  const portprober = require('./net/portprober')
34
32
  const remote = require('./remote')
35
33
  const webdriver = require('./lib/webdriver')
@@ -37,7 +35,6 @@ const { Browser, Capabilities } = require('./lib/capabilities')
37
35
  const error = require('./lib/error')
38
36
  const { getPath } = require('./common/driverFinder')
39
37
 
40
- const IEDRIVER_EXE = 'IEDriverServer.exe'
41
38
  const OPTIONS_CAPABILITY_KEY = 'se:ieOptions'
42
39
  const SCROLL_BEHAVIOUR = {
43
40
  BOTTOM: 1,
@@ -83,6 +80,7 @@ const Key = {
83
80
  FILE_UPLOAD_DIALOG_TIMEOUT: 'ie.fileUploadDialogTimeout',
84
81
  ATTACH_TO_EDGE_CHROMIUM: 'ie.edgechromium',
85
82
  EDGE_EXECUTABLE_PATH: 'ie.edgepath',
83
+ IGNORE_PROCESS_MATCH: 'ie.ignoreprocessmatch',
86
84
  }
87
85
 
88
86
  /**
@@ -379,16 +377,6 @@ class Options extends Capabilities {
379
377
  }
380
378
  }
381
379
 
382
- /**
383
- * _Synchronously_ attempts to locate the IE driver executable on the current
384
- * system.
385
- *
386
- * @return {?string} the located executable, or `null`.
387
- */
388
- function locateSynchronously() {
389
- return process.platform === 'win32' ? io.findInPath(IEDRIVER_EXE, true) : null
390
- }
391
-
392
380
  function createServiceFromCapabilities(capabilities) {
393
381
  if (process.platform !== 'win32') {
394
382
  throw Error(
@@ -399,7 +387,7 @@ function createServiceFromCapabilities(capabilities) {
399
387
  )
400
388
  }
401
389
 
402
- let exe = locateSynchronously()
390
+ let exe = null // Let Selenium Manager find it
403
391
  var args = []
404
392
  if (capabilities.has(Key.HOST)) {
405
393
  args.push('--host=' + capabilities.get(Key.HOST))
@@ -439,7 +427,7 @@ class ServiceBuilder extends remote.DriverService.Builder {
439
427
  * the builder will attempt to locate the IEDriverServer on the system PATH.
440
428
  */
441
429
  constructor(opt_exe) {
442
- super(opt_exe || IEDRIVER_EXE)
430
+ super(opt_exe)
443
431
  this.setLoopback(true) // Required.
444
432
  }
445
433
  }
@@ -467,7 +455,7 @@ class Driver extends webdriver.WebDriver {
467
455
  service = createServiceFromCapabilities(options)
468
456
  }
469
457
  if (!service.getExecutable()) {
470
- service.setExecutable(getPath(service, options))
458
+ service.setExecutable(getPath(options).driverPath)
471
459
  }
472
460
 
473
461
  let client = service.start().then((url) => new http.HttpClient(url))
@@ -495,4 +483,3 @@ exports.ServiceBuilder = ServiceBuilder
495
483
  exports.Key = Key
496
484
  exports.VENDOR_COMMAND_PREFIX = OPTIONS_CAPABILITY_KEY
497
485
  exports.Behavior = SCROLL_BEHAVIOUR
498
- exports.locateSynchronously = locateSynchronously
package/index.js CHANGED
@@ -43,6 +43,7 @@ const LogInspector = require('./bidi/logInspector')
43
43
  const BrowsingContext = require('./bidi/browsingContext')
44
44
  const BrowsingConextInspector = require('./bidi/browsingContextInspector')
45
45
  const ScriptManager = require('./bidi/scriptManager')
46
+ const NetworkInspector = require('./bidi/networkInspector')
46
47
 
47
48
  const Browser = capabilities.Browser
48
49
  const Capabilities = capabilities.Capabilities
@@ -803,3 +804,4 @@ exports.LogInspector = LogInspector
803
804
  exports.BrowsingContext = BrowsingContext
804
805
  exports.BrowsingConextInspector = BrowsingConextInspector
805
806
  exports.ScriptManager = ScriptManager
807
+ exports.NetworkInspector = NetworkInspector
package/io/exec.js CHANGED
@@ -141,8 +141,8 @@ function exec(command, opt_options) {
141
141
  resolve(new Result(code, signal))
142
142
  })
143
143
 
144
- proc.once('error', err => {
145
- reject(err);
144
+ proc.once('error', (err) => {
145
+ reject(err)
146
146
  })
147
147
  })
148
148
  return new Command(result, killCommand)
@@ -114,10 +114,9 @@ function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.repla
114
114
  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)}
115
115
  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,
116
116
  "\\$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)};
117
- 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=
118
- 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: "+
119
- 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};
120
- 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};
117
+ 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);
118
+ 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));
119
+ }};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};
121
120
  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]};
122
121
  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}
123
122
  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);};
package/lib/by.js CHANGED
@@ -396,7 +396,7 @@ class RelativeBy {
396
396
  * strategy.
397
397
  */
398
398
  function check(locator) {
399
- if (locator instanceof By || typeof locator === 'function') {
399
+ if (locator instanceof By || locator instanceof RelativeBy || typeof locator === 'function') {
400
400
  return locator
401
401
  }
402
402
 
package/lib/webdriver.js CHANGED
@@ -1238,8 +1238,8 @@ class WebDriver {
1238
1238
  } else {
1239
1239
  const seCdp = caps['map_'].get('se:cdp')
1240
1240
  const vendorInfo =
1241
- caps['map_'].get(this.VENDOR_COMMAND_PREFIX + ':chromeOptions') ||
1242
- caps['map_'].get(this.VENDOR_CAPABILITY_PREFIX + ':edgeOptions') ||
1241
+ caps['map_'].get('goog:chromeOptions') ||
1242
+ caps['map_'].get('ms:edgeOptions') ||
1243
1243
  caps['map_'].get('moz:debuggerAddress') ||
1244
1244
  new Map()
1245
1245
  debuggerUrl = seCdp || vendorInfo['debuggerAddress'] || vendorInfo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "4.9.2",
3
+ "version": "4.11.0",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -28,17 +28,17 @@
28
28
  "ws": ">=8.13.0"
29
29
  },
30
30
  "devDependencies": {
31
- "eslint": "^8.37.0",
31
+ "eslint": "^8.44.0",
32
32
  "eslint-config-prettier": "^8.8.0",
33
33
  "eslint-plugin-no-only-tests": "^3.1.0",
34
34
  "eslint-plugin-node": "^11.1.0",
35
- "eslint-plugin-prettier": "^4.2.1",
35
+ "eslint-plugin-prettier": "^5.0.0",
36
36
  "express": "^4.18.2",
37
37
  "mocha": "^10.2.0",
38
38
  "multer": "^1.4.5-lts.1",
39
- "prettier": "^2.8.7",
39
+ "prettier": "^3.0.0",
40
40
  "serve-index": "^1.9.1",
41
- "sinon": "^15.0.3"
41
+ "sinon": "^15.2.0"
42
42
  },
43
43
  "scripts": {
44
44
  "lint": "eslint --ignore-pattern node_modules --ignore-pattern generator --ext js lib/http.js \"**/*.js\"",
package/remote/util.js CHANGED
@@ -37,9 +37,7 @@ function getJavaPath() {
37
37
  function isSelenium3x(seleniumStandalonePath) {
38
38
  const javaPath = getJavaPath()
39
39
 
40
- const execRes = cp.execSync(
41
- `${javaPath} -jar ${seleniumStandalonePath} --version`
42
- )
40
+ const execRes = cp.execFileSync(javaPath, ['-jar', seleniumStandalonePath, '--version'])
43
41
 
44
42
  return execRes.toString().trim().startsWith('Selenium server version: 3')
45
43
  }
package/safari.js CHANGED
@@ -22,37 +22,10 @@
22
22
  'use strict'
23
23
 
24
24
  const http = require('./http')
25
- const io = require('./io')
26
25
  const remote = require('./remote')
27
26
  const webdriver = require('./lib/webdriver')
28
27
  const { Browser, Capabilities } = require('./lib/capabilities')
29
-
30
- /**
31
- * _Synchronously_ attempts to locate the IE driver executable on the current
32
- * system.
33
- *
34
- * @return {?string} the located executable, or `null`.
35
- */
36
- function locateSynchronously() {
37
- return process.platform === 'darwin'
38
- ? io.findInPath('safaridriver', true)
39
- : null
40
- }
41
-
42
- /**
43
- * @return {string} .
44
- * @throws {Error}
45
- */
46
- function findSafariDriver() {
47
- let exe = locateSynchronously()
48
- if (!exe) {
49
- throw Error(
50
- `The safaridriver executable could not be found on the current PATH.
51
- Please ensure you are using Safari 10.0 or above.`
52
- )
53
- }
54
- return exe
55
- }
28
+ const { getPath } = require('./common/driverFinder')
56
29
 
57
30
  /**
58
31
  * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
@@ -66,12 +39,12 @@ class ServiceBuilder extends remote.DriverService.Builder {
66
39
  * the builder will attempt to locate the safaridriver on the system PATH.
67
40
  */
68
41
  constructor(opt_exe) {
69
- super(opt_exe || findSafariDriver())
42
+ super(opt_exe)
70
43
  this.setLoopback(true) // Required.
71
44
  }
72
45
  }
73
46
 
74
- const OPTIONS_CAPABILITY_KEY = 'safari.options'
47
+ const OPTIONS_CAPABILITY_KEY = 'safari:options'
75
48
  const TECHNOLOGY_PREVIEW_OPTIONS_KEY = 'technologyPreview'
76
49
 
77
50
  /**
@@ -150,6 +123,9 @@ class Driver extends webdriver.WebDriver {
150
123
  }
151
124
 
152
125
  let service = new ServiceBuilder(exe).build()
126
+ if (!service.getExecutable()) {
127
+ service.setExecutable(getPath(caps).driverPath)
128
+ }
153
129
  let executor = new http.Executor(
154
130
  service.start().then((url) => new http.HttpClient(url))
155
131
  )
@@ -165,4 +141,3 @@ class Driver extends webdriver.WebDriver {
165
141
  exports.Driver = Driver
166
142
  exports.Options = Options
167
143
  exports.ServiceBuilder = ServiceBuilder
168
- exports.locateSynchronously = locateSynchronously
package/testing/index.js CHANGED
@@ -41,6 +41,7 @@ const remote = require('../remote')
41
41
  const safari = require('../safari')
42
42
  const { Browser } = require('../lib/capabilities')
43
43
  const { Builder } = require('../index')
44
+ const { getPath } = require('../common/driverFinder')
44
45
 
45
46
  /**
46
47
  * Describes a browser targeted by a {@linkplain suite test suite}.
@@ -117,19 +118,19 @@ function getAvailableBrowsers() {
117
118
  info(`Searching for WebDriver executables installed on the current system...`)
118
119
 
119
120
  let targets = [
120
- [chrome.locateSynchronously, Browser.CHROME],
121
- [edge.locateSynchronously, Browser.EDGE],
122
- [firefox.locateSynchronously, Browser.FIREFOX],
123
- [ie.locateSynchronously, Browser.INTERNET_EXPLORER],
124
- [safari.locateSynchronously, Browser.SAFARI],
121
+ [getPath(chrome.Options).driverPath, Browser.CHROME],
122
+ [getPath(edge.Options).driverPath, Browser.EDGE],
123
+ [getPath(firefox.Options).driverPath, Browser.FIREFOX],
124
+ [getPath(ie.Options).driverPath, Browser.INTERNET_EXPLORER],
125
+ [getPath(safari.Options).driverPath, Browser.SAFARI],
125
126
  ]
126
127
 
127
128
  let availableBrowsers = []
128
129
  for (let pair of targets) {
129
- const fn = pair[0]
130
+ const driverPath = pair[0]
130
131
  const name = pair[1]
131
132
  const capabilities = pair[2]
132
- if (fn()) {
133
+ if (driverPath.length > 0) {
133
134
  info(`... located ${name}`)
134
135
  availableBrowsers.push({ name, capabilities })
135
136
  }