selenium-webdriver 4.19.0 → 4.20.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.
Files changed (60) hide show
  1. package/CHANGES.md +15 -0
  2. package/bidi/addInterceptParameters.js +28 -2
  3. package/bidi/browser.js +17 -0
  4. package/bidi/browsingContext.js +207 -25
  5. package/bidi/browsingContextInspector.js +51 -0
  6. package/bidi/browsingContextTypes.js +31 -0
  7. package/bidi/captureScreenshotParameters.js +96 -0
  8. package/bidi/clipRectangle.js +127 -0
  9. package/bidi/continueRequestParameters.js +39 -0
  10. package/bidi/continueResponseParameters.js +40 -0
  11. package/bidi/cookieFilter.js +60 -0
  12. package/bidi/createContextParameters.js +73 -0
  13. package/bidi/evaluateResult.js +17 -0
  14. package/bidi/index.js +0 -1
  15. package/bidi/input.js +27 -3
  16. package/bidi/interceptPhase.js +4 -0
  17. package/bidi/logEntries.js +66 -0
  18. package/bidi/network.js +102 -0
  19. package/bidi/networkTypes.js +346 -1
  20. package/bidi/partialCookie.js +48 -0
  21. package/bidi/partitionDescriptor.js +33 -0
  22. package/bidi/partitionKey.js +17 -0
  23. package/bidi/protocolType.js +20 -0
  24. package/bidi/protocolValue.js +129 -2
  25. package/bidi/provideResponseParameters.js +40 -0
  26. package/bidi/realmInfo.js +27 -0
  27. package/bidi/resultOwnership.js +4 -0
  28. package/bidi/scriptManager.js +119 -1
  29. package/bidi/scriptTypes.js +36 -0
  30. package/bidi/storage.js +30 -0
  31. package/bidi/urlPattern.js +35 -0
  32. package/bin/linux/selenium-manager +0 -0
  33. package/bin/macos/selenium-manager +0 -0
  34. package/bin/windows/selenium-manager.exe +0 -0
  35. package/chromium.js +12 -9
  36. package/common/driverFinder.js +36 -4
  37. package/common/seleniumManager.js +7 -39
  38. package/eslint.config.js +107 -0
  39. package/firefox.js +20 -6
  40. package/http/index.js +6 -6
  41. package/ie.js +8 -4
  42. package/index.js +11 -0
  43. package/io/exec.js +1 -1
  44. package/io/index.js +3 -2
  45. package/io/zip.js +1 -1
  46. package/lib/atoms/find-elements.js +2 -2
  47. package/lib/http.js +5 -4
  48. package/lib/input.js +0 -1
  49. package/lib/pinnedScript.js +1 -1
  50. package/lib/select.js +5 -5
  51. package/lib/until.js +3 -3
  52. package/lib/util.js +1 -0
  53. package/lib/webdriver.js +2 -2
  54. package/net/index.js +1 -1
  55. package/net/portprober.js +1 -1
  56. package/package.json +12 -6
  57. package/remote/index.js +1 -1
  58. package/remote/util.js +2 -2
  59. package/safari.js +3 -3
  60. package/testing/index.js +12 -8
@@ -0,0 +1,107 @@
1
+ // Licensed to the Software Freedom Conservancy (SFC) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The SFC licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ const globals = require('globals')
19
+ const noOnlyTests = require('eslint-plugin-no-only-tests')
20
+ const js = require('@eslint/js')
21
+ const eslintPluginPrettierRecommended = require('eslint-plugin-prettier/recommended')
22
+ const mochaPlugin = require('eslint-plugin-mocha')
23
+ const nodePlugin = require('eslint-plugin-n')
24
+
25
+ module.exports = [
26
+ js.configs.recommended,
27
+ eslintPluginPrettierRecommended,
28
+ mochaPlugin.configs.flat.recommended,
29
+ nodePlugin.configs['flat/recommended-script'],
30
+ {
31
+ languageOptions: {
32
+ globals: {
33
+ mocha: true,
34
+ es6: true,
35
+ ...globals.node,
36
+ },
37
+ parserOptions: {
38
+ ecmaVersion: 2022,
39
+ },
40
+ },
41
+ files: ['**/*.js', 'lib/http.js'],
42
+ ignores: ['node_modules/*', 'generator/*', 'devtools/generator/'],
43
+ plugins: {
44
+ 'no-only-tests': noOnlyTests,
45
+ },
46
+ rules: {
47
+ 'no-const-assign': 'error',
48
+ 'no-this-before-super': 'error',
49
+ 'no-undef': 'error',
50
+ 'no-unreachable': 'error',
51
+ 'no-unused-vars': [
52
+ 'error',
53
+ {
54
+ varsIgnorePattern: '^_',
55
+ args: 'all',
56
+ argsIgnorePattern: '^_',
57
+ },
58
+ ],
59
+ 'constructor-super': 'error',
60
+ 'valid-typeof': 'error',
61
+ 'no-only-tests/no-only-tests': 'error',
62
+ 'n/no-deprecated-api': ['error'],
63
+ 'n/no-missing-import': ['error'],
64
+ 'n/no-missing-require': ['error'],
65
+ 'n/no-mixed-requires': ['error'],
66
+ 'n/no-new-require': ['error'],
67
+ 'n/no-unpublished-import': ['error'],
68
+ 'n/no-unpublished-require': [
69
+ 'error',
70
+ {
71
+ allowModules: [
72
+ 'globals',
73
+ '@eslint/js',
74
+ 'eslint-plugin-mocha',
75
+ 'eslint-plugin-prettier',
76
+ 'eslint-plugin-n',
77
+ 'eslint-plugin-no-only-tests',
78
+ ],
79
+ tryExtensions: ['.js'],
80
+ },
81
+ ],
82
+ 'n/prefer-node-protocol': ['error'],
83
+ 'mocha/no-skipped-tests': ['off'],
84
+ 'mocha/no-mocha-arrows': ['off'],
85
+ 'mocha/no-setup-in-describe': ['off'],
86
+ 'mocha/no-top-level-hooks': ['off'],
87
+ 'mocha/no-sibling-hooks': ['off'],
88
+ 'mocha/no-exports': ['off'],
89
+ 'mocha/no-empty-description': ['off'],
90
+ 'mocha/max-top-level-suites': ['off'],
91
+ 'mocha/consistent-spacing-between-blocks': ['off'],
92
+ 'mocha/no-nested-tests': ['off'],
93
+ 'mocha/no-pending-tests': ['off'],
94
+ 'mocha/no-identical-title': ['off'],
95
+ 'prettier/prettier': [
96
+ 'error',
97
+ {
98
+ endOfLine: 'lf',
99
+ printWidth: 120,
100
+ semi: false,
101
+ singleQuote: true,
102
+ trailingComma: 'all',
103
+ },
104
+ ],
105
+ },
106
+ },
107
+ ]
package/firefox.js CHANGED
@@ -107,8 +107,8 @@
107
107
 
108
108
  'use strict'
109
109
 
110
- const fs = require('fs')
111
- const path = require('path')
110
+ const fs = require('node:fs')
111
+ const path = require('node:path')
112
112
  const Symbols = require('./lib/symbols')
113
113
  const command = require('./lib/command')
114
114
  const http = require('./http')
@@ -116,9 +116,9 @@ const io = require('./io')
116
116
  const remote = require('./remote')
117
117
  const webdriver = require('./lib/webdriver')
118
118
  const zip = require('./io/zip')
119
- const { Browser, Capabilities } = require('./lib/capabilities')
119
+ const { Browser, Capabilities, Capability } = require('./lib/capabilities')
120
120
  const { Zip } = require('./io/zip')
121
- const { getPath } = require('./common/driverFinder')
121
+ const { getBinaryPaths } = require('./common/driverFinder')
122
122
  const FIREFOX_CAPABILITY_KEY = 'moz:firefoxOptions'
123
123
 
124
124
  /**
@@ -444,6 +444,7 @@ const ExtensionCommand = {
444
444
  SET_CONTEXT: 'setContext',
445
445
  INSTALL_ADDON: 'install addon',
446
446
  UNINSTALL_ADDON: 'uninstall addon',
447
+ FULL_PAGE_SCREENSHOT: 'fullPage screenshot',
447
448
  }
448
449
 
449
450
  /**
@@ -470,6 +471,8 @@ function configureExecutor(executor) {
470
471
  executor.defineCommand(ExtensionCommand.INSTALL_ADDON, 'POST', '/session/:sessionId/moz/addon/install')
471
472
 
472
473
  executor.defineCommand(ExtensionCommand.UNINSTALL_ADDON, 'POST', '/session/:sessionId/moz/addon/uninstall')
474
+
475
+ executor.defineCommand(ExtensionCommand.FULL_PAGE_SCREENSHOT, 'GET', '/session/:sessionId/moz/screenshot/full')
473
476
  }
474
477
 
475
478
  /**
@@ -538,7 +541,7 @@ class Driver extends webdriver.WebDriver {
538
541
  configureExecutor(executor)
539
542
  } else if (opt_executor instanceof remote.DriverService) {
540
543
  if (!opt_executor.getExecutable()) {
541
- const { driverPath, browserPath } = getPath(caps)
544
+ const { driverPath, browserPath } = getBinaryPaths(caps)
542
545
  opt_executor.setExecutable(driverPath)
543
546
  firefoxBrowserPath = browserPath
544
547
  }
@@ -547,7 +550,7 @@ class Driver extends webdriver.WebDriver {
547
550
  } else {
548
551
  let service = new ServiceBuilder().build()
549
552
  if (!service.getExecutable()) {
550
- const { driverPath, browserPath } = getPath(caps)
553
+ const { driverPath, browserPath } = getBinaryPaths(caps)
551
554
  service.setExecutable(driverPath)
552
555
  firefoxBrowserPath = browserPath
553
556
  }
@@ -563,6 +566,7 @@ class Driver extends webdriver.WebDriver {
563
566
  } else {
564
567
  caps.set(FIREFOX_CAPABILITY_KEY, { binary: firefoxBrowserPath })
565
568
  }
569
+ caps.delete(Capability.BROWSER_VERSION)
566
570
  }
567
571
 
568
572
  return /** @type {!Driver} */ (super.createSession(executor, caps, onQuit))
@@ -645,6 +649,16 @@ class Driver extends webdriver.WebDriver {
645
649
  id = await Promise.resolve(id)
646
650
  return this.execute(new command.Command(ExtensionCommand.UNINSTALL_ADDON).setParameter('id', id))
647
651
  }
652
+
653
+ /**
654
+ * Take full page screenshot of the visible region
655
+ *
656
+ * @return {!Promise<string>} A promise that will be
657
+ * resolved to the screenshot as a base-64 encoded PNG.
658
+ */
659
+ takeFullPageScreenshot() {
660
+ return this.execute(new command.Command(ExtensionCommand.FULL_PAGE_SCREENSHOT))
661
+ }
648
662
  }
649
663
 
650
664
  /**
package/http/index.js CHANGED
@@ -22,9 +22,9 @@
22
22
 
23
23
  'use strict'
24
24
 
25
- const http = require('http')
26
- const https = require('https')
27
- const url = require('url')
25
+ const http = require('node:http')
26
+ const https = require('node:https')
27
+ const url = require('node:url')
28
28
 
29
29
  const httpLib = require('../lib/http')
30
30
 
@@ -45,7 +45,7 @@ let RequestOptions // eslint-disable-line
45
45
  * @throws {Error} if the URL does not include a hostname.
46
46
  */
47
47
  function getRequestOptions(aUrl) {
48
- //eslint-disable-next-line node/no-deprecated-api
48
+ // eslint-disable-next-line n/no-deprecated-api
49
49
  let options = url.parse(aUrl)
50
50
  if (!options.hostname) {
51
51
  throw new Error('Invalid URL: ' + aUrl)
@@ -140,7 +140,7 @@ class HttpClient {
140
140
  } else {
141
141
  path += httpRequest.path
142
142
  }
143
- //eslint-disable-next-line node/no-deprecated-api
143
+ // eslint-disable-next-line n/no-deprecated-api
144
144
  let parsedPath = url.parse(path)
145
145
 
146
146
  let options = {
@@ -218,7 +218,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
218
218
  if (response.statusCode == 302 || response.statusCode == 303) {
219
219
  let location
220
220
  try {
221
- // eslint-disable-next-line node/no-deprecated-api
221
+ // eslint-disable-next-line n/no-deprecated-api
222
222
  location = url.parse(response.headers['location'])
223
223
  } catch (ex) {
224
224
  onError(
package/ie.js CHANGED
@@ -33,7 +33,7 @@ const remote = require('./remote')
33
33
  const webdriver = require('./lib/webdriver')
34
34
  const { Browser, Capabilities } = require('./lib/capabilities')
35
35
  const error = require('./lib/error')
36
- const { getPath } = require('./common/driverFinder')
36
+ const { getBinaryPaths } = require('./common/driverFinder')
37
37
 
38
38
  const OPTIONS_CAPABILITY_KEY = 'se:ieOptions'
39
39
  const SCROLL_BEHAVIOUR = {
@@ -223,7 +223,9 @@ class Options extends Capabilities {
223
223
 
224
224
  addBrowserCommandSwitches(...args) {
225
225
  let current = this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] || []
226
- if (typeof current == 'string') current = current.split(' ')
226
+ if (typeof current == 'string') {
227
+ current = current.split(' ')
228
+ }
227
229
  this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] = current.concat(args).join(' ')
228
230
  return this
229
231
  }
@@ -239,7 +241,9 @@ class Options extends Capabilities {
239
241
 
240
242
  addArguments(...args) {
241
243
  let current = this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] || []
242
- if (typeof current == 'string') current = current.split(' ')
244
+ if (typeof current == 'string') {
245
+ current = current.split(' ')
246
+ }
243
247
  this.options_[Key.BROWSER_COMMAND_LINE_SWITCHES] = current.concat(args).join(' ')
244
248
  return this
245
249
  }
@@ -447,7 +451,7 @@ class Driver extends webdriver.WebDriver {
447
451
  service = createServiceFromCapabilities(options)
448
452
  }
449
453
  if (!service.getExecutable()) {
450
- service.setExecutable(getPath(options).driverPath)
454
+ service.setExecutable(getBinaryPaths(options).driverPath)
451
455
  }
452
456
 
453
457
  let client = service.start().then((url) => new http.HttpClient(url))
package/index.js CHANGED
@@ -596,6 +596,17 @@ class Builder {
596
596
 
597
597
  browser = capabilities.get(Capability.BROWSER_NAME)
598
598
 
599
+ /**
600
+ * If browser is not defined in forBrowser, check if browserOptions are defined to pick the browserName
601
+ */
602
+ if (!browser) {
603
+ const options =
604
+ this.chromeOptions_ || this.firefoxOptions_ || this.ieOptions_ || this.safariOptions_ || this.edgeOptions_
605
+ if (options) {
606
+ browser = options['map_'].get(Capability.BROWSER_NAME)
607
+ }
608
+ }
609
+
599
610
  if (typeof browser !== 'string') {
600
611
  throw TypeError(
601
612
  `Target browser must be a string, but is <${typeof browser}>;` + ' did you forget to call forBrowser()?',
package/io/exec.js CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  'use strict'
19
19
 
20
- const childProcess = require('child_process')
20
+ const childProcess = require('node:child_process')
21
21
 
22
22
  /**
23
23
  * Options for configuring an executed command.
package/io/index.js CHANGED
@@ -17,8 +17,8 @@
17
17
 
18
18
  'use strict'
19
19
 
20
- const fs = require('fs')
21
- const path = require('path')
20
+ const fs = require('node:fs')
21
+ const path = require('node:path')
22
22
  const tmp = require('tmp')
23
23
 
24
24
  /**
@@ -219,6 +219,7 @@ function findInPath(file, opt_checkCwd) {
219
219
  try {
220
220
  let stats = fs.statSync(tmp)
221
221
  return stats.isFile() && !stats.isDirectory()
222
+ /*eslint no-unused-vars: "off"*/
222
223
  } catch (ex) {
223
224
  return false
224
225
  }
package/io/zip.js CHANGED
@@ -18,7 +18,7 @@
18
18
  'use strict'
19
19
 
20
20
  const jszip = require('jszip')
21
- const path = require('path')
21
+ const path = require('node:path')
22
22
 
23
23
  const io = require('./index')
24
24
  const { InvalidArgumentError } = require('../lib/error')
@@ -106,8 +106,8 @@ function gd(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4
106
106
  function hd(a){return a.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,"")}function id(a){var b=[];Yc?jd(a,b):kd(a,b);a=qa(b,hd);return hd(a.join("\n")).replace(/\xa0/g," ")}
107
107
  function ld(a,b,c){if(S(a,"BR"))b.push("");else{var d=S(a,"TD"),e=U(a,"display"),f=!d&&!(0<=oa(md,e)),g=void 0!==a.previousElementSibling?a.previousElementSibling:gb(a.previousSibling);g=g?U(g,"display"):"";var h=U(a,"float")||U(a,"cssFloat")||U(a,"styleFloat");!f||"run-in"==g&&"none"==h||/^[\s\xa0]*$/.test(b[b.length-1]||"")||b.push("");var n=ed(a),u=null,p=null;n&&(u=U(a,"white-space"),p=U(a,"text-transform"));l(a.childNodes,function(G){c(G,b,n,u,p)});a=b[b.length-1]||"";!d&&"table-cell"!=e||!a||
108
108
  za(a)||(b[b.length-1]+=" ");f&&"run-in"!=e&&!/^[\s\xa0]*$/.test(a)&&b.push("")}}function kd(a,b){ld(a,b,function(c,d,e,f,g){3==c.nodeType&&e?nd(c,d,f,g):S(c)&&kd(c,d)})}var md="inline inline-block inline-table none table-cell table-column table-column-group".split(" ");
109
- function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(t?/(^|\s|\b)(\S)/g:/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",
110
- 0)&&(a=a.substr(1));b.push(c+a)}function dd(a){if(Mc){if("relative"==U(a,"position"))return 1;a=U(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=U(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
109
+ function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(t?/(^|\s|\b)(\S)/g:/(^|\s|\b)(\S)/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",0)&&(a=a.substr(1));
110
+ b.push(c+a)}function dd(a){if(Mc){if("relative"==U(a,"position"))return 1;a=U(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=U(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
111
111
  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?(f=S(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),l(0<f.length?f:a.childNodes,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)}
112
112
  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,
113
113
  "\\$1")}};var X={},rd={};X.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})};X.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})};X.o=function(a,b){return X.N(a,b,!1)};X.j=function(a,b){return X.K(a,b,!1)};rd.o=function(a,b){return X.N(a,b,!0)};
package/lib/http.js CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  'use strict'
27
27
 
28
- const path = require('path')
28
+ const path = require('node:path')
29
29
  const cmd = require('./command')
30
30
  const error = require('./error')
31
31
  const logging = require('./logging')
@@ -161,10 +161,10 @@ function resource(method, path) {
161
161
  }
162
162
 
163
163
  /** @typedef {{method: string, path: string}} */
164
- var CommandSpec // eslint-disable-line
164
+ var CommandSpec
165
165
 
166
166
  /** @typedef {function(!cmd.Command): !cmd.Command} */
167
- var CommandTransformer // eslint-disable-line
167
+ var CommandTransformer
168
168
 
169
169
  class InternalTypeError extends TypeError {}
170
170
 
@@ -337,7 +337,7 @@ class Client {
337
337
  * @return {!Promise<Response>} A promise that will be fulfilled with the
338
338
  * server's response.
339
339
  */
340
- send(httpRequest) {} // eslint-disable-line
340
+ send(httpRequest) {}
341
341
  }
342
342
 
343
343
  /**
@@ -472,6 +472,7 @@ class Executor {
472
472
  function tryParse(str) {
473
473
  try {
474
474
  return JSON.parse(str)
475
+ /*eslint no-unused-vars: "off"*/
475
476
  } catch (ignored) {
476
477
  // Do nothing.
477
478
  }
package/lib/input.js CHANGED
@@ -162,7 +162,6 @@ class FileDetector {
162
162
  * @package
163
163
  */
164
164
  handleFile(_driver, path) {
165
- // eslint-disable-line
166
165
  return Promise.resolve(path)
167
166
  }
168
167
  }
@@ -15,7 +15,7 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- const crypto = require('crypto')
18
+ const crypto = require('node:crypto')
19
19
 
20
20
  class PinnedScript {
21
21
  constructor(script) {
package/lib/select.js CHANGED
@@ -51,23 +51,23 @@ class ISelect {
51
51
  * @return {!Promise<boolean>} Whether this select element supports selecting multiple options at the same time? This
52
52
  * is done by checking the value of the "multiple" attribute.
53
53
  */
54
- isMultiple() {} // eslint-disable-line
54
+ isMultiple() {}
55
55
 
56
56
  /**
57
57
  * @return {!Promise<!Array<!WebElement>>} All options belonging to this select tag
58
58
  */
59
- getOptions() {} // eslint-disable-line
59
+ getOptions() {}
60
60
 
61
61
  /**
62
62
  * @return {!Promise<!Array<!WebElement>>} All selected options belonging to this select tag
63
63
  */
64
- getAllSelectedOptions() {} // eslint-disable-line
64
+ getAllSelectedOptions() {}
65
65
 
66
66
  /**
67
67
  * @return {!Promise<!WebElement>} The first selected option in this select tag (or the currently selected option in a
68
68
  * normal select)
69
69
  */
70
- getFirstSelectedOption() {} // eslint-disable-line
70
+ getFirstSelectedOption() {}
71
71
 
72
72
  /**
73
73
  * Select all options that display text matching the argument. That is, when given "Bar" this
@@ -105,7 +105,7 @@ class ISelect {
105
105
  *
106
106
  * @return {Promise<void>}
107
107
  */
108
- deselectAll() {} // eslint-disable-line
108
+ deselectAll() {}
109
109
 
110
110
  /**
111
111
  * Deselect all options that display text matching the argument. That is, when given "Bar" this
package/lib/until.js CHANGED
@@ -43,9 +43,9 @@
43
43
 
44
44
  const by = require('./by')
45
45
  const error = require('./error')
46
- const webdriver = require('./webdriver'),
47
- Condition = webdriver.Condition,
48
- WebElementCondition = webdriver.WebElementCondition
46
+ const webdriver = require('./webdriver')
47
+ const Condition = webdriver.Condition
48
+ const WebElementCondition = webdriver.WebElementCondition
49
49
 
50
50
  /**
51
51
  * Creates a condition that will wait until the input driver is able to switch
package/lib/util.js CHANGED
@@ -38,6 +38,7 @@ function isPromise(value) {
38
38
  // Use array notation so the Closure compiler does not obfuscate away our
39
39
  // contract.
40
40
  return (typeof value === 'object' || typeof value === 'function') && typeof value['then'] === 'function'
41
+ /*eslint no-unused-vars: "off"*/
41
42
  } catch (ex) {
42
43
  return false
43
44
  }
package/lib/webdriver.js CHANGED
@@ -32,9 +32,9 @@ const Symbols = require('./symbols')
32
32
  const cdp = require('../devtools/CDPConnection')
33
33
  const WebSocket = require('ws')
34
34
  const http = require('../http/index')
35
- const fs = require('fs')
35
+ const fs = require('node:fs')
36
36
  const { Capabilities } = require('./capabilities')
37
- const path = require('path')
37
+ const path = require('node:path')
38
38
  const { NoSuchElementError } = require('./error')
39
39
  const cdpTargets = ['page', 'browser']
40
40
  const { Credential } = require('./virtual_authenticator')
package/net/index.js CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  'use strict'
19
19
 
20
- const os = require('os')
20
+ const os = require('node:os')
21
21
 
22
22
  function getLoInterface() {
23
23
  let name
package/net/portprober.js CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  'use strict'
19
19
 
20
- const net = require('net')
20
+ const net = require('node:net')
21
21
 
22
22
  /**
23
23
  * Tests if a port is free.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "4.19.0",
3
+ "version": "4.20.0",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -29,13 +29,16 @@
29
29
  },
30
30
  "devDependencies": {
31
31
  "@bazel/runfiles": "^5.8.1",
32
- "eslint": "^8.57.0",
32
+ "@eslint/js": "^9.1.1",
33
+ "eslint": "^9.1.0",
33
34
  "eslint-config-prettier": "^9.1.0",
35
+ "eslint-plugin-mocha": "^10.4.3",
36
+ "eslint-plugin-n": "^17.2.1",
34
37
  "eslint-plugin-no-only-tests": "^3.1.0",
35
- "eslint-plugin-node": "^11.1.0",
36
38
  "eslint-plugin-prettier": "^5.1.3",
37
39
  "express": "^4.19.2",
38
- "mocha": "^10.3.0",
40
+ "globals": "^15.0.0",
41
+ "mocha": "^10.4.0",
39
42
  "mocha-junit-reporter": "^2.2.1",
40
43
  "multer": "^1.4.5-lts.1",
41
44
  "prettier": "^3.2.5",
@@ -43,13 +46,16 @@
43
46
  "sinon": "^17.0.1"
44
47
  },
45
48
  "scripts": {
46
- "lint": "eslint --ignore-pattern node_modules --ignore-pattern generator --ext js lib/http.js \"**/*.js\"",
47
- "lint:fix": "eslint --ignore-pattern node_modules --ignore-pattern generator --ext js lib/http.js \"**/*.js\" --fix",
49
+ "lint": "eslint .",
50
+ "lint:fix": "eslint . --fix",
48
51
  "test": "npm run lint && mocha -t 600000 --recursive test",
49
52
  "test-jasmine": "bazel test //javascript/node/selenium-webdriver:tests"
50
53
  },
51
54
  "mocha": {
52
55
  "recursive": true,
53
56
  "timeout": 600000
57
+ },
58
+ "publishConfig": {
59
+ "registry": "https://registry.npmjs.org/"
54
60
  }
55
61
  }
package/remote/index.js CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  'use strict'
19
19
 
20
- const url = require('url')
20
+ const url = require('node:url')
21
21
 
22
22
  const httpUtil = require('../http/util')
23
23
  const io = require('../io')
package/remote/util.js CHANGED
@@ -17,8 +17,8 @@
17
17
 
18
18
  'use strict'
19
19
 
20
- const path = require('path')
21
- const cp = require('child_process')
20
+ const path = require('node:path')
21
+ const cp = require('node:child_process')
22
22
  const logging = require('../lib/logging')
23
23
 
24
24
  /**
package/safari.js CHANGED
@@ -25,10 +25,10 @@ const http = require('./http')
25
25
  const remote = require('./remote')
26
26
  const webdriver = require('./lib/webdriver')
27
27
  const { Browser, Capabilities } = require('./lib/capabilities')
28
- const { getPath } = require('./common/driverFinder')
28
+ const { getBinaryPaths } = require('./common/driverFinder')
29
29
 
30
30
  /**
31
- * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
31
+ * Creates {@link remote.DriverService} instances that manage
32
32
  * a [safaridriver] server in a child process.
33
33
  *
34
34
  * [safaridriver]: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html#//apple_ref/doc/uid/TP40014305-CH11-DontLinkElementID_28
@@ -123,7 +123,7 @@ class Driver extends webdriver.WebDriver {
123
123
 
124
124
  let service = new ServiceBuilder(exe).build()
125
125
  if (!service.getExecutable()) {
126
- service.setExecutable(getPath(caps).driverPath)
126
+ service.setExecutable(getBinaryPaths(caps).driverPath)
127
127
  }
128
128
  let executor = new http.Executor(service.start().then((url) => new http.HttpClient(url)))
129
129
 
package/testing/index.js CHANGED
@@ -32,7 +32,7 @@
32
32
 
33
33
  'use strict'
34
34
 
35
- const { isatty } = require('tty')
35
+ const { isatty } = require('node:tty')
36
36
  const chrome = require('../chrome')
37
37
  const edge = require('../edge')
38
38
  const firefox = require('../firefox')
@@ -41,7 +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
+ const { getBinaryPaths } = require('../common/driverFinder')
45
45
 
46
46
  /**
47
47
  * Describes a browser targeted by a {@linkplain suite test suite}.
@@ -122,15 +122,15 @@ function getAvailableBrowsers() {
122
122
  info(`Searching for WebDriver executables installed on the current system...`)
123
123
 
124
124
  let targets = [
125
- [getPath(new chrome.Options()), Browser.CHROME],
126
- [getPath(new edge.Options()), Browser.EDGE],
127
- [getPath(new firefox.Options()), Browser.FIREFOX],
125
+ [getBinaryPaths(new chrome.Options()), Browser.CHROME],
126
+ [getBinaryPaths(new edge.Options()), Browser.EDGE],
127
+ [getBinaryPaths(new firefox.Options()), Browser.FIREFOX],
128
128
  ]
129
129
  if (process.platform === 'win32') {
130
- targets.push([getPath(new ie.Options()), Browser.INTERNET_EXPLORER])
130
+ targets.push([getBinaryPaths(new ie.Options()), Browser.INTERNET_EXPLORER])
131
131
  }
132
132
  if (process.platform === 'darwin') {
133
- targets.push([getPath(new safari.Options()), Browser.SAFARI])
133
+ targets.push([getBinaryPaths(new safari.Options()), Browser.SAFARI])
134
134
  }
135
135
 
136
136
  let availableBrowsers = []
@@ -302,6 +302,11 @@ class Environment {
302
302
  builder.setCapability('moz:debuggerAddress', true)
303
303
  }
304
304
 
305
+ // Enable BiDi for supporting browsers.
306
+ if (browser.name === Browser.FIREFOX || browser.name === Browser.CHROME || browser.name === Browser.EDGE) {
307
+ builder.setCapability('webSocketUrl', true)
308
+ }
309
+
305
310
  if (typeof urlOrServer === 'string') {
306
311
  builder.usingServer(urlOrServer)
307
312
  } else if (urlOrServer) {
@@ -401,7 +406,6 @@ function suite(fn, options = undefined) {
401
406
 
402
407
  const startTimeout = 65 * 1000
403
408
 
404
- // eslint-disable-next-line no-inner-declarations
405
409
  function startSelenium() {
406
410
  if (typeof this.timeout === 'function') {
407
411
  this.timeout(startTimeout) // For mocha.