selenium-webdriver 4.0.0-beta.4 → 4.1.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 +55 -1
- package/README.md +4 -2
- package/chromium.js +67 -25
- package/devtools/CDPConnection.js +9 -4
- package/devtools/networkinterceptor.js +88 -0
- package/edge.js +14 -20
- package/firefox.js +25 -1
- package/http/index.js +36 -15
- package/http/util.js +14 -20
- package/ie.js +8 -8
- package/index.js +17 -1
- package/io/index.js +47 -46
- package/lib/atoms/find-elements.js +2 -2
- package/lib/atoms/get-attribute.js +25 -25
- package/lib/by.js +42 -24
- package/lib/capabilities.js +11 -2
- package/lib/command.js +5 -0
- package/lib/error.js +24 -0
- package/lib/http.js +12 -7
- package/lib/input.js +4 -15
- package/lib/webdriver.js +372 -129
- package/net/portprober.js +1 -1
- package/opera.js +3 -3
- package/package.json +2 -3
- package/remote/index.js +3 -3
- package/testing/index.js +9 -10
package/CHANGES.md
CHANGED
|
@@ -1,3 +1,57 @@
|
|
|
1
|
+
## v4.1.0
|
|
2
|
+
|
|
3
|
+
* add support for handling Shadow DOM elements
|
|
4
|
+
* Capture browser console logs when using BiDi onLogEvent api
|
|
5
|
+
* add CDP support for v96 and remove v93
|
|
6
|
+
* remove useless package, change io public api import to more common approach (#10037)
|
|
7
|
+
* Fix flaky CDP dom mutation (#10029)
|
|
8
|
+
* Fix edge test failures (#10012)
|
|
9
|
+
* code cleanup second iteration (#9979)
|
|
10
|
+
* Ensure correct serialization of extensions in chromium.Options (#6676)
|
|
11
|
+
* Remove explicit id passing for CDP commands
|
|
12
|
+
* Attach to page target while creating a CDP connection (#10005)
|
|
13
|
+
* Add support for form submit in W3C mode (fixes #9916) (#9936)
|
|
14
|
+
* Fixes relative locator 'locateWith' export
|
|
15
|
+
* update doc string for CDP Commands (#9929)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## v4.0.0
|
|
19
|
+
|
|
20
|
+
* Fixes cdp for Chrome and Firefox (#9909)
|
|
21
|
+
* Add cdp 95 to python and JS
|
|
22
|
+
* Removing unused target for cdpConnection
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## v4.0.0-rc-2
|
|
26
|
+
|
|
27
|
+
* Fix builder test
|
|
28
|
+
* Allow builder to set a single arbitrary capability (#9857)
|
|
29
|
+
* Restore withCapabilities() to ensure backward compatibility
|
|
30
|
+
* Add new websocketUrl capability
|
|
31
|
+
* update ruby, python and JS to add support for v94 and remove support for v92
|
|
32
|
+
* Add a check for Grid CDP endpoint
|
|
33
|
+
* Implement network request interceptions
|
|
34
|
+
* Update connections to devtools so it works in Firefox and Chrome
|
|
35
|
+
|
|
36
|
+
## v4.0.0-rc-1
|
|
37
|
+
|
|
38
|
+
* Deprecates withCapabilities method and removes tests (#9701)
|
|
39
|
+
* expose `withLocator` method at the top level
|
|
40
|
+
* Enables Mobile feature for Firefox (Still need to expand this to chromium based browsers)
|
|
41
|
+
|
|
42
|
+
* Add the ability to do Relative Locators with all By types. Fixes #9559
|
|
43
|
+
* Add default Opera capabilities. Fixes #9654
|
|
44
|
+
* Add support for ChromeDriver `--enable-chrome-logs` (#9575) [Author: Mark Stacey]
|
|
45
|
+
|
|
46
|
+
The `--enable-chrome-logs` ChromeDriver option can now be enabled using
|
|
47
|
+
the Chromium (or Chrome) ServiceBuilder, similarly to the other options
|
|
48
|
+
provided by ChromeDriver.
|
|
49
|
+
|
|
50
|
+
* Add the debuggerAddress option to chromium.js (#9561) [Author: Brandon Walderman]
|
|
51
|
+
* Adds http client options (#9638)[Author: Dharin Shah]
|
|
52
|
+
* Updating edge.js to extend chromium.driver (fixes #9626)
|
|
53
|
+
|
|
54
|
+
|
|
1
55
|
## v4.0.0-beta.4
|
|
2
56
|
|
|
3
57
|
* Add windowTypes option support for ChromiumDriver (#7897)
|
|
@@ -479,7 +533,7 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
|
|
|
479
533
|
DriverService instances that run in a child-process. The
|
|
480
534
|
`chrome.ServiceBuilder`, `edge.ServiceBuilder`, and `opera.ServiceBuilder`
|
|
481
535
|
classes now all extend this base class with browser-specific options.
|
|
482
|
-
* For each of the ServiceBuilder
|
|
536
|
+
* For each of the ServiceBuilder classes, renamed `usingPort` and
|
|
483
537
|
`withEnvironment` to `setPort` and `setEnvironment`, respectively.
|
|
484
538
|
* Renamed `chrome.ServiceBuilder#setUrlBasePath` to `#setPath`
|
|
485
539
|
* Changed the signature of the `firefox.Driver` from `(config, flow, executor)`
|
package/README.md
CHANGED
|
@@ -223,7 +223,9 @@ under the License.
|
|
|
223
223
|
[edge]: http://go.microsoft.com/fwlink/?LinkId=619687
|
|
224
224
|
[geckodriver]: https://github.com/mozilla/geckodriver/releases/
|
|
225
225
|
[reduction]: http://www.webkit.org/quality/reduction.html
|
|
226
|
-
|
|
226
|
+
|
|
227
|
+
[release]: https://www.selenium.dev/downloads/
|
|
228
|
+
|
|
227
229
|
[users]: https://groups.google.com/forum/#!forum/selenium-users
|
|
228
230
|
[safaridriver]: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html#//apple_ref/doc/uid/TP40014305-CH11-DontLinkElementID_28
|
|
229
|
-
[operadriver]: https://github.com/operasoftware/operachromiumdriver/releases
|
|
231
|
+
[operadriver]: https://github.com/operasoftware/operachromiumdriver/releases
|
package/chromium.js
CHANGED
|
@@ -213,6 +213,14 @@ class ServiceBuilder extends remote.DriverService.Builder {
|
|
|
213
213
|
return this.addArguments('--log-path=' + path)
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Enables Chrome logging.
|
|
218
|
+
* @returns {!ServiceBuilder} A self reference.
|
|
219
|
+
*/
|
|
220
|
+
enableChromeLogging() {
|
|
221
|
+
return this.addArguments('--enable-chrome-logs');
|
|
222
|
+
}
|
|
223
|
+
|
|
216
224
|
/**
|
|
217
225
|
* Enables verbose logging.
|
|
218
226
|
* @return {!ServiceBuilder} A self reference.
|
|
@@ -275,6 +283,19 @@ class Options extends Capabilities {
|
|
|
275
283
|
return this
|
|
276
284
|
}
|
|
277
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Sets the address of a Chromium remote debugging server to connect to.
|
|
288
|
+
* Address should be of the form "{hostname|IP address}:port"
|
|
289
|
+
* (e.g. "localhost:9222").
|
|
290
|
+
*
|
|
291
|
+
* @param {string} address The address to connect to.
|
|
292
|
+
* @return {!Options} A self reference.
|
|
293
|
+
*/
|
|
294
|
+
debuggerAddress(address) {
|
|
295
|
+
this.options_.debuggerAddress = address;
|
|
296
|
+
return this
|
|
297
|
+
}
|
|
298
|
+
|
|
278
299
|
/**
|
|
279
300
|
* Configures the driver to start the browser in headless mode.
|
|
280
301
|
*
|
|
@@ -337,8 +358,11 @@ class Options extends Capabilities {
|
|
|
337
358
|
* @return {!Options} A self reference.
|
|
338
359
|
*/
|
|
339
360
|
addExtensions(...args) {
|
|
340
|
-
let
|
|
341
|
-
|
|
361
|
+
let extensions = this.options_.extensions || new Extensions()
|
|
362
|
+
extensions.add(...args)
|
|
363
|
+
if (extensions.length) {
|
|
364
|
+
this.options_.extensions = extensions
|
|
365
|
+
}
|
|
342
366
|
return this
|
|
343
367
|
}
|
|
344
368
|
|
|
@@ -557,35 +581,53 @@ class Options extends Capabilities {
|
|
|
557
581
|
* @return {!Options} A self reference.
|
|
558
582
|
*/
|
|
559
583
|
windowTypes(...args) {
|
|
560
|
-
let windowTypes = (this.options_.windowTypes || []).concat(...args)
|
|
584
|
+
let windowTypes = (this.options_.windowTypes || []).concat(...args)
|
|
561
585
|
if (windowTypes.length) {
|
|
562
|
-
this.options_.windowTypes = windowTypes
|
|
586
|
+
this.options_.windowTypes = windowTypes
|
|
563
587
|
}
|
|
564
|
-
return this
|
|
588
|
+
return this
|
|
565
589
|
}
|
|
590
|
+
}
|
|
566
591
|
|
|
592
|
+
/**
|
|
593
|
+
* A list of extensions to install when launching the browser.
|
|
594
|
+
*/
|
|
595
|
+
class Extensions {
|
|
596
|
+
constructor() {
|
|
597
|
+
this.extensions = []
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* @return {number} The length of the extensions list.
|
|
602
|
+
*/
|
|
603
|
+
get length() {
|
|
604
|
+
return this.extensions.length
|
|
605
|
+
}
|
|
567
606
|
|
|
568
607
|
/**
|
|
569
|
-
*
|
|
570
|
-
*
|
|
608
|
+
* Add additional extensions to install when launching the browser. Each
|
|
609
|
+
* extension should be specified as the path to the packed CRX file, or a
|
|
610
|
+
* Buffer for an extension.
|
|
571
611
|
*
|
|
572
|
-
* @
|
|
573
|
-
*
|
|
612
|
+
* @param {...(string|!Buffer|!Array<(string|!Buffer)>)} args The
|
|
613
|
+
* extensions to add.
|
|
614
|
+
*/
|
|
615
|
+
add(...args) {
|
|
616
|
+
this.extensions = this.extensions.concat(...args)
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* @return {!Object} A serialized representation of this Extensions object.
|
|
574
621
|
*/
|
|
575
622
|
[Symbols.serialize]() {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
extension
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
.read(/** @type {string} */(extension))
|
|
585
|
-
.then((buffer) => buffer.toString('base64'))
|
|
586
|
-
})
|
|
587
|
-
}
|
|
588
|
-
return super[Symbols.serialize]()
|
|
623
|
+
return this.extensions.map(function (extension) {
|
|
624
|
+
if (Buffer.isBuffer(extension)) {
|
|
625
|
+
return extension.toString('base64')
|
|
626
|
+
}
|
|
627
|
+
return io
|
|
628
|
+
.read(/** @type {string} */ (extension))
|
|
629
|
+
.then((buffer) => buffer.toString('base64'))
|
|
630
|
+
})
|
|
589
631
|
}
|
|
590
632
|
}
|
|
591
633
|
|
|
@@ -634,7 +676,7 @@ class Driver extends webdriver.WebDriver {
|
|
|
634
676
|
* implementation.
|
|
635
677
|
* @override
|
|
636
678
|
*/
|
|
637
|
-
setFileDetector() {
|
|
679
|
+
setFileDetector() {}
|
|
638
680
|
|
|
639
681
|
/**
|
|
640
682
|
* Schedules a command to launch Chrome App with given ID.
|
|
@@ -705,11 +747,11 @@ class Driver extends webdriver.WebDriver {
|
|
|
705
747
|
}
|
|
706
748
|
|
|
707
749
|
/**
|
|
708
|
-
*
|
|
750
|
+
* Sends an arbitrary devtools command to the browser and get the result.
|
|
709
751
|
*
|
|
710
752
|
* @param {string} cmd The name of the command to send.
|
|
711
753
|
* @param {Object=} params The command parameters.
|
|
712
|
-
* @return {!Promise<
|
|
754
|
+
* @return {!Promise<string>} A promise that will be resolved when the command
|
|
713
755
|
* has finished.
|
|
714
756
|
* @see <https://chromedevtools.github.io/devtools-protocol/>
|
|
715
757
|
*/
|
|
@@ -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
|
@@ -80,8 +80,6 @@
|
|
|
80
80
|
const { Browser } = require('./lib/capabilities')
|
|
81
81
|
const io = require('./io')
|
|
82
82
|
const chromium = require('./chromium')
|
|
83
|
-
const http = require('./http')
|
|
84
|
-
const webdriver = require('./lib/webdriver')
|
|
85
83
|
|
|
86
84
|
/**
|
|
87
85
|
* Name of the EdgeDriver executable.
|
|
@@ -111,10 +109,10 @@ class ServiceBuilder extends chromium.ServiceBuilder {
|
|
|
111
109
|
let exe = opt_exe || locateSynchronously()
|
|
112
110
|
if (!exe) {
|
|
113
111
|
throw Error(
|
|
114
|
-
`The WebDriver for Edge could not be found on the current PATH. Please download the
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
`The WebDriver for Edge could not be found on the current PATH. Please download the ` +
|
|
113
|
+
`latest version of ${EDGEDRIVER_CHROMIUM_EXE} from ` +
|
|
114
|
+
`https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ ` +
|
|
115
|
+
`and ensure it can be found on your PATH.`
|
|
118
116
|
)
|
|
119
117
|
}
|
|
120
118
|
super(exe)
|
|
@@ -143,24 +141,20 @@ class Options extends chromium.Options {
|
|
|
143
141
|
/**
|
|
144
142
|
* Creates a new WebDriver client for Microsoft's Edge.
|
|
145
143
|
*/
|
|
146
|
-
class Driver extends
|
|
144
|
+
class Driver extends chromium.Driver {
|
|
147
145
|
/**
|
|
148
146
|
* Creates a new browser session for Microsoft's Edge browser.
|
|
149
147
|
*
|
|
150
|
-
* @param {(Capabilities|Options)=}
|
|
151
|
-
* @param {remote.DriverService=}
|
|
148
|
+
* @param {(Capabilities|Options)=} opt_config The configuration options.
|
|
149
|
+
* @param {remote.DriverService=} opt_serviceExecutor The service to use; will create
|
|
152
150
|
* a new Legacy or Chromium service based on {@linkplain Options} by default.
|
|
153
151
|
* @return {!Driver} A new driver instance.
|
|
154
152
|
*/
|
|
155
|
-
static createSession(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return /** @type {!Driver} */ (super.createSession(executor, options, () =>
|
|
162
|
-
service.kill()
|
|
163
|
-
))
|
|
153
|
+
static createSession(opt_config, opt_serviceExecutor) {
|
|
154
|
+
let caps = opt_config || new Options()
|
|
155
|
+
return /** @type {!Driver} */ (
|
|
156
|
+
super.createSession(caps, opt_serviceExecutor)
|
|
157
|
+
)
|
|
164
158
|
}
|
|
165
159
|
|
|
166
160
|
/**
|
|
@@ -180,7 +174,7 @@ function setDefaultService(service) {
|
|
|
180
174
|
if (defaultService && defaultService.isRunning()) {
|
|
181
175
|
throw Error(
|
|
182
176
|
'The previously configured EdgeDriver service is still running. ' +
|
|
183
|
-
|
|
177
|
+
'You must shut it down before you may adjust its configuration.'
|
|
184
178
|
)
|
|
185
179
|
}
|
|
186
180
|
defaultService = service
|
|
@@ -199,7 +193,6 @@ function getDefaultService() {
|
|
|
199
193
|
return defaultService
|
|
200
194
|
}
|
|
201
195
|
|
|
202
|
-
|
|
203
196
|
/**
|
|
204
197
|
* _Synchronously_ attempts to locate the chromedriver executable on the current
|
|
205
198
|
* system.
|
|
@@ -213,6 +206,7 @@ function locateSynchronously() {
|
|
|
213
206
|
Options.prototype.BROWSER_NAME_VALUE = Browser.EDGE
|
|
214
207
|
Options.prototype.CAPABILITY_KEY = 'ms:edgeOptions'
|
|
215
208
|
Driver.prototype.VENDOR_CAPABILITY_PREFIX = 'ms'
|
|
209
|
+
Driver.getDefaultService = getDefaultService
|
|
216
210
|
|
|
217
211
|
// PUBLIC API
|
|
218
212
|
|
package/firefox.js
CHANGED
|
@@ -124,7 +124,6 @@ const io = require('./io')
|
|
|
124
124
|
const remote = require('./remote')
|
|
125
125
|
const webdriver = require('./lib/webdriver')
|
|
126
126
|
const zip = require('./io/zip')
|
|
127
|
-
const cdp = require('./devtools/CDPConnection')
|
|
128
127
|
const { Browser, Capabilities } = require('./lib/capabilities')
|
|
129
128
|
const { Zip } = require('./io/zip')
|
|
130
129
|
|
|
@@ -394,6 +393,31 @@ class Options extends Capabilities {
|
|
|
394
393
|
}
|
|
395
394
|
throw TypeError('binary must be a string path or Channel object')
|
|
396
395
|
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Enables Mobile start up features
|
|
399
|
+
*
|
|
400
|
+
* @param {string} androidPackage The package to use
|
|
401
|
+
* @return {!Options} A self reference
|
|
402
|
+
*/
|
|
403
|
+
enableMobile(androidPackage = "org.mozilla.firefox", androidActivity = null, deviceSerial = null) {
|
|
404
|
+
this.firefoxOptions_().androidPackage = androidPackage
|
|
405
|
+
|
|
406
|
+
if (androidActivity) {
|
|
407
|
+
this.firefoxOptions_().androidActivity = androidActivity
|
|
408
|
+
}
|
|
409
|
+
if (deviceSerial) {
|
|
410
|
+
this.firefoxOptions_().deviceSerial = deviceSerial
|
|
411
|
+
}
|
|
412
|
+
return this
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Enables moz:debuggerAddress for firefox cdp
|
|
417
|
+
*/
|
|
418
|
+
enableDebugger() {
|
|
419
|
+
return this.set('moz:debuggerAddress', true)
|
|
420
|
+
}
|
|
397
421
|
}
|
|
398
422
|
|
|
399
423
|
/**
|
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.
|
|
@@ -77,8 +77,9 @@ class HttpClient {
|
|
|
77
77
|
* Defaults to `http.globalAgent`.
|
|
78
78
|
* @param {?string=} opt_proxy The proxy to use for the connection to the
|
|
79
79
|
* server. Default is to use no proxy.
|
|
80
|
+
* @param {?Object.<string,Object>} client_options
|
|
80
81
|
*/
|
|
81
|
-
constructor(serverUrl, opt_agent, opt_proxy) {
|
|
82
|
+
constructor(serverUrl, opt_agent, opt_proxy, client_options = {}) {
|
|
82
83
|
/** @private {http.Agent} */
|
|
83
84
|
this.agent_ = opt_agent || null
|
|
84
85
|
|
|
@@ -89,11 +90,30 @@ class HttpClient {
|
|
|
89
90
|
this.options_ = getRequestOptions(serverUrl)
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
|
-
*
|
|
93
|
+
* client options, header overrides
|
|
93
94
|
*/
|
|
95
|
+
this.client_options = client_options
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* sets keep-alive for the agent
|
|
99
|
+
* see https://stackoverflow.com/a/58332910
|
|
100
|
+
*/
|
|
101
|
+
this.keepAlive = this.client_options['keep-alive']
|
|
102
|
+
|
|
103
|
+
/** @private {?RequestOptions} */
|
|
94
104
|
this.proxyOptions_ = opt_proxy ? getRequestOptions(opt_proxy) : null
|
|
95
105
|
}
|
|
96
106
|
|
|
107
|
+
get keepAlive() {
|
|
108
|
+
return this.agent_.keepAlive
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
set keepAlive(value) {
|
|
112
|
+
if (value === 'true' || value === true) {
|
|
113
|
+
this.agent_.keepAlive = true
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
97
117
|
/** @override */
|
|
98
118
|
send(httpRequest) {
|
|
99
119
|
let data
|
|
@@ -106,7 +126,7 @@ class HttpClient {
|
|
|
106
126
|
})
|
|
107
127
|
}
|
|
108
128
|
|
|
109
|
-
headers['User-Agent'] = USER_AGENT
|
|
129
|
+
headers['User-Agent'] = this.client_options['user-agent'] || USER_AGENT
|
|
110
130
|
headers['Content-Length'] = 0
|
|
111
131
|
if (httpRequest.method == 'POST' || httpRequest.method == 'PUT') {
|
|
112
132
|
data = JSON.stringify(httpRequest.data)
|
|
@@ -197,9 +217,10 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
197
217
|
let requestFn = options.protocol === 'https:' ? https.request : http.request
|
|
198
218
|
var request = requestFn(options, function onResponse(response) {
|
|
199
219
|
if (response.statusCode == 302 || response.statusCode == 303) {
|
|
220
|
+
let location
|
|
200
221
|
try {
|
|
201
222
|
// eslint-disable-next-line node/no-deprecated-api
|
|
202
|
-
|
|
223
|
+
location = url.parse(response.headers['location'])
|
|
203
224
|
} catch (ex) {
|
|
204
225
|
onError(
|
|
205
226
|
Error(
|
|
@@ -218,7 +239,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
218
239
|
location.auth = options.auth
|
|
219
240
|
}
|
|
220
241
|
|
|
221
|
-
request.
|
|
242
|
+
request.destroy()
|
|
222
243
|
sendRequest(
|
|
223
244
|
{
|
|
224
245
|
method: 'GET',
|
|
@@ -232,7 +253,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
232
253
|
hash: location.hash,
|
|
233
254
|
headers: {
|
|
234
255
|
Accept: 'application/json; charset=utf-8',
|
|
235
|
-
'User-Agent': USER_AGENT,
|
|
256
|
+
'User-Agent': options.headers['User-Agent'] || USER_AGENT,
|
|
236
257
|
},
|
|
237
258
|
},
|
|
238
259
|
onOk,
|
|
@@ -243,10 +264,10 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
243
264
|
return
|
|
244
265
|
}
|
|
245
266
|
|
|
246
|
-
|
|
267
|
+
const body = []
|
|
247
268
|
response.on('data', body.push.bind(body))
|
|
248
269
|
response.on('end', function () {
|
|
249
|
-
|
|
270
|
+
const resp = new httpLib.Response(
|
|
250
271
|
/** @type {number} */ (response.statusCode),
|
|
251
272
|
/** @type {!Object<string>} */ (response.headers),
|
|
252
273
|
Buffer.concat(body).toString('utf8').replace(/\0/g, '')
|
|
@@ -266,7 +287,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
266
287
|
sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries)
|
|
267
288
|
}, 15)
|
|
268
289
|
} else {
|
|
269
|
-
|
|
290
|
+
let message = e.message
|
|
270
291
|
if (e.code) {
|
|
271
292
|
message = e.code + ' ' + message
|
|
272
293
|
}
|
|
@@ -317,8 +338,8 @@ function isRetryableNetworkError(err) {
|
|
|
317
338
|
|
|
318
339
|
// PUBLIC API
|
|
319
340
|
|
|
320
|
-
exports.Agent = http.Agent
|
|
321
|
-
exports.Executor = httpLib.Executor
|
|
322
|
-
exports.HttpClient = HttpClient
|
|
323
|
-
exports.Request = httpLib.Request
|
|
324
|
-
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
|