selenium-webdriver 4.8.1 → 4.9.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.
- package/CHANGES.md +29 -0
- package/bidi/argumentValue.js +34 -0
- package/bidi/evaluateResult.js +60 -0
- package/bidi/logEntries.js +16 -13
- package/bidi/protocolType.js +97 -0
- package/bidi/protocolValue.js +204 -0
- package/bidi/realmInfo.js +99 -0
- package/bidi/resultOwnership.js +23 -0
- package/bidi/scriptManager.js +325 -0
- package/bin/linux/selenium-manager +0 -0
- package/bin/macos/selenium-manager +0 -0
- package/bin/windows/selenium-manager.exe +0 -0
- package/chrome.js +0 -23
- package/chromium.js +4 -0
- package/common/driverFinder.js +59 -0
- package/common/seleniumManager.js +51 -16
- package/edge.js +0 -23
- package/firefox.js +8 -24
- package/http/index.js +2 -1
- package/ie.js +4 -22
- package/index.js +2 -0
- package/lib/http.js +17 -3
- package/lib/webdriver.js +15 -8
- package/package.json +9 -8
- package/remote/index.js +8 -4
- package/remote/util.js +3 -1
|
@@ -0,0 +1,325 @@
|
|
|
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 {
|
|
19
|
+
EvaluateResultType,
|
|
20
|
+
EvaluateResultSuccess,
|
|
21
|
+
EvaluateResultException,
|
|
22
|
+
ExceptionDetails,
|
|
23
|
+
} = require('./evaluateResult')
|
|
24
|
+
const { RealmInfo } = require('./realmInfo')
|
|
25
|
+
const { RemoteValue } = require('./protocolValue')
|
|
26
|
+
|
|
27
|
+
class ScriptManager {
|
|
28
|
+
constructor(driver) {
|
|
29
|
+
this._driver = driver
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async init(browsingContextId) {
|
|
33
|
+
if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {
|
|
34
|
+
throw Error('WebDriver instance must support BiDi protocol')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.bidi = await this._driver.getBidi()
|
|
38
|
+
this._browsingContextId = browsingContextId
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async disownRealmScript(realmId, handles) {
|
|
42
|
+
const params = {
|
|
43
|
+
method: 'script.disown',
|
|
44
|
+
params: {
|
|
45
|
+
handles: handles,
|
|
46
|
+
target: {
|
|
47
|
+
realm: realmId,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await this.bidi.send(params)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async disownBrowsingContextScript(
|
|
56
|
+
browsingContextId,
|
|
57
|
+
handles,
|
|
58
|
+
sandbox = null
|
|
59
|
+
) {
|
|
60
|
+
const params = {
|
|
61
|
+
method: 'script.disown',
|
|
62
|
+
params: {
|
|
63
|
+
handles: handles,
|
|
64
|
+
target: {
|
|
65
|
+
context: browsingContextId,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (sandbox != null) {
|
|
71
|
+
params.params.target['sandbox'] = sandbox
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await this.bidi.send(params)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async callFunctionInRealm(
|
|
78
|
+
realmId,
|
|
79
|
+
functionDeclaration,
|
|
80
|
+
awaitPromise,
|
|
81
|
+
argumentValueList = null,
|
|
82
|
+
thisParameter = null,
|
|
83
|
+
resultOwnership = null
|
|
84
|
+
) {
|
|
85
|
+
const params = this.getCallFunctionParams(
|
|
86
|
+
'realm',
|
|
87
|
+
realmId,
|
|
88
|
+
null,
|
|
89
|
+
functionDeclaration,
|
|
90
|
+
awaitPromise,
|
|
91
|
+
argumentValueList,
|
|
92
|
+
thisParameter,
|
|
93
|
+
resultOwnership
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const command = {
|
|
97
|
+
method: 'script.callFunction',
|
|
98
|
+
params,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let response = await this.bidi.send(command)
|
|
102
|
+
return this.createEvaluateResult(response)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async callFunctionInBrowsingContext(
|
|
106
|
+
browsingContextId,
|
|
107
|
+
functionDeclaration,
|
|
108
|
+
awaitPromise,
|
|
109
|
+
argumentValueList = null,
|
|
110
|
+
thisParameter = null,
|
|
111
|
+
resultOwnership = null,
|
|
112
|
+
sandbox = null
|
|
113
|
+
) {
|
|
114
|
+
const params = this.getCallFunctionParams(
|
|
115
|
+
'contextTarget',
|
|
116
|
+
browsingContextId,
|
|
117
|
+
sandbox,
|
|
118
|
+
functionDeclaration,
|
|
119
|
+
awaitPromise,
|
|
120
|
+
argumentValueList,
|
|
121
|
+
thisParameter,
|
|
122
|
+
resultOwnership
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
const command = {
|
|
126
|
+
method: 'script.callFunction',
|
|
127
|
+
params,
|
|
128
|
+
}
|
|
129
|
+
const response = await this.bidi.send(command)
|
|
130
|
+
return this.createEvaluateResult(response)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async evaluateFunctionInRealm(
|
|
134
|
+
realmId,
|
|
135
|
+
expression,
|
|
136
|
+
awaitPromise,
|
|
137
|
+
resultOwnership = null
|
|
138
|
+
) {
|
|
139
|
+
const params = this.getEvaluateParams(
|
|
140
|
+
'realm',
|
|
141
|
+
realmId,
|
|
142
|
+
null,
|
|
143
|
+
expression,
|
|
144
|
+
awaitPromise,
|
|
145
|
+
resultOwnership
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
const command = {
|
|
149
|
+
method: 'script.evaluate',
|
|
150
|
+
params,
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let response = await this.bidi.send(command)
|
|
154
|
+
return this.createEvaluateResult(response)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async evaluateFunctionInBrowsingContext(
|
|
158
|
+
browsingContextId,
|
|
159
|
+
expression,
|
|
160
|
+
awaitPromise,
|
|
161
|
+
resultOwnership = null,
|
|
162
|
+
sandbox = null
|
|
163
|
+
) {
|
|
164
|
+
const params = this.getEvaluateParams(
|
|
165
|
+
'contextTarget',
|
|
166
|
+
browsingContextId,
|
|
167
|
+
sandbox,
|
|
168
|
+
expression,
|
|
169
|
+
awaitPromise,
|
|
170
|
+
resultOwnership
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
const command = {
|
|
174
|
+
method: 'script.evaluate',
|
|
175
|
+
params,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
let response = await this.bidi.send(command)
|
|
179
|
+
return this.createEvaluateResult(response)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
getCallFunctionParams(
|
|
183
|
+
targetType,
|
|
184
|
+
id,
|
|
185
|
+
sandbox,
|
|
186
|
+
functionDeclaration,
|
|
187
|
+
awaitPromise,
|
|
188
|
+
argumentValueList = null,
|
|
189
|
+
thisParameter = null,
|
|
190
|
+
resultOwnership = null
|
|
191
|
+
) {
|
|
192
|
+
const params = {
|
|
193
|
+
functionDeclaration: functionDeclaration,
|
|
194
|
+
awaitPromise: awaitPromise,
|
|
195
|
+
}
|
|
196
|
+
if (targetType === 'contextTarget') {
|
|
197
|
+
if (sandbox != null) {
|
|
198
|
+
params['target'] = { context: id, sandbox: sandbox }
|
|
199
|
+
} else {
|
|
200
|
+
params['target'] = { context: id }
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
params['target'] = { realm: id }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (argumentValueList != null) {
|
|
207
|
+
let argumentParams = []
|
|
208
|
+
argumentValueList.forEach((argumentValue) => {
|
|
209
|
+
argumentParams.push(argumentValue.asMap())
|
|
210
|
+
})
|
|
211
|
+
params['arguments'] = argumentParams
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (thisParameter != null) {
|
|
215
|
+
params['this'] = thisParameter
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (resultOwnership != null) {
|
|
219
|
+
params['resultOwnership'] = resultOwnership
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return params
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
getEvaluateParams(
|
|
226
|
+
targetType,
|
|
227
|
+
id,
|
|
228
|
+
sandbox,
|
|
229
|
+
expression,
|
|
230
|
+
awaitPromise,
|
|
231
|
+
resultOwnership = null
|
|
232
|
+
) {
|
|
233
|
+
const params = {
|
|
234
|
+
expression: expression,
|
|
235
|
+
awaitPromise: awaitPromise,
|
|
236
|
+
}
|
|
237
|
+
if (targetType === 'contextTarget') {
|
|
238
|
+
if (sandbox != null) {
|
|
239
|
+
params['target'] = { context: id, sandbox: sandbox }
|
|
240
|
+
} else {
|
|
241
|
+
params['target'] = { context: id }
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
params['target'] = { realm: id }
|
|
245
|
+
}
|
|
246
|
+
if (resultOwnership != null) {
|
|
247
|
+
params['resultOwnership'] = resultOwnership
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return params
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
createEvaluateResult(response) {
|
|
254
|
+
var type = response.result.type
|
|
255
|
+
var realmId = response.result.realm
|
|
256
|
+
var evaluateResult
|
|
257
|
+
|
|
258
|
+
if (type === EvaluateResultType.SUCCESS) {
|
|
259
|
+
var result = response.result.result
|
|
260
|
+
evaluateResult = new EvaluateResultSuccess(
|
|
261
|
+
realmId,
|
|
262
|
+
new RemoteValue(result)
|
|
263
|
+
)
|
|
264
|
+
} else {
|
|
265
|
+
var exceptionDetails = response.result.exceptionDetails
|
|
266
|
+
evaluateResult = new EvaluateResultException(
|
|
267
|
+
realmId,
|
|
268
|
+
new ExceptionDetails(exceptionDetails)
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
return evaluateResult
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
realmInfoMapper(realms) {
|
|
275
|
+
var realmsList = []
|
|
276
|
+
realms.forEach((realm) => {
|
|
277
|
+
realmsList.push(RealmInfo.fromJson(realm))
|
|
278
|
+
})
|
|
279
|
+
return realmsList
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async getAllRealms() {
|
|
283
|
+
const command = {
|
|
284
|
+
method: 'script.getRealms',
|
|
285
|
+
params: {},
|
|
286
|
+
}
|
|
287
|
+
let response = await this.bidi.send(command)
|
|
288
|
+
return this.realmInfoMapper(response.result.realms)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async getRealmsByType(type) {
|
|
292
|
+
const command = {
|
|
293
|
+
method: 'script.getRealms',
|
|
294
|
+
params: { type: type },
|
|
295
|
+
}
|
|
296
|
+
let response = await this.bidi.send(command)
|
|
297
|
+
return this.realmInfoMapper(response.result.realms)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async getRealmsInBrowsingContext(browsingContext) {
|
|
301
|
+
const command = {
|
|
302
|
+
method: 'script.getRealms',
|
|
303
|
+
params: { context: browsingContext },
|
|
304
|
+
}
|
|
305
|
+
let response = await this.bidi.send(command)
|
|
306
|
+
return this.realmInfoMapper(response.result.realms)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async getRealmsInBrowsingContextByType(browsingContext, type) {
|
|
310
|
+
const command = {
|
|
311
|
+
method: 'script.getRealms',
|
|
312
|
+
params: { context: browsingContext, type: type },
|
|
313
|
+
}
|
|
314
|
+
let response = await this.bidi.send(command)
|
|
315
|
+
return this.realmInfoMapper(response.result.realms)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async function getScriptManagerInstance(browsingContextId, driver) {
|
|
320
|
+
let instance = new ScriptManager(driver)
|
|
321
|
+
await instance.init(browsingContextId)
|
|
322
|
+
return instance
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
module.exports = getScriptManagerInstance
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/chrome.js
CHANGED
|
@@ -130,7 +130,6 @@
|
|
|
130
130
|
const io = require('./io')
|
|
131
131
|
const { Browser } = require('./lib/capabilities')
|
|
132
132
|
const chromium = require('./chromium')
|
|
133
|
-
const { driverLocation } = require('./common/seleniumManager')
|
|
134
133
|
|
|
135
134
|
/**
|
|
136
135
|
* Name of the ChromeDriver executable.
|
|
@@ -158,28 +157,6 @@ class ServiceBuilder extends chromium.ServiceBuilder {
|
|
|
158
157
|
*/
|
|
159
158
|
constructor(opt_exe) {
|
|
160
159
|
let exe = opt_exe || locateSynchronously()
|
|
161
|
-
|
|
162
|
-
if (!exe) {
|
|
163
|
-
console.log(
|
|
164
|
-
` The ChromeDriver could not be found on the current PATH, trying Selenium Manager`
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
try {
|
|
168
|
-
exe = driverLocation(Browser.CHROME)
|
|
169
|
-
} catch (err) {
|
|
170
|
-
console.log(`Unable to obtain driver using Selenium Manager: ${err}`)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (!exe) {
|
|
175
|
-
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.`
|
|
180
|
-
)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
160
|
super(exe)
|
|
184
161
|
}
|
|
185
162
|
}
|
package/chromium.js
CHANGED
|
@@ -83,6 +83,7 @@ const error = require('./lib/error')
|
|
|
83
83
|
const Symbols = require('./lib/symbols')
|
|
84
84
|
const webdriver = require('./lib/webdriver')
|
|
85
85
|
const remote = require('./remote')
|
|
86
|
+
const { getPath } = require('./common/driverFinder')
|
|
86
87
|
|
|
87
88
|
/**
|
|
88
89
|
* Custom command names supported by Chromium WebDriver.
|
|
@@ -684,6 +685,9 @@ class Driver extends webdriver.WebDriver {
|
|
|
684
685
|
configureExecutor(executor, this.VENDOR_COMMAND_PREFIX)
|
|
685
686
|
} else {
|
|
686
687
|
let service = opt_serviceExecutor || this.getDefaultService()
|
|
688
|
+
if (!service.getExecutable()) {
|
|
689
|
+
service.setExecutable(getPath(service, caps))
|
|
690
|
+
}
|
|
687
691
|
onQuit = () => service.kill()
|
|
688
692
|
executor = createExecutor(service.start(), this.VENDOR_COMMAND_PREFIX)
|
|
689
693
|
}
|
|
@@ -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
|
+
/**
|
|
19
|
+
* This implementation is still in beta, and may change.
|
|
20
|
+
*
|
|
21
|
+
* Utility to find if a given file is present and executable.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const { driverLocation } = require('./seleniumManager')
|
|
25
|
+
const fs = require('fs')
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Determines the path of the correct Selenium Manager binary
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
function getPath(service, capabilities) {
|
|
32
|
+
try {
|
|
33
|
+
return pathExists(service.getExecutable()) || driverLocation(capabilities)
|
|
34
|
+
} catch (e) {
|
|
35
|
+
throw Error(
|
|
36
|
+
`Unable to obtain browser driver.
|
|
37
|
+
For more information on how to install drivers see
|
|
38
|
+
https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/. ${e}`
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* _Synchronously_ attempts to locate the driver executable on the current
|
|
45
|
+
* system.
|
|
46
|
+
*
|
|
47
|
+
* @param {!string} driverPath
|
|
48
|
+
*
|
|
49
|
+
* @return {?string} the located executable, or `null`.
|
|
50
|
+
*/
|
|
51
|
+
function pathExists(driverPath) {
|
|
52
|
+
if (!driverPath || !fs.existsSync(driverPath)) {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
return driverPath
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// PUBLIC API
|
|
59
|
+
module.exports = { getPath }
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
const { platform } = require('process')
|
|
25
25
|
const path = require('path')
|
|
26
26
|
const fs = require('fs')
|
|
27
|
-
const
|
|
27
|
+
const spawnSync = require('child_process').spawnSync
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* currently supported browsers for selenium-manager
|
|
31
31
|
* @type {string[]}
|
|
32
32
|
*/
|
|
33
|
-
const Browser = ['chrome', 'firefox', 'edge', 'iexplorer']
|
|
33
|
+
const Browser = ['chrome', 'firefox', 'edge', 'MicrosoftEdge', 'iexplorer']
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Determines the path of the correct Selenium Manager binary
|
|
@@ -47,7 +47,14 @@ function getBinary() {
|
|
|
47
47
|
const file =
|
|
48
48
|
directory === 'windows' ? 'selenium-manager.exe' : 'selenium-manager'
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
let seleniumManagerBasePath
|
|
51
|
+
if (process.env.SELENIUM_MANAGER_BASE_PATH) {
|
|
52
|
+
seleniumManagerBasePath = process.env.SELENIUM_MANAGER_BASE_PATH
|
|
53
|
+
} else {
|
|
54
|
+
seleniumManagerBasePath = path.join(__dirname, '..', '/bin')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const filePath = path.join(seleniumManagerBasePath, directory, file)
|
|
51
58
|
|
|
52
59
|
if (!fs.existsSync(filePath)) {
|
|
53
60
|
throw new Error(`Unable to obtain Selenium Manager`)
|
|
@@ -58,33 +65,61 @@ function getBinary() {
|
|
|
58
65
|
|
|
59
66
|
/**
|
|
60
67
|
* Determines the path of the correct driver
|
|
61
|
-
* @param {
|
|
68
|
+
* @param {Capabilities} options browser options to fetch the driver
|
|
62
69
|
* @returns {string} path of the driver location
|
|
63
70
|
*/
|
|
64
71
|
|
|
65
|
-
function driverLocation(
|
|
66
|
-
if (!Browser.includes(
|
|
72
|
+
function driverLocation(options) {
|
|
73
|
+
if (!Browser.includes(options.getBrowserName().toLocaleString())) {
|
|
67
74
|
throw new Error(
|
|
68
|
-
`Unable to locate driver associated with browser name: ${
|
|
75
|
+
`Unable to locate driver associated with browser name: ${options.getBrowserName()}`
|
|
69
76
|
)
|
|
70
77
|
}
|
|
71
78
|
|
|
72
|
-
let args = [
|
|
73
|
-
|
|
79
|
+
let args = ['--browser', options.getBrowserName(), '--output', 'json']
|
|
80
|
+
|
|
81
|
+
if (options.getBrowserVersion() && options.getBrowserVersion() !== "") {
|
|
82
|
+
args.push("--browser-version", options.getBrowserVersion())
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const vendorOptions = options.get('goog:chromeOptions') || options.get('ms:edgeOptions')
|
|
86
|
+
|| options.get('moz:firefoxOptions')
|
|
87
|
+
if (vendorOptions && vendorOptions.binary && vendorOptions.binary !== "") {
|
|
88
|
+
args.push("--browser-path", '"' + vendorOptions.binary + '"')
|
|
89
|
+
}
|
|
74
90
|
|
|
91
|
+
const smBinary = getBinary()
|
|
92
|
+
const spawnResult = spawnSync(smBinary, args)
|
|
93
|
+
let output
|
|
94
|
+
if (spawnResult.status) {
|
|
95
|
+
let errorMessage
|
|
96
|
+
if (spawnResult.stderr.toString()) {
|
|
97
|
+
errorMessage = spawnResult.stderr.toString()
|
|
98
|
+
}
|
|
99
|
+
if (spawnResult.stdout.toString()) {
|
|
100
|
+
try {
|
|
101
|
+
output = JSON.parse(spawnResult.stdout.toString())
|
|
102
|
+
errorMessage = output.result.message
|
|
103
|
+
} catch (e) {
|
|
104
|
+
errorMessage = e.toString()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
throw new Error(`Error executing command for ${smBinary} with ${args}: ${errorMessage}`)
|
|
108
|
+
}
|
|
75
109
|
try {
|
|
76
|
-
|
|
110
|
+
output = JSON.parse(spawnResult.stdout.toString())
|
|
77
111
|
} catch (e) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`Error executing command with ${args}\n${e.stdout.toString()}${e.stderr.toString()}`
|
|
80
|
-
)
|
|
112
|
+
throw new Error(`Error executing command for ${smBinary} with ${args}: ${e.toString()}`)
|
|
81
113
|
}
|
|
82
114
|
|
|
83
|
-
|
|
84
|
-
|
|
115
|
+
|
|
116
|
+
for (const key in output.logs) {
|
|
117
|
+
if (output.logs[key].level === 'WARN') {
|
|
118
|
+
console.warn(`${output.logs[key].message}`)
|
|
119
|
+
}
|
|
85
120
|
}
|
|
86
121
|
|
|
87
|
-
return result.
|
|
122
|
+
return output.result.message
|
|
88
123
|
}
|
|
89
124
|
|
|
90
125
|
// PUBLIC API
|
package/edge.js
CHANGED
|
@@ -80,7 +80,6 @@
|
|
|
80
80
|
const { Browser } = require('./lib/capabilities')
|
|
81
81
|
const io = require('./io')
|
|
82
82
|
const chromium = require('./chromium')
|
|
83
|
-
const { driverLocation } = require('./common/seleniumManager')
|
|
84
83
|
|
|
85
84
|
/**
|
|
86
85
|
* Name of the EdgeDriver executable.
|
|
@@ -107,28 +106,6 @@ class ServiceBuilder extends chromium.ServiceBuilder {
|
|
|
107
106
|
*/
|
|
108
107
|
constructor(opt_exe) {
|
|
109
108
|
let exe = opt_exe || locateSynchronously()
|
|
110
|
-
|
|
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
|
-
try {
|
|
117
|
-
exe = driverLocation('edge')
|
|
118
|
-
} catch (err) {
|
|
119
|
-
console.log(`Unable to obtain driver using Selenium Manager: ${err}`)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (!exe) {
|
|
124
|
-
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.`
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
109
|
super(exe)
|
|
133
110
|
this.setLoopback(true)
|
|
134
111
|
}
|
package/firefox.js
CHANGED
|
@@ -127,7 +127,7 @@ const webdriver = require('./lib/webdriver')
|
|
|
127
127
|
const zip = require('./io/zip')
|
|
128
128
|
const { Browser, Capabilities } = require('./lib/capabilities')
|
|
129
129
|
const { Zip } = require('./io/zip')
|
|
130
|
-
const {
|
|
130
|
+
const { getPath } = require('./common/driverFinder')
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Thrown when there an add-on is malformed.
|
|
@@ -471,29 +471,7 @@ function locateSynchronously() {
|
|
|
471
471
|
* @throws {Error}
|
|
472
472
|
*/
|
|
473
473
|
function findGeckoDriver() {
|
|
474
|
-
|
|
475
|
-
|
|
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
|
-
try {
|
|
482
|
-
exe = driverLocation(Browser.FIREFOX)
|
|
483
|
-
} catch (err) {
|
|
484
|
-
console.log(`Unable to obtain driver using Selenium Manager: ${err}`)
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
if (!exe) {
|
|
489
|
-
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.`
|
|
493
|
-
)
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
return exe
|
|
474
|
+
return locateSynchronously()
|
|
497
475
|
}
|
|
498
476
|
|
|
499
477
|
/**
|
|
@@ -630,10 +608,16 @@ class Driver extends webdriver.WebDriver {
|
|
|
630
608
|
executor = opt_executor
|
|
631
609
|
configureExecutor(executor)
|
|
632
610
|
} else if (opt_executor instanceof remote.DriverService) {
|
|
611
|
+
if (!opt_executor.getExecutable()) {
|
|
612
|
+
opt_executor.setExecutable(getPath(opt_executor, opt_config))
|
|
613
|
+
}
|
|
633
614
|
executor = createExecutor(opt_executor.start())
|
|
634
615
|
onQuit = () => opt_executor.kill()
|
|
635
616
|
} else {
|
|
636
617
|
let service = new ServiceBuilder().build()
|
|
618
|
+
if (!service.getExecutable()) {
|
|
619
|
+
service.setExecutable(getPath(service, opt_config))
|
|
620
|
+
}
|
|
637
621
|
executor = createExecutor(service.start())
|
|
638
622
|
onQuit = () => service.kill()
|
|
639
623
|
}
|
package/http/index.js
CHANGED
|
@@ -54,7 +54,8 @@ function getRequestOptions(aUrl) {
|
|
|
54
54
|
options.search = null
|
|
55
55
|
options.hash = null
|
|
56
56
|
options.path = options.pathname
|
|
57
|
-
|
|
57
|
+
options.hostname =
|
|
58
|
+
options.hostname === 'localhost' ? '127.0.0.1' : options.hostname // To support Node 17 and above. Refer https://github.com/nodejs/node/issues/40702 for details.
|
|
58
59
|
return options
|
|
59
60
|
}
|
|
60
61
|
|