selenium-webdriver 4.8.0 → 4.8.2

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.
package/CHANGES.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## v4.8.2
2
+
3
+ #### :nail_care: Polish
4
+
5
+ * Add CDP support for v111 and remove v108
6
+ * Using json output with Selenium Manager
7
+
8
+ #### :bug: Bug Fix
9
+
10
+ fix: Using status from response (#11742)
11
+
12
+ ## v4.8.1
13
+
14
+ #### :rocket: New Feature
15
+
16
+ * Add script pinning (#11584)
17
+
18
+ #### :nail_care: Polish
19
+
20
+ * Add CDP support for v110 and remove v107
21
+ * Updating Selenium Manager binaries for 4.8.1 release
22
+
23
+ #### :bug: Bug Fix
24
+
25
+ fix: iedriver download with selenium-manager #11579
26
+
1
27
  ## v4.8.0
2
28
 
3
29
  #### :rocket: New Feature
Binary file
Binary file
Binary file
package/chrome.js CHANGED
@@ -160,10 +160,6 @@ class ServiceBuilder extends chromium.ServiceBuilder {
160
160
  let exe = opt_exe || locateSynchronously()
161
161
 
162
162
  if (!exe) {
163
- console.log(
164
- ` The ChromeDriver could not be found on the current PATH, trying Selenium Manager`
165
- )
166
-
167
163
  try {
168
164
  exe = driverLocation(Browser.CHROME)
169
165
  } catch (err) {
@@ -173,10 +169,9 @@ class ServiceBuilder extends chromium.ServiceBuilder {
173
169
 
174
170
  if (!exe) {
175
171
  throw Error(
176
- `The ChromeDriver could not be found on the current PATH.
177
- Please download the latest version of the ChromeDriver
178
- from http://chromedriver.storage.googleapis.com/index.html
179
- and ensure it can be found on your PATH.`
172
+ `ChromeDriver could not be found on the PATH.
173
+ For more information on how to install drivers see
174
+ https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/.`
180
175
  )
181
176
  }
182
177
 
@@ -30,7 +30,7 @@ const execSync = require('child_process').execSync
30
30
  * currently supported browsers for selenium-manager
31
31
  * @type {string[]}
32
32
  */
33
- const Browser = ['chrome', 'firefox', 'edge']
33
+ const Browser = ['chrome', 'firefox', 'edge', 'iexplorer']
34
34
 
35
35
  /**
36
36
  * Determines the path of the correct Selenium Manager binary
@@ -69,22 +69,30 @@ function driverLocation(browser) {
69
69
  )
70
70
  }
71
71
 
72
- let args = [getBinary(), '--browser', browser]
73
- let result
72
+ let args = [getBinary(), '--browser', browser, '--output', 'json']
73
+ let output
74
74
 
75
75
  try {
76
- result = execSync(args.join(' ')).toString()
76
+ output = JSON.parse(execSync(args.join(' ')).toString())
77
77
  } catch (e) {
78
+ let error
79
+ try {
80
+ error = JSON.parse(e.stdout.toString()).result.message
81
+ } catch (e) {
82
+ error = e.toString()
83
+ }
78
84
  throw new Error(
79
- `Error executing command with ${args}\n${e.stdout.toString()}${e.stderr.toString()}`
85
+ `Error executing command with ${args}: ${error}`
80
86
  )
81
87
  }
82
88
 
83
- if (!result.startsWith('INFO\t')) {
84
- throw new Error(`Unsuccessful command executed: ${args}\n${result}`)
89
+ for (const key in output.logs){
90
+ if (output.logs[key].level === 'WARN') {
91
+ console.warn(`${output.logs[key].message}`)
92
+ }
85
93
  }
86
94
 
87
- return result.replace('INFO\t', '').trim()
95
+ return output.result.message
88
96
  }
89
97
 
90
98
  // PUBLIC API
@@ -15,6 +15,7 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
+ const RESPONSE_TIMEOUT = 1000 * 30
18
19
  class CDPConnection {
19
20
  constructor(wsConnection) {
20
21
  this._wsConnection = wsConnection
@@ -35,6 +36,42 @@ class CDPConnection {
35
36
  const mergedMessage = Object.assign({ params: params }, message)
36
37
  this._wsConnection.send(JSON.stringify(mergedMessage), callback)
37
38
  }
39
+
40
+ async send(method, params) {
41
+ let cdp_id = this.cmd_id++
42
+ let message = {
43
+ method,
44
+ id: cdp_id,
45
+ }
46
+ if (this.sessionId) {
47
+ message['sessionId'] = this.sessionId
48
+ }
49
+
50
+ const mergedMessage = Object.assign({ params: params }, message)
51
+ this._wsConnection.send(JSON.stringify(mergedMessage))
52
+
53
+ return new Promise((resolve, reject) => {
54
+ const timeoutId = setTimeout(() => {
55
+ reject(new Error(`Request with id ${cdp_id} timed out`))
56
+ handler.off('message', listener)
57
+ }, RESPONSE_TIMEOUT)
58
+
59
+ const listener = (data) => {
60
+ try {
61
+ const payload = JSON.parse(data.toString())
62
+ if (payload.id === cdp_id) {
63
+ clearTimeout(timeoutId)
64
+ handler.off('message', listener)
65
+ resolve(payload)
66
+ }
67
+ } catch (err) {
68
+ console.error(`Failed parse message: ${err.message}`)
69
+ }
70
+ }
71
+
72
+ const handler = this._wsConnection.on('message', listener)
73
+ })
74
+ }
38
75
  }
39
76
 
40
77
  exports.CdpConnection = CDPConnection
package/edge.js CHANGED
@@ -109,10 +109,6 @@ class ServiceBuilder extends chromium.ServiceBuilder {
109
109
  let exe = opt_exe || locateSynchronously()
110
110
 
111
111
  if (!exe) {
112
- console.log(
113
- `The WebDriver for Edge could not be found on the current PATH, trying Selenium Manager`
114
- )
115
-
116
112
  try {
117
113
  exe = driverLocation('edge')
118
114
  } catch (err) {
@@ -122,13 +118,11 @@ class ServiceBuilder extends chromium.ServiceBuilder {
122
118
 
123
119
  if (!exe) {
124
120
  throw Error(
125
- `The WebDriver for Edge could not be found on the current PATH. Please download the ` +
126
- `latest version of ${EDGEDRIVER_CHROMIUM_EXE} from ` +
127
- `https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ ` +
128
- `and ensure it can be found on your PATH.`
121
+ `MSEdgeDriver could not be found on the PATH.
122
+ For more information on how to install drivers see
123
+ https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/.`
129
124
  )
130
125
  }
131
-
132
126
  super(exe)
133
127
  this.setLoopback(true)
134
128
  }
package/firefox.js CHANGED
@@ -474,10 +474,6 @@ function findGeckoDriver() {
474
474
  let exe = locateSynchronously()
475
475
 
476
476
  if (!exe) {
477
- console.log(
478
- `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH, trying Selenium Manager`
479
- )
480
-
481
477
  try {
482
478
  exe = driverLocation(Browser.FIREFOX)
483
479
  } catch (err) {
@@ -487,9 +483,9 @@ function findGeckoDriver() {
487
483
 
488
484
  if (!exe) {
489
485
  throw Error(
490
- `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH.
491
- Please download the latest version from https://github.com/mozilla/geckodriver/releases/
492
- and ensure it can be found on your PATH.`
486
+ `GeckoDriver could not be found on the PATH.
487
+ For more information on how to install drivers see
488
+ https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/.`
493
489
  )
494
490
  }
495
491
 
package/ie.js CHANGED
@@ -401,12 +401,8 @@ function createServiceFromCapabilities(capabilities) {
401
401
 
402
402
  let exe = locateSynchronously()
403
403
  if (!exe) {
404
- console.log(
405
- `The ${IEDRIVER_EXE} executable could not be found on the current PATH, trying Selenium Manager`
406
- )
407
-
408
404
  try {
409
- exe = driverLocation(Browser.INTERNET_EXPLORER)
405
+ exe = driverLocation('iexplorer')
410
406
  } catch (err) {
411
407
  console.log(`Unable to obtain driver using Selenium Manager: ${err}`)
412
408
  }
@@ -414,10 +410,9 @@ function createServiceFromCapabilities(capabilities) {
414
410
 
415
411
  if (!exe || !fs.existsSync(exe)) {
416
412
  throw Error(
417
- `${IEDRIVER_EXE} could not be found on the current PATH. Please ` +
418
- `download the latest version of ${IEDRIVER_EXE} from ` +
419
- 'https://www.selenium.dev/downloads/ and ' +
420
- 'ensure it can be found on your system PATH.'
413
+ `IEDriver could not be found on the PATH.
414
+ For more information on how to install drivers see
415
+ https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/.`
421
416
  )
422
417
  }
423
418
 
@@ -0,0 +1,59 @@
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 crypto = require('crypto')
19
+
20
+ class PinnedScript {
21
+ constructor(script) {
22
+ this.scriptSource_ = script
23
+ this.scriptHandle_ = crypto.randomUUID().replace(/-/gi, '')
24
+ }
25
+
26
+ get handle() {
27
+ return this.scriptHandle_
28
+ }
29
+
30
+ get source() {
31
+ return this.scriptSource_
32
+ }
33
+
34
+ get scriptId() {
35
+ return this.scriptId_
36
+ }
37
+
38
+ set scriptId(id) {
39
+ this.scriptId_ = id
40
+ }
41
+
42
+ creationScript() {
43
+ return `function __webdriver_${this.scriptHandle_}(arguments) { ${this.scriptSource_} }`
44
+ }
45
+
46
+ executionScript() {
47
+ return `return __webdriver_${this.scriptHandle_}(arguments)`
48
+ }
49
+
50
+ removalScript() {
51
+ return `__webdriver_${this.scriptHandle_} = undefined`
52
+ }
53
+ }
54
+
55
+ // PUBLIC API
56
+
57
+ module.exports = {
58
+ PinnedScript,
59
+ }
package/lib/webdriver.js CHANGED
@@ -41,6 +41,7 @@ const { Credential } = require('./virtual_authenticator')
41
41
  const webElement = require('./webelement')
42
42
  const { isObject } = require('./util')
43
43
  const BIDI = require('../bidi')
44
+ const { PinnedScript } = require('./pinnedScript')
44
45
 
45
46
  // Capability names that are defined in the W3C spec.
46
47
  const W3C_CAPABILITY_NAMES = new Set([
@@ -686,6 +687,8 @@ class WebDriver {
686
687
 
687
688
  /** @private {./virtual_authenticator}*/
688
689
  this.authenticatorId_ = null
690
+
691
+ this.pinnedScripts_ = {}
689
692
  }
690
693
 
691
694
  /**
@@ -795,6 +798,15 @@ class WebDriver {
795
798
  if (typeof script === 'function') {
796
799
  script = 'return (' + script + ').apply(null, arguments);'
797
800
  }
801
+
802
+ if (script && script instanceof PinnedScript) {
803
+ return this.execute(
804
+ new command.Command(command.Name.EXECUTE_SCRIPT)
805
+ .setParameter('script', script.executionScript())
806
+ .setParameter('args', args)
807
+ )
808
+ }
809
+
798
810
  return this.execute(
799
811
  new command.Command(command.Name.EXECUTE_SCRIPT)
800
812
  .setParameter('script', script)
@@ -807,6 +819,15 @@ class WebDriver {
807
819
  if (typeof script === 'function') {
808
820
  script = 'return (' + script + ').apply(null, arguments);'
809
821
  }
822
+
823
+ if (script && script instanceof PinnedScript) {
824
+ return this.execute(
825
+ new command.Command(command.Name.EXECUTE_ASYNC_SCRIPT)
826
+ .setParameter('script', script.executionScript())
827
+ .setParameter('args', args)
828
+ )
829
+ }
830
+
810
831
  return this.execute(
811
832
  new command.Command(command.Name.EXECUTE_ASYNC_SCRIPT)
812
833
  .setParameter('script', script)
@@ -1226,7 +1247,9 @@ class WebDriver {
1226
1247
  this._wsUrl = await this.getWsUrl(debuggerUrl, target, caps)
1227
1248
  return new Promise((resolve, reject) => {
1228
1249
  try {
1229
- this._wsConnection = new WebSocket(this._wsUrl.replace('localhost', '127.0.0.1'))
1250
+ this._wsConnection = new WebSocket(
1251
+ this._wsUrl.replace('localhost', '127.0.0.1')
1252
+ )
1230
1253
  this._cdpConnection = new cdp.CdpConnection(this._wsConnection)
1231
1254
  } catch (err) {
1232
1255
  reject(err)
@@ -1382,7 +1405,7 @@ class WebDriver {
1382
1405
  if (requestPausedParams.request.url == httpResponse.urlToIntercept) {
1383
1406
  connection.execute('Fetch.fulfillRequest', {
1384
1407
  requestId: requestPausedParams['requestId'],
1385
- responseCode: 200,
1408
+ responseCode: httpResponse.status,
1386
1409
  responseHeaders: httpResponse.headers,
1387
1410
  body: httpResponse.body,
1388
1411
  })
@@ -1532,6 +1555,74 @@ class WebDriver {
1532
1555
  })
1533
1556
  }
1534
1557
 
1558
+ async pinScript(script) {
1559
+ let pinnedScript = new PinnedScript(script)
1560
+ let connection
1561
+ if (Object.is(this._cdpConnection, undefined)) {
1562
+ connection = await this.createCDPConnection('page')
1563
+ } else {
1564
+ connection = this._cdpConnection
1565
+ }
1566
+
1567
+ await connection.execute('Page.enable', {}, null)
1568
+
1569
+ await connection.execute(
1570
+ 'Runtime.evaluate',
1571
+ {
1572
+ expression: pinnedScript.creationScript(),
1573
+ },
1574
+ null
1575
+ )
1576
+
1577
+ let result = await connection.send(
1578
+ 'Page.addScriptToEvaluateOnNewDocument',
1579
+ {
1580
+ source: pinnedScript.creationScript(),
1581
+ }
1582
+ )
1583
+
1584
+ pinnedScript.scriptId = result['result']['identifier']
1585
+
1586
+ this.pinnedScripts_[pinnedScript.handle] = pinnedScript
1587
+
1588
+ return pinnedScript
1589
+ }
1590
+
1591
+ async unpinScript(script) {
1592
+ if (script && !(script instanceof PinnedScript)) {
1593
+ throw Error(`Pass valid PinnedScript object. Received: ${script}`)
1594
+ }
1595
+
1596
+ if (script.handle in this.pinnedScripts_) {
1597
+ let connection
1598
+ if (Object.is(this._cdpConnection, undefined)) {
1599
+ connection = this.createCDPConnection('page')
1600
+ } else {
1601
+ connection = this._cdpConnection
1602
+ }
1603
+
1604
+ await connection.execute('Page.enable', {}, null)
1605
+
1606
+ await connection.execute(
1607
+ 'Runtime.evaluate',
1608
+ {
1609
+ expression: script.removalScript(),
1610
+ },
1611
+ null
1612
+ )
1613
+
1614
+ await connection.execute(
1615
+ 'Page.removeScriptToEvaluateOnLoad',
1616
+ {
1617
+ identifier: script.scriptId,
1618
+ },
1619
+ null
1620
+ )
1621
+
1622
+ delete this.pinnedScripts_[script.handle]
1623
+ }
1624
+ }
1625
+
1535
1626
  /**
1536
1627
  *
1537
1628
  * @returns The value of authenticator ID added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "4.8.0",
3
+ "version": "4.8.2",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [