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 +15 -0
- package/bin/linux/selenium-manager +0 -0
- package/bin/macos/selenium-manager +0 -0
- package/bin/windows/selenium-manager.exe +0 -0
- package/common/seleniumManager.js +1 -1
- package/devtools/CDPConnection.js +37 -0
- package/ie.js +1 -1
- package/lib/pinnedScript.js +59 -0
- package/lib/webdriver.js +92 -1
- package/package.json +1 -1
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(
|
|
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(
|
|
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
|