selenium-webdriver 4.0.0-rc-1 → 4.1.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 +51 -1
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/chrome.js +10 -6
- package/chromium.js +75 -27
- package/devtools/CDPConnection.js +9 -4
- package/devtools/networkinterceptor.js +88 -0
- package/edge.js +8 -6
- package/example/google_search.js +1 -1
- package/firefox.js +39 -17
- package/http/index.js +13 -14
- package/http/util.js +14 -20
- package/index.js +26 -13
- package/io/index.js +58 -55
- package/io/zip.js +1 -3
- package/lib/atoms/find-elements.js +2 -2
- package/lib/atoms/get-attribute.js +25 -25
- package/lib/by.js +8 -9
- package/lib/capabilities.js +1 -1
- package/lib/command.js +6 -11
- package/lib/error.js +24 -19
- package/lib/http.js +64 -156
- package/lib/input.js +1 -1
- package/lib/promise.js +12 -17
- package/lib/proxy.js +15 -5
- package/lib/session.js +1 -1
- package/lib/webdriver.js +422 -176
- package/net/index.js +14 -7
- package/net/portprober.js +5 -4
- package/opera.js +19 -22
- package/package.json +1 -2
- package/remote/index.js +13 -10
- package/testing/index.js +16 -10
package/CHANGES.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
+
## v4.1.1
|
|
2
|
+
|
|
3
|
+
* Add support for installing unpacked addons at runtime in Firefox webdriver (#10216)
|
|
4
|
+
* Enables firefox debugger for devtools test
|
|
5
|
+
* Sets correct browserName when set via SELENIUM_BROWSER fixes #10218
|
|
6
|
+
* add support for Chrome v97
|
|
7
|
+
* Adds new desktop cast command for Chromium #10190 (#10191)
|
|
8
|
+
* ignore errors arising from trying to use file detector fixes #6343
|
|
9
|
+
* Added RelativeBy class on the main api (#10148)
|
|
10
|
+
* Code cleanup and minor improvements
|
|
11
|
+
* Implements 'getDomAttribute' to get attribute value as defined by w3c spec and removes legacy command usages
|
|
12
|
+
* Remove legacy JWP support and w3c<boolean> switch (#10095)
|
|
13
|
+
* update map/filter clean up to common format (#10094)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## v4.1.0
|
|
17
|
+
|
|
18
|
+
* add support for handling Shadow DOM elements
|
|
19
|
+
* Capture browser console logs when using BiDi onLogEvent api
|
|
20
|
+
* add CDP support for v96 and remove v93
|
|
21
|
+
* remove useless package, change io public api import to more common approach (#10037)
|
|
22
|
+
* Fix flaky CDP dom mutation (#10029)
|
|
23
|
+
* Fix edge test failures (#10012)
|
|
24
|
+
* code cleanup second iteration (#9979)
|
|
25
|
+
* Ensure correct serialization of extensions in chromium.Options (#6676)
|
|
26
|
+
* Remove explicit id passing for CDP commands
|
|
27
|
+
* Attach to page target while creating a CDP connection (#10005)
|
|
28
|
+
* Add support for form submit in W3C mode (fixes #9916) (#9936)
|
|
29
|
+
* Fixes relative locator 'locateWith' export
|
|
30
|
+
* update doc string for CDP Commands (#9929)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## v4.0.0
|
|
34
|
+
|
|
35
|
+
* Fixes cdp for Chrome and Firefox (#9909)
|
|
36
|
+
* Add cdp 95 to python and JS
|
|
37
|
+
* Removing unused target for cdpConnection
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## v4.0.0-rc-2
|
|
41
|
+
|
|
42
|
+
* Fix builder test
|
|
43
|
+
* Allow builder to set a single arbitrary capability (#9857)
|
|
44
|
+
* Restore withCapabilities() to ensure backward compatibility
|
|
45
|
+
* Add new websocketUrl capability
|
|
46
|
+
* update ruby, python and JS to add support for v94 and remove support for v92
|
|
47
|
+
* Add a check for Grid CDP endpoint
|
|
48
|
+
* Implement network request interceptions
|
|
49
|
+
* Update connections to devtools so it works in Firefox and Chrome
|
|
50
|
+
|
|
1
51
|
## v4.0.0-rc-1
|
|
2
52
|
|
|
3
53
|
* Deprecates withCapabilities method and removes tests (#9701)
|
|
@@ -498,7 +548,7 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
|
|
|
498
548
|
DriverService instances that run in a child-process. The
|
|
499
549
|
`chrome.ServiceBuilder`, `edge.ServiceBuilder`, and `opera.ServiceBuilder`
|
|
500
550
|
classes now all extend this base class with browser-specific options.
|
|
501
|
-
* For each of the ServiceBuilder
|
|
551
|
+
* For each of the ServiceBuilder classes, renamed `usingPort` and
|
|
502
552
|
`withEnvironment` to `setPort` and `setEnvironment`, respectively.
|
|
503
553
|
* Renamed `chrome.ServiceBuilder#setUrlBasePath` to `#setPath`
|
|
504
554
|
* Changed the signature of the `firefox.Driver` from `(config, flow, executor)`
|
package/LICENSE
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
|
188
188
|
identification within third-party archives.
|
|
189
189
|
|
|
190
|
-
Copyright
|
|
190
|
+
Copyright 2022 Software Freedom Conservancy (SFC)
|
|
191
191
|
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
193
|
you may not use this file except in compliance with the License.
|
package/NOTICE
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Copyright 2011-
|
|
1
|
+
Copyright 2011-2022 Software Freedom Conservancy
|
|
2
2
|
Copyright 2004-2011 Selenium committers
|
package/chrome.js
CHANGED
|
@@ -286,9 +286,13 @@ Driver.getDefaultService = getDefaultService
|
|
|
286
286
|
Driver.prototype.VENDOR_COMMAND_PREFIX = 'goog'
|
|
287
287
|
|
|
288
288
|
// PUBLIC API
|
|
289
|
-
|
|
290
|
-
exports
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
289
|
+
|
|
290
|
+
module.exports = {
|
|
291
|
+
Driver: Driver,
|
|
292
|
+
Options,
|
|
293
|
+
ServiceBuilder ,
|
|
294
|
+
getDefaultService,
|
|
295
|
+
setDefaultService,
|
|
296
|
+
locateSynchronously
|
|
297
|
+
}
|
|
298
|
+
|
package/chromium.js
CHANGED
|
@@ -97,6 +97,7 @@ const Command = {
|
|
|
97
97
|
SET_PERMISSION: 'setPermission',
|
|
98
98
|
GET_CAST_SINKS: 'getCastSinks',
|
|
99
99
|
SET_CAST_SINK_TO_USE: 'setCastSinkToUse',
|
|
100
|
+
START_CAST_DESKTOP_MIRRORING: 'startDesktopMirroring',
|
|
100
101
|
START_CAST_TAB_MIRRORING: 'setCastTabMirroring',
|
|
101
102
|
GET_CAST_ISSUE_MESSAGE: 'getCastIssueMessage',
|
|
102
103
|
STOP_CASTING: 'stopCasting',
|
|
@@ -105,6 +106,7 @@ const Command = {
|
|
|
105
106
|
/**
|
|
106
107
|
* Creates a command executor with support for Chromium's custom commands.
|
|
107
108
|
* @param {!Promise<string>} url The server's URL.
|
|
109
|
+
* @param vendorPrefix
|
|
108
110
|
* @return {!command.Executor} The new command executor.
|
|
109
111
|
*/
|
|
110
112
|
function createExecutor(url, vendorPrefix) {
|
|
@@ -160,6 +162,11 @@ function configureExecutor(executor, vendorPrefix) {
|
|
|
160
162
|
'POST',
|
|
161
163
|
`/session/:sessionId/${vendorPrefix}/cast/set_sink_to_use`
|
|
162
164
|
)
|
|
165
|
+
executor.defineCommand(
|
|
166
|
+
Command.START_CAST_DESKTOP_MIRRORING,
|
|
167
|
+
'POST',
|
|
168
|
+
`/session/:sessionId/${vendorPrefix}/cast/start_desktop_mirroring`
|
|
169
|
+
)
|
|
163
170
|
executor.defineCommand(
|
|
164
171
|
Command.START_CAST_TAB_MIRRORING,
|
|
165
172
|
'POST',
|
|
@@ -217,8 +224,8 @@ class ServiceBuilder extends remote.DriverService.Builder {
|
|
|
217
224
|
* Enables Chrome logging.
|
|
218
225
|
* @returns {!ServiceBuilder} A self reference.
|
|
219
226
|
*/
|
|
220
|
-
|
|
221
|
-
return this.addArguments('--enable-chrome-logs')
|
|
227
|
+
enableChromeLogging() {
|
|
228
|
+
return this.addArguments('--enable-chrome-logs')
|
|
222
229
|
}
|
|
223
230
|
|
|
224
231
|
/**
|
|
@@ -292,7 +299,7 @@ class Options extends Capabilities {
|
|
|
292
299
|
* @return {!Options} A self reference.
|
|
293
300
|
*/
|
|
294
301
|
debuggerAddress(address) {
|
|
295
|
-
this.options_.debuggerAddress = address
|
|
302
|
+
this.options_.debuggerAddress = address
|
|
296
303
|
return this
|
|
297
304
|
}
|
|
298
305
|
|
|
@@ -358,8 +365,11 @@ class Options extends Capabilities {
|
|
|
358
365
|
* @return {!Options} A self reference.
|
|
359
366
|
*/
|
|
360
367
|
addExtensions(...args) {
|
|
361
|
-
let
|
|
362
|
-
|
|
368
|
+
let extensions = this.options_.extensions || new Extensions()
|
|
369
|
+
extensions.add(...args)
|
|
370
|
+
if (extensions.length) {
|
|
371
|
+
this.options_.extensions = extensions
|
|
372
|
+
}
|
|
363
373
|
return this
|
|
364
374
|
}
|
|
365
375
|
|
|
@@ -584,28 +594,47 @@ class Options extends Capabilities {
|
|
|
584
594
|
}
|
|
585
595
|
return this
|
|
586
596
|
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* A list of extensions to install when launching the browser.
|
|
601
|
+
*/
|
|
602
|
+
class Extensions {
|
|
603
|
+
constructor() {
|
|
604
|
+
this.extensions = []
|
|
605
|
+
}
|
|
587
606
|
|
|
588
607
|
/**
|
|
589
|
-
*
|
|
590
|
-
|
|
608
|
+
* @return {number} The length of the extensions list.
|
|
609
|
+
*/
|
|
610
|
+
get length() {
|
|
611
|
+
return this.extensions.length
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Add additional extensions to install when launching the browser. Each
|
|
616
|
+
* extension should be specified as the path to the packed CRX file, or a
|
|
617
|
+
* Buffer for an extension.
|
|
591
618
|
*
|
|
592
|
-
* @
|
|
593
|
-
*
|
|
619
|
+
* @param {...(string|!Buffer|!Array<(string|!Buffer)>)} args The
|
|
620
|
+
* extensions to add.
|
|
621
|
+
*/
|
|
622
|
+
add(...args) {
|
|
623
|
+
this.extensions = this.extensions.concat(...args)
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* @return {!Object} A serialized representation of this Extensions object.
|
|
594
628
|
*/
|
|
595
629
|
[Symbols.serialize]() {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
extension
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
.read(/** @type {string} */ (extension))
|
|
605
|
-
.then((buffer) => buffer.toString('base64'))
|
|
606
|
-
})
|
|
607
|
-
}
|
|
608
|
-
return super[Symbols.serialize]()
|
|
630
|
+
return this.extensions.map(function (extension) {
|
|
631
|
+
if (Buffer.isBuffer(extension)) {
|
|
632
|
+
return extension.toString('base64')
|
|
633
|
+
}
|
|
634
|
+
return io
|
|
635
|
+
.read(/** @type {string} */ (extension))
|
|
636
|
+
.then((buffer) => buffer.toString('base64'))
|
|
637
|
+
})
|
|
609
638
|
}
|
|
610
639
|
}
|
|
611
640
|
|
|
@@ -725,11 +754,11 @@ class Driver extends webdriver.WebDriver {
|
|
|
725
754
|
}
|
|
726
755
|
|
|
727
756
|
/**
|
|
728
|
-
*
|
|
757
|
+
* Sends an arbitrary devtools command to the browser and get the result.
|
|
729
758
|
*
|
|
730
759
|
* @param {string} cmd The name of the command to send.
|
|
731
760
|
* @param {Object=} params The command parameters.
|
|
732
|
-
* @return {!Promise<
|
|
761
|
+
* @return {!Promise<string>} A promise that will be resolved when the command
|
|
733
762
|
* has finished.
|
|
734
763
|
* @see <https://chromedevtools.github.io/devtools-protocol/>
|
|
735
764
|
*/
|
|
@@ -811,6 +840,23 @@ class Driver extends webdriver.WebDriver {
|
|
|
811
840
|
)
|
|
812
841
|
}
|
|
813
842
|
|
|
843
|
+
/**
|
|
844
|
+
* Initiates desktop mirroring for the current browser tab on the specified device.
|
|
845
|
+
*
|
|
846
|
+
* @param {String} deviceName name of the target device.
|
|
847
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
848
|
+
* when the mirror command has been issued to the device.
|
|
849
|
+
*/
|
|
850
|
+
startDesktopMirroring(deviceName) {
|
|
851
|
+
return this.schedule(
|
|
852
|
+
new command.Command(Command.START_CAST_DESKTOP_MIRRORING).setParameter(
|
|
853
|
+
'sinkName',
|
|
854
|
+
deviceName
|
|
855
|
+
),
|
|
856
|
+
'Driver.startDesktopMirroring(' + deviceName + ')'
|
|
857
|
+
)
|
|
858
|
+
}
|
|
859
|
+
|
|
814
860
|
/**
|
|
815
861
|
* Initiates tab mirroring for the current browser tab on the specified device.
|
|
816
862
|
*
|
|
@@ -860,6 +906,8 @@ class Driver extends webdriver.WebDriver {
|
|
|
860
906
|
|
|
861
907
|
// PUBLIC API
|
|
862
908
|
|
|
863
|
-
exports
|
|
864
|
-
|
|
865
|
-
|
|
909
|
+
module.exports = {
|
|
910
|
+
Driver,
|
|
911
|
+
Options,
|
|
912
|
+
ServiceBuilder,
|
|
913
|
+
}
|
|
@@ -18,16 +18,21 @@
|
|
|
18
18
|
class CDPConnection {
|
|
19
19
|
constructor(wsConnection) {
|
|
20
20
|
this._wsConnection = wsConnection
|
|
21
|
+
this.cmd_id = 0
|
|
22
|
+
this.targetID = null;
|
|
23
|
+
this.sessionId = null
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
execute(method,
|
|
24
|
-
|
|
26
|
+
execute(method, params, callback) {
|
|
27
|
+
let message = {
|
|
25
28
|
method,
|
|
26
|
-
id:
|
|
29
|
+
id: this.cmd_id++,
|
|
30
|
+
}
|
|
31
|
+
if (this.sessionId) {
|
|
32
|
+
message['sessionId'] = this.sessionId
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
const mergedMessage = Object.assign({ params: params }, message)
|
|
30
|
-
|
|
31
36
|
this._wsConnection.send(JSON.stringify(mergedMessage), callback)
|
|
32
37
|
}
|
|
33
38
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
class HttpResponse {
|
|
19
|
+
/**
|
|
20
|
+
* Creates a HTTP Response that will be used to
|
|
21
|
+
* mock out network interceptions.
|
|
22
|
+
* @param {*} urlToIntercept
|
|
23
|
+
*/
|
|
24
|
+
constructor(urlToIntercept = '') {
|
|
25
|
+
this.returnBody = ''
|
|
26
|
+
this.returnHeaders = []
|
|
27
|
+
this.returnMethod = 'GET'
|
|
28
|
+
this.returnStatus = 200
|
|
29
|
+
this.urlToIntercept = urlToIntercept
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Add headers that will be returned when we intercept
|
|
34
|
+
* a HTTP Request
|
|
35
|
+
* @param {*} header
|
|
36
|
+
* @param {*} value
|
|
37
|
+
*/
|
|
38
|
+
addHeaders(header, value) {
|
|
39
|
+
this.returnHeaders.push({ name: header, value: value })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get headers() {
|
|
43
|
+
return this.returnHeaders
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Set the STATUS value of the returned HTTP Request
|
|
48
|
+
* @param {*} value
|
|
49
|
+
*/
|
|
50
|
+
set status(value) {
|
|
51
|
+
// Add in check that his should be a number
|
|
52
|
+
this.returnStatus = value
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get status() {
|
|
56
|
+
return this.returnStatus
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Sets the value of the body of the HTTP Request that
|
|
61
|
+
* will be returned.
|
|
62
|
+
* @param {*} value
|
|
63
|
+
*/
|
|
64
|
+
set body(value) {
|
|
65
|
+
this.returnBody = value
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get body() {
|
|
69
|
+
let buff = Buffer.from(this.returnBody, 'utf-8')
|
|
70
|
+
return buff.toString('base64')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Sets the method of the HTTP Request
|
|
75
|
+
* @param {*} value the method of the request.
|
|
76
|
+
*/
|
|
77
|
+
set method(value) {
|
|
78
|
+
this.returnMethod = value
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns the Method to be used in the intercept
|
|
83
|
+
*/
|
|
84
|
+
get method() {
|
|
85
|
+
return this.returnMethod
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.HttpResponse = HttpResponse
|
package/edge.js
CHANGED
|
@@ -210,9 +210,11 @@ Driver.getDefaultService = getDefaultService
|
|
|
210
210
|
|
|
211
211
|
// PUBLIC API
|
|
212
212
|
|
|
213
|
-
exports
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
213
|
+
module.exports = {
|
|
214
|
+
Driver,
|
|
215
|
+
Options,
|
|
216
|
+
ServiceBuilder,
|
|
217
|
+
getDefaultService,
|
|
218
|
+
setDefaultService,
|
|
219
|
+
locateSynchronously,
|
|
220
|
+
}
|
package/example/google_search.js
CHANGED
package/firefox.js
CHANGED
|
@@ -116,6 +116,7 @@
|
|
|
116
116
|
|
|
117
117
|
'use strict'
|
|
118
118
|
|
|
119
|
+
const fs = require('fs')
|
|
119
120
|
const path = require('path')
|
|
120
121
|
const Symbols = require('./lib/symbols')
|
|
121
122
|
const command = require('./lib/command')
|
|
@@ -222,7 +223,7 @@ async function buildProfile(template, extensions) {
|
|
|
222
223
|
dir = await io.tmpDir()
|
|
223
224
|
if (template) {
|
|
224
225
|
await io.copyDir(
|
|
225
|
-
/** @type {string} */(template),
|
|
226
|
+
/** @type {string} */ (template),
|
|
226
227
|
dir,
|
|
227
228
|
/(parent\.lock|lock|\.parentlock)/
|
|
228
229
|
)
|
|
@@ -400,7 +401,11 @@ class Options extends Capabilities {
|
|
|
400
401
|
* @param {string} androidPackage The package to use
|
|
401
402
|
* @return {!Options} A self reference
|
|
402
403
|
*/
|
|
403
|
-
enableMobile(
|
|
404
|
+
enableMobile(
|
|
405
|
+
androidPackage = 'org.mozilla.firefox',
|
|
406
|
+
androidActivity = null,
|
|
407
|
+
deviceSerial = null
|
|
408
|
+
) {
|
|
404
409
|
this.firefoxOptions_().androidPackage = androidPackage
|
|
405
410
|
|
|
406
411
|
if (androidActivity) {
|
|
@@ -411,6 +416,13 @@ class Options extends Capabilities {
|
|
|
411
416
|
}
|
|
412
417
|
return this
|
|
413
418
|
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Enables moz:debuggerAddress for firefox cdp
|
|
422
|
+
*/
|
|
423
|
+
enableDebugger() {
|
|
424
|
+
return this.set('moz:debuggerAddress', true)
|
|
425
|
+
}
|
|
414
426
|
}
|
|
415
427
|
|
|
416
428
|
/**
|
|
@@ -450,11 +462,11 @@ function findGeckoDriver() {
|
|
|
450
462
|
if (!exe) {
|
|
451
463
|
throw Error(
|
|
452
464
|
'The ' +
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
465
|
+
GECKO_DRIVER_EXE +
|
|
466
|
+
' executable could not be found on the current ' +
|
|
467
|
+
'PATH. Please download the latest version from ' +
|
|
468
|
+
'https://github.com/mozilla/geckodriver/releases/ ' +
|
|
469
|
+
'and ensure it can be found on your PATH.'
|
|
458
470
|
)
|
|
459
471
|
}
|
|
460
472
|
return exe
|
|
@@ -475,8 +487,8 @@ function findInProgramFiles(file) {
|
|
|
475
487
|
return exists
|
|
476
488
|
? files[0]
|
|
477
489
|
: io.exists(files[1]).then(function (exists) {
|
|
478
|
-
|
|
479
|
-
|
|
490
|
+
return exists ? files[1] : null
|
|
491
|
+
})
|
|
480
492
|
})
|
|
481
493
|
}
|
|
482
494
|
|
|
@@ -610,7 +622,7 @@ class Driver extends webdriver.WebDriver {
|
|
|
610
622
|
* implementation.
|
|
611
623
|
* @override
|
|
612
624
|
*/
|
|
613
|
-
setFileDetector() {
|
|
625
|
+
setFileDetector() {}
|
|
614
626
|
|
|
615
627
|
/**
|
|
616
628
|
* Get the context that is currently in effect.
|
|
@@ -659,7 +671,15 @@ class Driver extends webdriver.WebDriver {
|
|
|
659
671
|
* @see #uninstallAddon
|
|
660
672
|
*/
|
|
661
673
|
async installAddon(path, temporary = false) {
|
|
662
|
-
let
|
|
674
|
+
let stats = fs.statSync(path)
|
|
675
|
+
let buf;
|
|
676
|
+
if (stats.isDirectory()) {
|
|
677
|
+
let zip = new Zip()
|
|
678
|
+
await zip.addDir(path)
|
|
679
|
+
buf = await zip.toBuffer('DEFLATE')
|
|
680
|
+
} else {
|
|
681
|
+
buf = await io.read(path)
|
|
682
|
+
}
|
|
663
683
|
return this.execute(
|
|
664
684
|
new command.Command(ExtensionCommand.INSTALL_ADDON)
|
|
665
685
|
.setParameter('addon', buf.toString('base64'))
|
|
@@ -798,9 +818,11 @@ Channel.NIGHTLY = new Channel(
|
|
|
798
818
|
|
|
799
819
|
// PUBLIC API
|
|
800
820
|
|
|
801
|
-
exports
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
821
|
+
module.exports = {
|
|
822
|
+
Channel,
|
|
823
|
+
Context,
|
|
824
|
+
Driver,
|
|
825
|
+
Options,
|
|
826
|
+
ServiceBuilder,
|
|
827
|
+
locateSynchronously,
|
|
828
|
+
}
|
package/http/index.js
CHANGED
|
@@ -37,7 +37,7 @@ const httpLib = require('../lib/http')
|
|
|
37
37
|
* path: (?string|undefined),
|
|
38
38
|
* pathname: (?string|undefined)}}
|
|
39
39
|
*/
|
|
40
|
-
|
|
40
|
+
let RequestOptions // eslint-disable-line
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* @param {string} aUrl The request URL to parse.
|
|
@@ -100,9 +100,7 @@ class HttpClient {
|
|
|
100
100
|
*/
|
|
101
101
|
this.keepAlive = this.client_options['keep-alive']
|
|
102
102
|
|
|
103
|
-
/**
|
|
104
|
-
* @private {?RequestOptions}
|
|
105
|
-
*/
|
|
103
|
+
/** @private {?RequestOptions} */
|
|
106
104
|
this.proxyOptions_ = opt_proxy ? getRequestOptions(opt_proxy) : null
|
|
107
105
|
}
|
|
108
106
|
|
|
@@ -219,9 +217,10 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
219
217
|
let requestFn = options.protocol === 'https:' ? https.request : http.request
|
|
220
218
|
var request = requestFn(options, function onResponse(response) {
|
|
221
219
|
if (response.statusCode == 302 || response.statusCode == 303) {
|
|
220
|
+
let location
|
|
222
221
|
try {
|
|
223
222
|
// eslint-disable-next-line node/no-deprecated-api
|
|
224
|
-
|
|
223
|
+
location = url.parse(response.headers['location'])
|
|
225
224
|
} catch (ex) {
|
|
226
225
|
onError(
|
|
227
226
|
Error(
|
|
@@ -240,7 +239,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
240
239
|
location.auth = options.auth
|
|
241
240
|
}
|
|
242
241
|
|
|
243
|
-
request.
|
|
242
|
+
request.destroy()
|
|
244
243
|
sendRequest(
|
|
245
244
|
{
|
|
246
245
|
method: 'GET',
|
|
@@ -265,10 +264,10 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
265
264
|
return
|
|
266
265
|
}
|
|
267
266
|
|
|
268
|
-
|
|
267
|
+
const body = []
|
|
269
268
|
response.on('data', body.push.bind(body))
|
|
270
269
|
response.on('end', function () {
|
|
271
|
-
|
|
270
|
+
const resp = new httpLib.Response(
|
|
272
271
|
/** @type {number} */ (response.statusCode),
|
|
273
272
|
/** @type {!Object<string>} */ (response.headers),
|
|
274
273
|
Buffer.concat(body).toString('utf8').replace(/\0/g, '')
|
|
@@ -288,7 +287,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
288
287
|
sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries)
|
|
289
288
|
}, 15)
|
|
290
289
|
} else {
|
|
291
|
-
|
|
290
|
+
let message = e.message
|
|
292
291
|
if (e.code) {
|
|
293
292
|
message = e.code + ' ' + message
|
|
294
293
|
}
|
|
@@ -339,8 +338,8 @@ function isRetryableNetworkError(err) {
|
|
|
339
338
|
|
|
340
339
|
// PUBLIC API
|
|
341
340
|
|
|
342
|
-
exports.Agent = http.Agent
|
|
343
|
-
exports.Executor = httpLib.Executor
|
|
344
|
-
exports.HttpClient = HttpClient
|
|
345
|
-
exports.Request = httpLib.Request
|
|
346
|
-
exports.Response = httpLib.Response
|
|
341
|
+
module.exports.Agent = http.Agent
|
|
342
|
+
module.exports.Executor = httpLib.Executor
|
|
343
|
+
module.exports.HttpClient = HttpClient
|
|
344
|
+
module.exports.Request = httpLib.Request
|
|
345
|
+
module.exports.Response = httpLib.Response
|
package/http/util.js
CHANGED
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
|
|
22
22
|
'use strict'
|
|
23
23
|
|
|
24
|
-
const Executor = require('./index').Executor
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
const Executor = require('./index').Executor
|
|
25
|
+
const HttpClient = require('./index').HttpClient
|
|
26
|
+
const HttpRequest = require('./index').Request
|
|
27
|
+
const Command = require('../lib/command').Command
|
|
28
|
+
const CommandName = require('../lib/command').Name
|
|
29
|
+
const error = require('../lib/error')
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Queries a WebDriver server for its current status.
|
|
@@ -43,18 +43,6 @@ function getStatus(url) {
|
|
|
43
43
|
|
|
44
44
|
class CancellationError {}
|
|
45
45
|
|
|
46
|
-
// PUBLIC API
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Queries a WebDriver server for its current status.
|
|
50
|
-
* @param {string} url Base URL of the server to query.
|
|
51
|
-
* @return {!Promise<!Object>} A promise that resolves with
|
|
52
|
-
* a hash of the server status.
|
|
53
|
-
*/
|
|
54
|
-
exports.getStatus = getStatus
|
|
55
|
-
|
|
56
|
-
exports.CancellationError = CancellationError
|
|
57
|
-
|
|
58
46
|
/**
|
|
59
47
|
* Waits for a WebDriver server to be healthy and accepting requests.
|
|
60
48
|
* @param {string} url Base URL of the server to query.
|
|
@@ -65,7 +53,7 @@ exports.CancellationError = CancellationError
|
|
|
65
53
|
* @return {!Promise} A promise that will resolve when the server is ready, or
|
|
66
54
|
* if the wait is cancelled.
|
|
67
55
|
*/
|
|
68
|
-
|
|
56
|
+
function waitForServer(url, timeout, opt_cancelToken) {
|
|
69
57
|
return new Promise((onResolve, onReject) => {
|
|
70
58
|
let start = Date.now()
|
|
71
59
|
|
|
@@ -120,7 +108,7 @@ exports.waitForServer = function (url, timeout, opt_cancelToken) {
|
|
|
120
108
|
* @return {!Promise} A promise that will resolve when a 2xx is received from
|
|
121
109
|
* the given URL, or if the wait is cancelled.
|
|
122
110
|
*/
|
|
123
|
-
|
|
111
|
+
function waitForUrl(url, timeout, opt_cancelToken) {
|
|
124
112
|
return new Promise((onResolve, onReject) => {
|
|
125
113
|
let client = new HttpClient(url)
|
|
126
114
|
let request = new HttpRequest('GET', '')
|
|
@@ -170,3 +158,9 @@ exports.waitForUrl = function (url, timeout, opt_cancelToken) {
|
|
|
170
158
|
}
|
|
171
159
|
})
|
|
172
160
|
}
|
|
161
|
+
|
|
162
|
+
// PUBLIC API
|
|
163
|
+
module.exports.getStatus = getStatus
|
|
164
|
+
module.exports.CancellationError = CancellationError
|
|
165
|
+
module.exports.waitForServer = waitForServer
|
|
166
|
+
module.exports.waitForUrl = waitForUrl
|