selenium-webdriver 4.8.0 → 4.8.1

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,18 @@
1
+ ## v4.8.1
2
+
3
+ #### :rocket: New Feature
4
+
5
+ * Add script pinning (#11584)
6
+
7
+ #### :nail_care: Polish
8
+
9
+ * Add CDP support for v110 and remove v107
10
+ * Updating Selenium Manager binaries for 4.8.1 release
11
+
12
+ #### :bug: Bug Fix
13
+
14
+ fix: iedriver download with selenium-manager #11579
15
+
1
16
  ## v4.8.0
2
17
 
3
18
  #### :rocket: New Feature
Binary file
Binary file
Binary file
@@ -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
@@ -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/ie.js CHANGED
@@ -406,7 +406,7 @@ function createServiceFromCapabilities(capabilities) {
406
406
  )
407
407
 
408
408
  try {
409
- exe = driverLocation(Browser.INTERNET_EXPLORER)
409
+ exe = driverLocation('iexplorer')
410
410
  } catch (err) {
411
411
  console.log(`Unable to obtain driver using Selenium Manager: ${err}`)
412
412
  }
@@ -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)
@@ -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.1",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [