selenium-webdriver 4.1.2 → 4.3.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 +207 -206
- package/chrome.js +10 -36
- package/chromium.js +4 -2
- package/devtools/CDPConnection.js +1 -1
- package/edge.js +8 -32
- package/firefox.js +1 -1
- package/ie.js +3 -3
- package/index.js +1 -47
- package/lib/capabilities.js +0 -8
- package/lib/command.js +9 -0
- package/lib/http.js +40 -0
- package/lib/input.js +76 -23
- package/lib/virtual_authenticator.js +230 -0
- package/lib/webdriver.js +137 -14
- package/net/index.js +9 -2
- package/package.json +10 -10
- package/testing/index.js +11 -15
- package/opera.js +0 -403
|
@@ -0,0 +1,230 @@
|
|
|
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
|
+
'use strict'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Options for the creation of virtual authenticators.
|
|
22
|
+
* @see http://w3c.github.io/webauthn/#sctn-automation
|
|
23
|
+
*/
|
|
24
|
+
class VirtualAuthenticatorOptions {
|
|
25
|
+
|
|
26
|
+
static Protocol = {
|
|
27
|
+
"CTAP2": 'ctap2',
|
|
28
|
+
"U2F": 'ctap1/u2f',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static Transport = {
|
|
32
|
+
"BLE": 'ble',
|
|
33
|
+
"USB": 'usb',
|
|
34
|
+
"NFC": 'nfc',
|
|
35
|
+
"INTERNAL": 'internal',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Constructor to initialise VirtualAuthenticatorOptions object.
|
|
40
|
+
*/
|
|
41
|
+
constructor() {
|
|
42
|
+
this._protocol = VirtualAuthenticatorOptions.Protocol["CTAP2"]
|
|
43
|
+
this._transport = VirtualAuthenticatorOptions.Transport["USB"]
|
|
44
|
+
this._hasResidentKey = false
|
|
45
|
+
this._hasUserVerification = false
|
|
46
|
+
this._isUserConsenting = true
|
|
47
|
+
this._isUserVerified = false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getProtocol() {
|
|
51
|
+
return this._protocol
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setProtocol(protocol) {
|
|
55
|
+
this._protocol = protocol
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getTransport() {
|
|
59
|
+
return this._transport
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
setTransport(transport) {
|
|
63
|
+
this._transport = transport
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getHasResidentKey() {
|
|
67
|
+
return this._hasResidentKey
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
setHasResidentKey(value) {
|
|
71
|
+
this._hasResidentKey = value
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getHasUserVerification() {
|
|
75
|
+
return this._hasUserVerification
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setHasUserVerification(value) {
|
|
79
|
+
this._hasUserVerification = value
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getIsUserConsenting() {
|
|
83
|
+
return this._isUserConsenting
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
setIsUserConsenting(value) {
|
|
87
|
+
this._isUserConsenting = value
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getIsUserVerified() {
|
|
91
|
+
return this._isUserVerified
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
setIsUserVerified(value) {
|
|
95
|
+
this._isUserVerified = value
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
toDict() {
|
|
99
|
+
return {
|
|
100
|
+
"protocol": this.getProtocol(),
|
|
101
|
+
"transport": this.getTransport(),
|
|
102
|
+
"hasResidentKey": this.getHasResidentKey(),
|
|
103
|
+
"hasUserVerification": this.getHasUserVerification(),
|
|
104
|
+
"isUserConsenting": this.getIsUserConsenting(),
|
|
105
|
+
"isUserVerified": this.getIsUserVerified(),
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* A credential stored in a virtual authenticator.
|
|
113
|
+
* @see https://w3c.github.io/webauthn/#credential-parameters
|
|
114
|
+
*/
|
|
115
|
+
class Credential {
|
|
116
|
+
constructor(
|
|
117
|
+
credentialId,
|
|
118
|
+
isResidentCredential,
|
|
119
|
+
rpId,
|
|
120
|
+
userHandle,
|
|
121
|
+
privateKey,
|
|
122
|
+
signCount
|
|
123
|
+
) {
|
|
124
|
+
this._id = credentialId
|
|
125
|
+
this._isResidentCredential = isResidentCredential
|
|
126
|
+
this._rpId = rpId
|
|
127
|
+
this._userHandle = userHandle
|
|
128
|
+
this._privateKey = privateKey
|
|
129
|
+
this._signCount = signCount
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
id() {
|
|
133
|
+
return this._id
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
isResidentCredential() {
|
|
137
|
+
return this._isResidentCredential
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
rpId() {
|
|
141
|
+
return this._rpId
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
userHandle() {
|
|
145
|
+
if (this._userHandle != null) {
|
|
146
|
+
return this._userHandle
|
|
147
|
+
}
|
|
148
|
+
return null
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
privateKey() {
|
|
152
|
+
return this._privateKey
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
signCount() {
|
|
156
|
+
return this._signCount
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Creates a resident (i.e. stateless) credential.
|
|
161
|
+
* @param id Unique base64 encoded string.
|
|
162
|
+
* @param rpId Relying party identifier.
|
|
163
|
+
* @param userHandle userHandle associated to the credential. Must be Base64 encoded string.
|
|
164
|
+
* @param privateKey Base64 encoded PKCS
|
|
165
|
+
* @param signCount initial value for a signature counter.
|
|
166
|
+
* @returns A resident credential
|
|
167
|
+
*/
|
|
168
|
+
createResidentCredential(id, rpId, userHandle, privateKey, signCount) {
|
|
169
|
+
return new Credential(id, true, rpId, userHandle, privateKey, signCount)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Creates a non-resident (i.e. stateless) credential.
|
|
174
|
+
* @param id Unique base64 encoded string.
|
|
175
|
+
* @param rpId Relying party identifier.
|
|
176
|
+
* @param privateKey Base64 encoded PKCS
|
|
177
|
+
* @param signCount initial value for a signature counter.
|
|
178
|
+
* @returns A non-resident credential
|
|
179
|
+
*/
|
|
180
|
+
createNonResidentCredential(id, rpId, privateKey, signCount) {
|
|
181
|
+
return new Credential(id, false, rpId, null, privateKey, signCount)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
toDict() {
|
|
185
|
+
let credentialData = {
|
|
186
|
+
'credentialId': Buffer.from(this._id).toString('base64url'),
|
|
187
|
+
'isResidentCredential': this._isResidentCredential,
|
|
188
|
+
'rpId': this._rpId,
|
|
189
|
+
'privateKey': Buffer.from(this._privateKey, 'binary').toString('base64url'),
|
|
190
|
+
'signCount': this._signCount,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (this.userHandle() != null) {
|
|
194
|
+
credentialData['userHandle'] = Buffer.from(this._userHandle).toString('base64url')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return credentialData
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Creates a credential from a map.
|
|
202
|
+
*/
|
|
203
|
+
fromDict(data) {
|
|
204
|
+
let id = new Uint8Array(Buffer.from(data['credentialId'], 'base64url'))
|
|
205
|
+
let isResidentCredential = data['isResidentCredential']
|
|
206
|
+
let rpId = data['rpId']
|
|
207
|
+
let privateKey = Buffer.from(data['privateKey'], 'base64url').toString('binary')
|
|
208
|
+
let signCount = data['signCount']
|
|
209
|
+
let userHandle
|
|
210
|
+
|
|
211
|
+
if ('userHandle' in data) {
|
|
212
|
+
userHandle = new Uint8Array(Buffer.from(data['userHandle'], 'base64url'))
|
|
213
|
+
} else {
|
|
214
|
+
userHandle = null
|
|
215
|
+
}
|
|
216
|
+
return new Credential(
|
|
217
|
+
id,
|
|
218
|
+
isResidentCredential,
|
|
219
|
+
rpId,
|
|
220
|
+
userHandle,
|
|
221
|
+
privateKey,
|
|
222
|
+
signCount
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = {
|
|
228
|
+
Credential,
|
|
229
|
+
VirtualAuthenticatorOptions,
|
|
230
|
+
}
|
package/lib/webdriver.js
CHANGED
|
@@ -37,6 +37,7 @@ const { Capabilities } = require('./capabilities')
|
|
|
37
37
|
const path = require('path')
|
|
38
38
|
const { NoSuchElementError } = require('./error')
|
|
39
39
|
const cdpTargets = ['page', 'browser']
|
|
40
|
+
const Credential = require('./virtual_authenticator').Credential
|
|
40
41
|
|
|
41
42
|
// Capability names that are defined in the W3C spec.
|
|
42
43
|
const W3C_CAPABILITY_NAMES = new Set([
|
|
@@ -679,6 +680,9 @@ class WebDriver {
|
|
|
679
680
|
|
|
680
681
|
/** @private @const {(function(this: void): ?|undefined)} */
|
|
681
682
|
this.onQuit_ = onQuit
|
|
683
|
+
|
|
684
|
+
/** @private {./virtual_authenticator}*/
|
|
685
|
+
this.authenticatorId_ = null
|
|
682
686
|
}
|
|
683
687
|
|
|
684
688
|
/**
|
|
@@ -730,6 +734,7 @@ class WebDriver {
|
|
|
730
734
|
/** @override */
|
|
731
735
|
async execute(command) {
|
|
732
736
|
command.setParameter('sessionId', this.session_)
|
|
737
|
+
|
|
733
738
|
let parameters = await toWireValue(command.getParameters())
|
|
734
739
|
command.setParameters(parameters)
|
|
735
740
|
let value = await this.executor_.execute(command)
|
|
@@ -1363,12 +1368,11 @@ class WebDriver {
|
|
|
1363
1368
|
if (params.method === 'Fetch.requestPaused') {
|
|
1364
1369
|
const requestPausedParams = params['params']
|
|
1365
1370
|
if (requestPausedParams.request.url == httpResponse.urlToIntercept) {
|
|
1366
|
-
connection.execute('Fetch.
|
|
1371
|
+
connection.execute('Fetch.fulfillRequest', {
|
|
1367
1372
|
requestId: requestPausedParams['requestId'],
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
postData: httpResponse.body,
|
|
1373
|
+
responseCode: 200,
|
|
1374
|
+
responseHeaders: httpResponse.headers,
|
|
1375
|
+
body: httpResponse.body,
|
|
1372
1376
|
})
|
|
1373
1377
|
callback()
|
|
1374
1378
|
} else {
|
|
@@ -1515,6 +1519,110 @@ class WebDriver {
|
|
|
1515
1519
|
}
|
|
1516
1520
|
})
|
|
1517
1521
|
}
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
*
|
|
1525
|
+
* @returns The value of authenticator ID added
|
|
1526
|
+
*/
|
|
1527
|
+
virtualAuthenticatorId() {
|
|
1528
|
+
return this.authenticatorId_
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
/**
|
|
1532
|
+
* Adds a virtual authenticator with the given options.
|
|
1533
|
+
* @param options VirtualAuthenticatorOptions object to set authenticator optons.
|
|
1534
|
+
*/
|
|
1535
|
+
async addVirtualAuthenticator(options) {
|
|
1536
|
+
this.authenticatorId_ = await this.execute(
|
|
1537
|
+
new command.Command(command.Name.ADD_VIRTUAL_AUTHENTICATOR).setParameters(
|
|
1538
|
+
options.toDict()
|
|
1539
|
+
)
|
|
1540
|
+
)
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
/**
|
|
1544
|
+
* Removes a previously added virtual authenticator. The authenticator is no
|
|
1545
|
+
* longer valid after removal, so no methods may be called.
|
|
1546
|
+
*/
|
|
1547
|
+
async removeVirtualAuthenticator() {
|
|
1548
|
+
await this.execute(
|
|
1549
|
+
new command.Command(
|
|
1550
|
+
command.Name.REMOVE_VIRTUAL_AUTHENTICATOR
|
|
1551
|
+
).setParameter('authenticatorId', this.authenticatorId_)
|
|
1552
|
+
)
|
|
1553
|
+
this.authenticatorId_ = null
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
/**
|
|
1557
|
+
* Injects a credential into the authenticator.
|
|
1558
|
+
* @param credential Credential to be added
|
|
1559
|
+
*/
|
|
1560
|
+
async addCredential(credential) {
|
|
1561
|
+
credential = credential.toDict()
|
|
1562
|
+
credential['authenticatorId'] = this.authenticatorId_
|
|
1563
|
+
await this.execute(
|
|
1564
|
+
new command.Command(command.Name.ADD_CREDENTIAL).setParameters(credential)
|
|
1565
|
+
)
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
*
|
|
1570
|
+
* @returns The list of credentials owned by the authenticator.
|
|
1571
|
+
*/
|
|
1572
|
+
async getCredentials() {
|
|
1573
|
+
let credential_data = await this.execute(
|
|
1574
|
+
new command.Command(command.Name.GET_CREDENTIALS).setParameter(
|
|
1575
|
+
'authenticatorId',
|
|
1576
|
+
this.virtualAuthenticatorId()
|
|
1577
|
+
)
|
|
1578
|
+
)
|
|
1579
|
+
var credential_list = []
|
|
1580
|
+
for (var i = 0; i < credential_data.length; i++) {
|
|
1581
|
+
credential_list.push(new Credential().fromDict(credential_data[i]))
|
|
1582
|
+
}
|
|
1583
|
+
return credential_list
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
/**
|
|
1587
|
+
* Removes a credential from the authenticator.
|
|
1588
|
+
* @param credential_id The ID of the credential to be removed.
|
|
1589
|
+
*/
|
|
1590
|
+
async removeCredential(credential_id) {
|
|
1591
|
+
// If credential_id is not a base64url, then convert it to base64url.
|
|
1592
|
+
if (Array.isArray(credential_id)) {
|
|
1593
|
+
credential_id = Buffer.from(credential_id).toString('base64url')
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
await this.execute(
|
|
1597
|
+
new command.Command(command.Name.REMOVE_CREDENTIAL)
|
|
1598
|
+
.setParameter('credentialId', credential_id)
|
|
1599
|
+
.setParameter('authenticatorId', this.authenticatorId_)
|
|
1600
|
+
)
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
/**
|
|
1604
|
+
* Removes all the credentials from the authenticator.
|
|
1605
|
+
*/
|
|
1606
|
+
async removeAllCredentials() {
|
|
1607
|
+
await this.execute(
|
|
1608
|
+
new command.Command(command.Name.REMOVE_ALL_CREDENTIALS).setParameter(
|
|
1609
|
+
'authenticatorId',
|
|
1610
|
+
this.authenticatorId_
|
|
1611
|
+
)
|
|
1612
|
+
)
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/**
|
|
1616
|
+
* Sets whether the authenticator will simulate success or fail on user verification.
|
|
1617
|
+
* @param verified true if the authenticator will pass user verification, false otherwise.
|
|
1618
|
+
*/
|
|
1619
|
+
async setUserVerified(verified) {
|
|
1620
|
+
await this.execute(
|
|
1621
|
+
new command.Command(command.Name.SET_USER_VERIFIED)
|
|
1622
|
+
.setParameter('authenticatorId', this.authenticatorId_)
|
|
1623
|
+
.setParameter('isUserVerified', verified)
|
|
1624
|
+
)
|
|
1625
|
+
}
|
|
1518
1626
|
}
|
|
1519
1627
|
|
|
1520
1628
|
/**
|
|
@@ -2162,13 +2270,23 @@ class TargetLocator {
|
|
|
2162
2270
|
* If the specified frame can not be found, the returned promise will be
|
|
2163
2271
|
* rejected with a {@linkplain error.NoSuchFrameError}.
|
|
2164
2272
|
*
|
|
2165
|
-
* @param {(number|WebElement|null)} id The frame locator.
|
|
2273
|
+
* @param {(number|string|WebElement|null)} id The frame locator.
|
|
2166
2274
|
* @return {!Promise<void>} A promise that will be resolved
|
|
2167
2275
|
* when the driver has changed focus to the specified frame.
|
|
2168
2276
|
*/
|
|
2169
2277
|
frame(id) {
|
|
2278
|
+
let frameReference = id
|
|
2279
|
+
if (typeof id === 'string') {
|
|
2280
|
+
frameReference = this.driver_
|
|
2281
|
+
.findElement({ id })
|
|
2282
|
+
.catch((_) => this.driver_.findElement({ name: id }))
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2170
2285
|
return this.driver_.execute(
|
|
2171
|
-
new command.Command(command.Name.SWITCH_TO_FRAME).setParameter(
|
|
2286
|
+
new command.Command(command.Name.SWITCH_TO_FRAME).setParameter(
|
|
2287
|
+
'id',
|
|
2288
|
+
frameReference
|
|
2289
|
+
)
|
|
2172
2290
|
)
|
|
2173
2291
|
}
|
|
2174
2292
|
|
|
@@ -2755,13 +2873,18 @@ class WebElement {
|
|
|
2755
2873
|
* when the form has been submitted.
|
|
2756
2874
|
*/
|
|
2757
2875
|
submit() {
|
|
2758
|
-
const
|
|
2759
|
-
|
|
2760
|
-
"
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
form
|
|
2764
|
-
|
|
2876
|
+
const script =
|
|
2877
|
+
'var form = arguments[0];\n' +
|
|
2878
|
+
'while (form.nodeName != "FORM" && form.parentNode) {\n' +
|
|
2879
|
+
' form = form.parentNode;\n' +
|
|
2880
|
+
'}\n' +
|
|
2881
|
+
"if (!form) { throw Error('Unable to find containing form element'); }\n" +
|
|
2882
|
+
"if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" +
|
|
2883
|
+
"var e = form.ownerDocument.createEvent('Event');\n" +
|
|
2884
|
+
"e.initEvent('submit', true, true);\n" +
|
|
2885
|
+
'if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n'
|
|
2886
|
+
|
|
2887
|
+
this.driver_.executeScript(script, this)
|
|
2765
2888
|
}
|
|
2766
2889
|
|
|
2767
2890
|
/**
|
package/net/index.js
CHANGED
|
@@ -48,7 +48,10 @@ function getIPAddress(loopback, family) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
for (let ipAddress of interfaces[key]) {
|
|
51
|
-
if (
|
|
51
|
+
if (
|
|
52
|
+
(ipAddress.family === family || `IPv${ipAddress.family}` === family) &&
|
|
53
|
+
ipAddress.internal === loopback
|
|
54
|
+
) {
|
|
52
55
|
return ipAddress.address
|
|
53
56
|
}
|
|
54
57
|
}
|
|
@@ -73,7 +76,11 @@ function getAddress(family = 'IPv4') {
|
|
|
73
76
|
* @return {(string|undefined)} The IP address or undefined if not available.
|
|
74
77
|
*/
|
|
75
78
|
function getLoopbackAddress(family = 'IPv4') {
|
|
76
|
-
|
|
79
|
+
let address = getIPAddress(true, family)
|
|
80
|
+
if (address === '127.0.0.1') {
|
|
81
|
+
address = 'localhost'
|
|
82
|
+
}
|
|
83
|
+
return address
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selenium-webdriver",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.3.1",
|
|
4
4
|
"description": "The official WebDriver JavaScript bindings from the Selenium project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -23,26 +23,26 @@
|
|
|
23
23
|
"node": ">= 10.15.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"jszip": "^3.
|
|
26
|
+
"jszip": "^3.10.0",
|
|
27
27
|
"tmp": "^0.2.1",
|
|
28
|
-
"ws": ">=7.
|
|
28
|
+
"ws": ">=8.7.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"eslint": "^
|
|
32
|
-
"eslint-config-prettier": "^8.
|
|
31
|
+
"eslint": "^8.16.0",
|
|
32
|
+
"eslint-config-prettier": "^8.5.0",
|
|
33
33
|
"eslint-plugin-no-only-tests": "^2.6.0",
|
|
34
34
|
"eslint-plugin-node": "^11.1.0",
|
|
35
|
-
"eslint-plugin-prettier": "^
|
|
35
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
36
36
|
"express": "^4.17.1",
|
|
37
37
|
"jasmine": "^3.8.0",
|
|
38
|
-
"mocha": "^
|
|
39
|
-
"multer": "^1.4.
|
|
40
|
-
"prettier": "^2.
|
|
38
|
+
"mocha": "^10.0.0",
|
|
39
|
+
"multer": "^1.4.5-lts.1",
|
|
40
|
+
"prettier": "^2.6.1",
|
|
41
41
|
"serve-index": "^1.9.1",
|
|
42
42
|
"sinon": "^10.0.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
|
-
"lint": "eslint --ignore-pattern node_modules --ignore-pattern generator --ext js lib/http.js \"**/*.js\"",
|
|
45
|
+
"lint": "eslint --ignore-pattern node_modules --ignore-pattern generator --fix --ext js lib/http.js \"**/*.js\"",
|
|
46
46
|
"test": "npm run lint && mocha -t 600000 --recursive test",
|
|
47
47
|
"test-jasmine": "jasmine JASMINE_CONFIG_PATH=jasmine.json"
|
|
48
48
|
},
|
package/testing/index.js
CHANGED
|
@@ -39,8 +39,7 @@ const firefox = require('../firefox')
|
|
|
39
39
|
const ie = require('../ie')
|
|
40
40
|
const remote = require('../remote')
|
|
41
41
|
const safari = require('../safari')
|
|
42
|
-
const
|
|
43
|
-
const { Browser, Capabilities } = require('../lib/capabilities')
|
|
42
|
+
const { Browser } = require('../lib/capabilities')
|
|
44
43
|
const { Builder } = require('../index')
|
|
45
44
|
|
|
46
45
|
/**
|
|
@@ -123,7 +122,6 @@ function getAvailableBrowsers() {
|
|
|
123
122
|
[firefox.locateSynchronously, Browser.FIREFOX],
|
|
124
123
|
[ie.locateSynchronously, Browser.INTERNET_EXPLORER],
|
|
125
124
|
[safari.locateSynchronously, Browser.SAFARI],
|
|
126
|
-
[opera.locateSynchronously, Browser.OPERA],
|
|
127
125
|
]
|
|
128
126
|
|
|
129
127
|
let availableBrowsers = []
|
|
@@ -236,7 +234,8 @@ function init(force = false) {
|
|
|
236
234
|
}
|
|
237
235
|
|
|
238
236
|
const TARGET_MAP = /** !WeakMap<!Environment, !TargetBrowser> */ new WeakMap()
|
|
239
|
-
const URL_MAP =
|
|
237
|
+
const URL_MAP =
|
|
238
|
+
/** !WeakMap<!Environment, ?(string|remote.SeleniumServer)> */ new WeakMap()
|
|
240
239
|
|
|
241
240
|
/**
|
|
242
241
|
* Defines the environment a {@linkplain suite test suite} is running against.
|
|
@@ -249,9 +248,9 @@ class Environment {
|
|
|
249
248
|
* Selenium server to test against.
|
|
250
249
|
*/
|
|
251
250
|
constructor(browser, url = undefined) {
|
|
252
|
-
browser = /** @type {!TargetBrowser} */ (
|
|
253
|
-
Object.assign({}, browser)
|
|
254
|
-
)
|
|
251
|
+
browser = /** @type {!TargetBrowser} */ (
|
|
252
|
+
Object.seal(Object.assign({}, browser))
|
|
253
|
+
)
|
|
255
254
|
|
|
256
255
|
TARGET_MAP.set(this, browser)
|
|
257
256
|
URL_MAP.set(this, url || null)
|
|
@@ -286,19 +285,16 @@ class Environment {
|
|
|
286
285
|
const builder = new Builder()
|
|
287
286
|
builder.disableEnvironmentOverrides()
|
|
288
287
|
|
|
289
|
-
|
|
290
|
-
|
|
291
288
|
const realBuild = builder.build
|
|
292
289
|
builder.build = function () {
|
|
293
|
-
builder.forBrowser(browser.name, browser.version, browser.platform)
|
|
294
|
-
|
|
290
|
+
builder.forBrowser(browser.name, browser.version, browser.platform)
|
|
295
291
|
|
|
296
292
|
if (browser.capabilities) {
|
|
297
|
-
builder.getCapabilities().merge(browser.capabilities)
|
|
293
|
+
builder.getCapabilities().merge(browser.capabilities)
|
|
298
294
|
}
|
|
299
295
|
|
|
300
|
-
if(browser.name === 'firefox') {
|
|
301
|
-
builder.setCapability('moz:debuggerAddress', true)
|
|
296
|
+
if (browser.name === 'firefox') {
|
|
297
|
+
builder.setCapability('moz:debuggerAddress', true)
|
|
302
298
|
}
|
|
303
299
|
|
|
304
300
|
if (typeof urlOrServer === 'string') {
|
|
@@ -444,7 +440,7 @@ function suite(fn, options = undefined) {
|
|
|
444
440
|
* @param {function(): boolean} predicateFn A predicate to call to determine
|
|
445
441
|
* if the test should be suppressed. This function MUST be synchronous.
|
|
446
442
|
* @return {{describe: !Function, it: !Function}} an object with wrapped
|
|
447
|
-
* versions of the `describe` and `it`
|
|
443
|
+
* versions of the `describe` and `it` test functions.
|
|
448
444
|
*/
|
|
449
445
|
function ignore(predicateFn) {
|
|
450
446
|
const isJasmine = global.jasmine && typeof global.jasmine === 'object'
|