@checkly/playwright-core 1.42.17 → 1.47.20-alpha
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/ThirdPartyNotices.txt +144 -109
- package/browsers.json +15 -25
- package/lib/androidServerImpl.js +1 -1
- package/lib/browserServerImpl.js +1 -1
- package/lib/cli/driver.js +1 -3
- package/lib/cli/program.js +5 -10
- package/lib/client/android.js +1 -1
- package/lib/client/api.js +7 -0
- package/lib/client/browserContext.js +37 -5
- package/lib/client/browserType.js +19 -11
- package/lib/client/channelOwner.js +19 -16
- package/lib/client/clientInstrumentation.js +17 -7
- package/lib/client/clock.js +68 -0
- package/lib/client/connection.js +9 -6
- package/lib/client/electron.js +7 -5
- package/lib/client/elementHandle.js +44 -14
- package/lib/client/eventEmitter.js +314 -0
- package/lib/client/fetch.js +81 -28
- package/lib/client/frame.js +2 -4
- package/lib/client/jsHandle.js +7 -1
- package/lib/client/locator.js +9 -0
- package/lib/client/network.js +12 -9
- package/lib/client/page.js +45 -23
- package/lib/client/playwright.js +3 -0
- package/lib/client/tracing.js +7 -4
- package/lib/common/socksProxy.js +2 -2
- package/lib/generated/clockSource.js +7 -0
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/recorderSource.js +1 -1
- package/lib/generated/utilityScriptSource.js +1 -1
- package/lib/protocol/serializers.js +12 -11
- package/lib/protocol/validator.js +137 -55
- package/lib/server/bidi/bidiBrowser.js +296 -0
- package/lib/server/bidi/bidiConnection.js +206 -0
- package/lib/server/bidi/bidiExecutionContext.js +162 -0
- package/lib/server/bidi/bidiFirefox.js +110 -0
- package/lib/server/bidi/bidiInput.js +174 -0
- package/lib/server/bidi/bidiNetworkManager.js +304 -0
- package/lib/server/bidi/bidiPage.js +456 -0
- package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
- package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
- package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
- package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
- package/lib/server/browser.js +9 -1
- package/lib/server/browserContext.js +97 -22
- package/lib/server/browserType.js +27 -20
- package/lib/server/chromium/chromium.js +30 -15
- package/lib/server/chromium/chromiumSwitches.js +6 -3
- package/lib/server/chromium/crBrowser.js +11 -17
- package/lib/server/chromium/crConnection.js +2 -2
- package/lib/server/chromium/crDragDrop.js +28 -29
- package/lib/server/chromium/crNetworkManager.js +130 -84
- package/lib/server/chromium/crPage.js +34 -79
- package/lib/server/chromium/crProtocolHelper.js +3 -1
- package/lib/server/chromium/crServiceWorker.js +20 -23
- package/lib/server/chromium/videoRecorder.js +1 -1
- package/lib/server/clock.js +125 -0
- package/lib/server/codegen/csharp.js +299 -0
- package/lib/server/codegen/java.js +235 -0
- package/lib/server/codegen/javascript.js +223 -0
- package/lib/server/codegen/jsonl.js +47 -0
- package/lib/server/codegen/language.js +76 -0
- package/lib/server/codegen/languages.js +30 -0
- package/lib/server/codegen/python.js +265 -0
- package/lib/server/codegen/types.js +5 -0
- package/lib/server/debugController.js +3 -5
- package/lib/server/deviceDescriptors.js +9 -4
- package/lib/server/deviceDescriptorsSource.json +239 -119
- package/lib/server/dispatchers/androidDispatcher.js +1 -1
- package/lib/server/dispatchers/browserContextDispatcher.js +51 -7
- package/lib/server/dispatchers/dispatcher.js +36 -40
- package/lib/server/dispatchers/frameDispatcher.js +1 -2
- package/lib/server/dispatchers/jsHandleDispatcher.js +1 -1
- package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -6
- package/lib/server/dispatchers/localUtilsDispatcher.js +19 -5
- package/lib/server/dispatchers/networkDispatchers.js +2 -2
- package/lib/server/dispatchers/pageDispatcher.js +5 -2
- package/lib/server/dispatchers/playwrightDispatcher.js +1 -0
- package/lib/server/dispatchers/writableStreamDispatcher.js +8 -5
- package/lib/server/dom.js +90 -53
- package/lib/server/electron/electron.js +21 -4
- package/lib/server/fetch.js +74 -25
- package/lib/server/fileUploadUtils.js +7 -3
- package/lib/server/firefox/ffBrowser.js +36 -25
- package/lib/server/firefox/ffConnection.js +2 -2
- package/lib/server/firefox/ffNetworkManager.js +6 -4
- package/lib/server/firefox/ffPage.js +22 -24
- package/lib/server/firefox/firefox.js +25 -6
- package/lib/server/frameSelectors.js +2 -2
- package/lib/server/frames.js +205 -159
- package/lib/server/har/harTracer.js +4 -12
- package/lib/server/helper.js +3 -3
- package/lib/server/index.js +18 -0
- package/lib/server/input.js +18 -8
- package/lib/server/instrumentation.js +0 -4
- package/lib/server/isomorphic/utilityScriptSerializers.js +19 -5
- package/lib/server/javascript.js +3 -2
- package/lib/server/launchApp.js +3 -2
- package/lib/server/network.js +14 -4
- package/lib/server/page.js +75 -46
- package/lib/server/playwright.js +5 -2
- package/lib/server/recorder/codeGenerator.js +2 -1
- package/lib/server/recorder/contextRecorder.js +316 -0
- package/lib/server/recorder/csharp.js +2 -1
- package/lib/server/recorder/java.js +2 -1
- package/lib/server/recorder/javascript.js +2 -1
- package/lib/server/recorder/jsonl.js +2 -1
- package/lib/server/recorder/language.js +2 -1
- package/lib/server/recorder/python.js +2 -1
- package/lib/server/recorder/recorderApp.js +14 -5
- package/lib/server/recorder/recorderCollection.js +127 -0
- package/lib/server/recorder/recorderRunner.js +177 -0
- package/lib/server/recorder/recorderUtils.js +23 -0
- package/lib/server/recorder/throttledFile.js +46 -0
- package/lib/server/recorder/utils.js +2 -1
- package/lib/server/recorder.js +42 -418
- package/lib/server/registry/index.js +99 -100
- package/lib/server/registry/nativeDeps.js +107 -0
- package/lib/server/screenshotter.js +6 -12
- package/lib/server/socksClientCertificatesInterceptor.js +328 -0
- package/lib/server/trace/recorder/snapshotter.js +4 -1
- package/lib/server/trace/recorder/tracing.js +27 -96
- package/lib/server/trace/viewer/traceViewer.js +54 -67
- package/lib/server/transport.js +1 -1
- package/lib/server/webkit/webkit.js +5 -5
- package/lib/server/webkit/wkBrowser.js +14 -14
- package/lib/server/webkit/wkConnection.js +3 -3
- package/lib/server/webkit/wkInterceptableRequest.js +8 -4
- package/lib/server/webkit/wkPage.js +52 -34
- package/lib/server/webkit/wkProvisionalPage.js +36 -1
- package/lib/utils/crypto.js +141 -0
- package/lib/utils/debugLogger.js +2 -0
- package/lib/utils/env.js +4 -2
- package/lib/utils/expectUtils.js +33 -0
- package/lib/utils/fileUtils.js +140 -1
- package/lib/utils/glob.js +2 -1
- package/lib/utils/happy-eyeballs.js +29 -2
- package/lib/utils/hostPlatform.js +13 -4
- package/lib/utils/httpServer.js +54 -13
- package/lib/utils/index.js +53 -31
- package/lib/utils/isomorphic/cssTokenizer.js +1 -1
- package/lib/utils/isomorphic/locatorParser.js +1 -1
- package/lib/utils/isomorphic/mimeType.js +29 -0
- package/lib/utils/isomorphic/stringUtils.js +28 -1
- package/lib/utils/isomorphic/urlMatch.js +120 -0
- package/lib/utils/mimeType.js +2 -1
- package/lib/utils/network.js +7 -35
- package/lib/utils/stackTrace.js +2 -4
- package/lib/utils/timeoutRunner.js +11 -76
- package/lib/utils/zones.js +23 -60
- package/lib/utilsBundle.js +2 -1
- package/lib/utilsBundleImpl/index.js +33 -31
- package/lib/vite/htmlReport/index.html +12 -12
- package/lib/vite/recorder/assets/codeMirrorModule-C-fQ5QZD.js +24 -0
- package/lib/vite/recorder/assets/{codicon-zGuYmc9o.ttf → codicon-DCmgc-ay.ttf} +0 -0
- package/lib/vite/recorder/assets/index-B-MT5gKo.css +1 -0
- package/lib/vite/recorder/assets/index-D-5S5PPN.js +47 -0
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-5yiV-3wl.js +16831 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-B7Z3vq11.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-C6p3E9Zg.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-CqYUz5ms.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-T_sdMrbM.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-V7N6ppkd.js +15585 -0
- package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
- package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
- package/lib/vite/traceViewer/assets/workbench-Bjkiwcr1.js +19119 -0
- package/lib/vite/traceViewer/assets/workbench-C43LWZEX.js +72 -0
- package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
- package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
- package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
- package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
- package/lib/vite/traceViewer/assets/wsPort-EUvw-dwH.js +18540 -0
- package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
- package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
- package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
- package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
- package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
- package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
- package/lib/vite/traceViewer/embedded.BVDVQOzc.js +2 -0
- package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
- package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
- package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
- package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
- package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
- package/lib/vite/traceViewer/embedded.html +16 -0
- package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
- package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
- package/lib/vite/traceViewer/index.6KJ-JQ0L.js +180 -0
- package/lib/vite/traceViewer/index.B8dgQwuN.js +2 -0
- package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
- package/lib/vite/traceViewer/index.C0EgJ4oW.js +195 -0
- package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
- package/lib/vite/traceViewer/{index.-g_5lMbJ.css → index.CrbWWHbf.css} +1 -1
- package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
- package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
- package/lib/vite/traceViewer/index.html +5 -4
- package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
- package/lib/vite/traceViewer/snapshot.html +1 -1
- package/lib/vite/traceViewer/sw.bundle.js +3 -4
- package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
- package/lib/vite/traceViewer/uiMode.D3cNFP6u.css +1 -0
- package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
- package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
- package/lib/vite/traceViewer/uiMode.DVrL7a1K.js +10 -0
- package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
- package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
- package/lib/vite/traceViewer/uiMode.html +5 -4
- package/lib/vite/traceViewer/uiMode.iq7CyYy7.js +1490 -0
- package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
- package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
- package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
- package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
- package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
- package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
- package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
- package/package.json +2 -2
- package/types/protocol.d.ts +960 -78
- package/types/structs.d.ts +1 -1
- package/types/types.d.ts +3083 -2448
- package/lib/vite/recorder/assets/codeMirrorModule-I9ks4y7D.js +0 -24
- package/lib/vite/recorder/assets/index-ljsTwXtJ.css +0 -1
- package/lib/vite/recorder/assets/index-yg8ypzl6.js +0 -47
- package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
- package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
- package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
- package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
- package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
- package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
- /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
- /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
- /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
- /package/lib/vite/traceViewer/{xtermModule.0lwXJFHT.css → xtermModule.DSXBckUd.css} +0 -0
package/lib/server/dom.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.assertDone = assertDone;
|
|
|
8
8
|
exports.isNonRecoverableDOMError = isNonRecoverableDOMError;
|
|
9
9
|
exports.kUnableToAdoptErrorMessage = void 0;
|
|
10
10
|
exports.throwRetargetableDOMError = throwRetargetableDOMError;
|
|
11
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
11
12
|
var injectedScriptSource = _interopRequireWildcard(require("../generated/injectedScriptSource"));
|
|
12
13
|
var _protocolError = require("./protocolError");
|
|
13
14
|
var js = _interopRequireWildcard(require("./javascript"));
|
|
@@ -16,6 +17,7 @@ var _utils = require("../utils");
|
|
|
16
17
|
var _fileUploadUtils = require("./fileUploadUtils");
|
|
17
18
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
18
19
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
21
|
/**
|
|
20
22
|
* Copyright (c) Microsoft Corporation.
|
|
21
23
|
*
|
|
@@ -217,6 +219,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
217
219
|
width: innerWidth,
|
|
218
220
|
height: innerHeight
|
|
219
221
|
})))]);
|
|
222
|
+
if (quads === 'error:notconnected') return quads;
|
|
220
223
|
if (!quads || !quads.length) return 'error:notvisible';
|
|
221
224
|
|
|
222
225
|
// Allow 1x1 elements. Compensate for rounding errors by comparing with 0.99 instead.
|
|
@@ -399,20 +402,22 @@ class ElementHandle extends js.JSHandle {
|
|
|
399
402
|
hitTargetInterceptionHandle.dispose();
|
|
400
403
|
});
|
|
401
404
|
}
|
|
402
|
-
const actionResult = await this._page._frameManager.waitForSignalsCreatedBy(progress, options.
|
|
405
|
+
const actionResult = await this._page._frameManager.waitForSignalsCreatedBy(progress, options.waitAfter === true, async () => {
|
|
403
406
|
if (options.__testHookBeforePointerAction) await options.__testHookBeforePointerAction();
|
|
404
407
|
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
405
408
|
let restoreModifiers;
|
|
406
|
-
if (options && options.modifiers) restoreModifiers = await this._page.keyboard.
|
|
409
|
+
if (options && options.modifiers) restoreModifiers = await this._page.keyboard.ensureModifiers(options.modifiers);
|
|
407
410
|
progress.log(` performing ${actionName} action`);
|
|
408
411
|
await action(point);
|
|
409
|
-
if (restoreModifiers) await this._page.keyboard.
|
|
412
|
+
if (restoreModifiers) await this._page.keyboard.ensureModifiers(restoreModifiers);
|
|
410
413
|
if (hitTargetInterceptionHandle) {
|
|
411
|
-
const stopHitTargetInterception =
|
|
414
|
+
const stopHitTargetInterception = this._frame.raceAgainstEvaluationStallingEvents(() => {
|
|
415
|
+
return hitTargetInterceptionHandle.evaluate(h => h.stop());
|
|
416
|
+
}).catch(e => 'done').finally(() => {
|
|
412
417
|
var _hitTargetInterceptio;
|
|
413
418
|
(_hitTargetInterceptio = hitTargetInterceptionHandle) === null || _hitTargetInterceptio === void 0 || _hitTargetInterceptio.dispose();
|
|
414
419
|
});
|
|
415
|
-
if (
|
|
420
|
+
if (options.waitAfter !== false) {
|
|
416
421
|
// When noWaitAfter is passed, we do not want to accidentally stall on
|
|
417
422
|
// non-committed navigation blocking the evaluate.
|
|
418
423
|
const hitTargetResult = await stopHitTargetInterception;
|
|
@@ -423,7 +428,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
423
428
|
progress.log(' waiting for scheduled navigations to finish');
|
|
424
429
|
if (options.__testHookAfterPointerAction) await options.__testHookAfterPointerAction();
|
|
425
430
|
return 'done';
|
|
426
|
-
}
|
|
431
|
+
});
|
|
427
432
|
if (actionResult !== 'done') return actionResult;
|
|
428
433
|
progress.log(' navigations have finished');
|
|
429
434
|
return 'done';
|
|
@@ -436,12 +441,18 @@ class ElementHandle extends js.JSHandle {
|
|
|
436
441
|
}, this._page._timeoutSettings.timeout(options));
|
|
437
442
|
}
|
|
438
443
|
_hover(progress, options) {
|
|
439
|
-
return this._retryPointerAction(progress, 'hover', false /* waitForEnabled */, point => this._page.mouse.move(point.x, point.y),
|
|
444
|
+
return this._retryPointerAction(progress, 'hover', false /* waitForEnabled */, point => this._page.mouse.move(point.x, point.y), {
|
|
445
|
+
...options,
|
|
446
|
+
waitAfter: 'disabled'
|
|
447
|
+
});
|
|
440
448
|
}
|
|
441
449
|
async click(metadata, options = {}) {
|
|
442
450
|
const controller = new _progress.ProgressController(metadata, this);
|
|
443
451
|
return controller.run(async progress => {
|
|
444
|
-
const result = await this._click(progress,
|
|
452
|
+
const result = await this._click(progress, {
|
|
453
|
+
...options,
|
|
454
|
+
waitAfter: !options.noWaitAfter
|
|
455
|
+
});
|
|
445
456
|
return assertDone(throwRetargetableDOMError(result));
|
|
446
457
|
}, this._page._timeoutSettings.timeout(options));
|
|
447
458
|
}
|
|
@@ -456,7 +467,10 @@ class ElementHandle extends js.JSHandle {
|
|
|
456
467
|
}, this._page._timeoutSettings.timeout(options));
|
|
457
468
|
}
|
|
458
469
|
_dblclick(progress, options) {
|
|
459
|
-
return this._retryPointerAction(progress, 'dblclick', true /* waitForEnabled */, point => this._page.mouse.dblclick(point.x, point.y, options),
|
|
470
|
+
return this._retryPointerAction(progress, 'dblclick', true /* waitForEnabled */, point => this._page.mouse.dblclick(point.x, point.y, options), {
|
|
471
|
+
...options,
|
|
472
|
+
waitAfter: 'disabled'
|
|
473
|
+
});
|
|
460
474
|
}
|
|
461
475
|
async tap(metadata, options = {}) {
|
|
462
476
|
const controller = new _progress.ProgressController(metadata, this);
|
|
@@ -466,7 +480,10 @@ class ElementHandle extends js.JSHandle {
|
|
|
466
480
|
}, this._page._timeoutSettings.timeout(options));
|
|
467
481
|
}
|
|
468
482
|
_tap(progress, options) {
|
|
469
|
-
return this._retryPointerAction(progress, 'tap', true /* waitForEnabled */, point => this._page.touchscreen.tap(point.x, point.y),
|
|
483
|
+
return this._retryPointerAction(progress, 'tap', true /* waitForEnabled */, point => this._page.touchscreen.tap(point.x, point.y), {
|
|
484
|
+
...options,
|
|
485
|
+
waitAfter: 'disabled'
|
|
486
|
+
});
|
|
470
487
|
}
|
|
471
488
|
async selectOption(metadata, elements, values, options) {
|
|
472
489
|
const controller = new _progress.ProgressController(metadata, this);
|
|
@@ -514,29 +531,27 @@ class ElementHandle extends js.JSHandle {
|
|
|
514
531
|
progress.log(` fill("${value}")`);
|
|
515
532
|
return await this._retryAction(progress, 'fill', async () => {
|
|
516
533
|
await progress.beforeInputAction(this);
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
if (checkResult) return checkResult;
|
|
526
|
-
}
|
|
527
|
-
return injected.fill(node, value);
|
|
528
|
-
}, {
|
|
529
|
-
value,
|
|
530
|
-
force: options.force
|
|
531
|
-
});
|
|
532
|
-
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
533
|
-
if (result === 'needsinput') {
|
|
534
|
-
if (value) await this._page.keyboard.insertText(value);else await this._page.keyboard.press('Delete');
|
|
535
|
-
return 'done';
|
|
536
|
-
} else {
|
|
537
|
-
return result;
|
|
534
|
+
if (!options.force) progress.log(' waiting for element to be visible, enabled and editable');
|
|
535
|
+
const result = await this.evaluateInUtility(async ([injected, node, {
|
|
536
|
+
value,
|
|
537
|
+
force
|
|
538
|
+
}]) => {
|
|
539
|
+
if (!force) {
|
|
540
|
+
const checkResult = await injected.checkElementStates(node, ['visible', 'enabled', 'editable']);
|
|
541
|
+
if (checkResult) return checkResult;
|
|
538
542
|
}
|
|
539
|
-
|
|
543
|
+
return injected.fill(node, value);
|
|
544
|
+
}, {
|
|
545
|
+
value,
|
|
546
|
+
force: options.force
|
|
547
|
+
});
|
|
548
|
+
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
549
|
+
if (result === 'needsinput') {
|
|
550
|
+
if (value) await this._page.keyboard.insertText(value);else await this._page.keyboard.press('Delete');
|
|
551
|
+
return 'done';
|
|
552
|
+
} else {
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
540
555
|
}, options);
|
|
541
556
|
}
|
|
542
557
|
async selectText(metadata, options = {}) {
|
|
@@ -563,30 +578,51 @@ class ElementHandle extends js.JSHandle {
|
|
|
563
578
|
const inputFileItems = await (0, _fileUploadUtils.prepareFilesForUpload)(this._frame, params);
|
|
564
579
|
const controller = new _progress.ProgressController(metadata, this);
|
|
565
580
|
return controller.run(async progress => {
|
|
566
|
-
const result = await this._setInputFiles(progress, inputFileItems
|
|
581
|
+
const result = await this._setInputFiles(progress, inputFileItems);
|
|
567
582
|
return assertDone(throwRetargetableDOMError(result));
|
|
568
583
|
}, this._page._timeoutSettings.timeout(params));
|
|
569
584
|
}
|
|
570
|
-
async _setInputFiles(progress, items
|
|
585
|
+
async _setInputFiles(progress, items) {
|
|
571
586
|
const {
|
|
572
587
|
filePayloads,
|
|
573
|
-
localPaths
|
|
588
|
+
localPaths,
|
|
589
|
+
localDirectory
|
|
574
590
|
} = items;
|
|
575
591
|
const multiple = filePayloads && filePayloads.length > 1 || localPaths && localPaths.length > 1;
|
|
576
|
-
const result = await this.evaluateHandleInUtility(([injected, node,
|
|
592
|
+
const result = await this.evaluateHandleInUtility(([injected, node, {
|
|
593
|
+
multiple,
|
|
594
|
+
directoryUpload
|
|
595
|
+
}]) => {
|
|
577
596
|
const element = injected.retarget(node, 'follow-label');
|
|
578
597
|
if (!element) return;
|
|
579
598
|
if (element.tagName !== 'INPUT') throw injected.createStacklessError('Node is not an HTMLInputElement');
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
599
|
+
const inputElement = element;
|
|
600
|
+
if (multiple && !inputElement.multiple && !inputElement.webkitdirectory) throw injected.createStacklessError('Non-multiple file input can only accept single file');
|
|
601
|
+
if (directoryUpload && !inputElement.webkitdirectory) throw injected.createStacklessError('File input does not support directories, pass individual files instead');
|
|
602
|
+
if (!directoryUpload && inputElement.webkitdirectory) throw injected.createStacklessError('[webkitdirectory] input requires passing a path to a directory');
|
|
603
|
+
return inputElement;
|
|
604
|
+
}, {
|
|
605
|
+
multiple,
|
|
606
|
+
directoryUpload: !!localDirectory
|
|
607
|
+
});
|
|
583
608
|
if (result === 'error:notconnected' || !result.asElement()) return 'error:notconnected';
|
|
584
609
|
const retargeted = result.asElement();
|
|
585
610
|
await progress.beforeInputAction(this);
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
611
|
+
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
612
|
+
if (localPaths || localDirectory) {
|
|
613
|
+
const localPathsOrDirectory = localDirectory ? [localDirectory] : localPaths;
|
|
614
|
+
await Promise.all(localPathsOrDirectory.map(localPath => _fs.default.promises.access(localPath, _fs.default.constants.F_OK)));
|
|
615
|
+
// Browsers traverse the given directory asynchronously and we want to ensure all files are uploaded.
|
|
616
|
+
const waitForInputEvent = localDirectory ? this.evaluate(node => new Promise(fulfill => {
|
|
617
|
+
node.addEventListener('input', fulfill, {
|
|
618
|
+
once: true
|
|
619
|
+
});
|
|
620
|
+
})).catch(() => {}) : Promise.resolve();
|
|
621
|
+
await this._page._delegate.setInputFilePaths(retargeted, localPathsOrDirectory);
|
|
622
|
+
await waitForInputEvent;
|
|
623
|
+
} else {
|
|
624
|
+
await this._page._delegate.setInputFiles(retargeted, filePayloads);
|
|
625
|
+
}
|
|
590
626
|
return 'done';
|
|
591
627
|
}
|
|
592
628
|
async focus(metadata) {
|
|
@@ -614,13 +650,11 @@ class ElementHandle extends js.JSHandle {
|
|
|
614
650
|
async _type(progress, text, options) {
|
|
615
651
|
progress.log(`elementHandle.type("${text}")`);
|
|
616
652
|
await progress.beforeInputAction(this);
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
return 'done';
|
|
623
|
-
}, 'input');
|
|
653
|
+
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
|
|
654
|
+
if (result !== 'done') return result;
|
|
655
|
+
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
656
|
+
await this._page.keyboard.type(text, options);
|
|
657
|
+
return 'done';
|
|
624
658
|
}
|
|
625
659
|
async press(metadata, key, options) {
|
|
626
660
|
const controller = new _progress.ProgressController(metadata, this);
|
|
@@ -632,13 +666,13 @@ class ElementHandle extends js.JSHandle {
|
|
|
632
666
|
async _press(progress, key, options) {
|
|
633
667
|
progress.log(`elementHandle.press("${key}")`);
|
|
634
668
|
await progress.beforeInputAction(this);
|
|
635
|
-
return this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
|
|
669
|
+
return this._page._frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
|
|
636
670
|
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
|
|
637
671
|
if (result !== 'done') return result;
|
|
638
672
|
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
639
673
|
await this._page.keyboard.press(key, options);
|
|
640
674
|
return 'done';
|
|
641
|
-
}
|
|
675
|
+
});
|
|
642
676
|
}
|
|
643
677
|
async check(metadata, options) {
|
|
644
678
|
const controller = new _progress.ProgressController(metadata, this);
|
|
@@ -660,7 +694,10 @@ class ElementHandle extends js.JSHandle {
|
|
|
660
694
|
return throwRetargetableDOMError(result);
|
|
661
695
|
};
|
|
662
696
|
if ((await isChecked()) === state) return 'done';
|
|
663
|
-
const result = await this._click(progress,
|
|
697
|
+
const result = await this._click(progress, {
|
|
698
|
+
...options,
|
|
699
|
+
waitAfter: 'disabled'
|
|
700
|
+
});
|
|
664
701
|
if (result !== 'done') return result;
|
|
665
702
|
if (options.trial) return 'done';
|
|
666
703
|
if ((await isChecked()) !== state) throw new NonRecoverableDOMError('Clicking the checkbox did not change its state');
|
|
@@ -156,7 +156,7 @@ class Electron extends _instrumentation.SdkObject {
|
|
|
156
156
|
return controller.run(async progress => {
|
|
157
157
|
let app = undefined;
|
|
158
158
|
// --remote-debugging-port=0 must be the last playwright's argument, loader.ts relies on it.
|
|
159
|
-
|
|
159
|
+
let electronArguments = ['--inspect=0', '--remote-debugging-port=0', ...args];
|
|
160
160
|
if (_os.default.platform() === 'linux') {
|
|
161
161
|
const runningAsRoot = process.geteuid && process.geteuid() === 0;
|
|
162
162
|
if (runningAsRoot && electronArguments.indexOf('--no-sandbox') === -1) electronArguments.unshift('--no-sandbox');
|
|
@@ -182,6 +182,16 @@ class Electron extends _instrumentation.SdkObject {
|
|
|
182
182
|
// Packaged apps might have their own command line handling.
|
|
183
183
|
electronArguments.unshift('-r', require.resolve('./loader'));
|
|
184
184
|
}
|
|
185
|
+
let shell = false;
|
|
186
|
+
if (process.platform === 'win32') {
|
|
187
|
+
// On Windows in order to run .cmd files, shell: true is required.
|
|
188
|
+
// https://github.com/nodejs/node/issues/52554
|
|
189
|
+
shell = true;
|
|
190
|
+
// On Windows, we need to quote the executable path due to shell: true.
|
|
191
|
+
command = `"${command}"`;
|
|
192
|
+
// On Windows, we need to quote the arguments due to shell: true.
|
|
193
|
+
electronArguments = electronArguments.map(arg => `"${arg}"`);
|
|
194
|
+
}
|
|
185
195
|
|
|
186
196
|
// When debugging Playwright test that runs Electron, NODE_OPTIONS
|
|
187
197
|
// will make the debugger attach to Electron's Node. But Playwright
|
|
@@ -199,6 +209,7 @@ class Electron extends _instrumentation.SdkObject {
|
|
|
199
209
|
progress.log(message);
|
|
200
210
|
browserLogsCollector.log(message);
|
|
201
211
|
},
|
|
212
|
+
shell,
|
|
202
213
|
stdio: 'pipe',
|
|
203
214
|
cwd: options.cwd,
|
|
204
215
|
tempDirectories: [artifactsDir],
|
|
@@ -211,18 +222,24 @@ class Electron extends _instrumentation.SdkObject {
|
|
|
211
222
|
return (_app = app) === null || _app === void 0 ? void 0 : _app.emit(ElectronApplication.Events.Close);
|
|
212
223
|
}
|
|
213
224
|
});
|
|
225
|
+
|
|
226
|
+
// All waitForLines must be started immediately.
|
|
227
|
+
// Otherwise the lines might come before we are ready.
|
|
214
228
|
const waitForXserverError = new Promise(async (resolve, reject) => {
|
|
215
229
|
waitForLine(progress, launchedProcess, /Unable to open X display/).then(() => reject(new Error(['Unable to open X display!', `================================`, 'Most likely this is because there is no X server available.', "Use 'xvfb-run' on Linux to launch your tests with an emulated display server.", "For example: 'xvfb-run npm run test:e2e'", `================================`, progress.metadata.log].join('\n')))).catch(() => {});
|
|
216
230
|
});
|
|
217
|
-
const
|
|
231
|
+
const nodeMatchPromise = waitForLine(progress, launchedProcess, /^Debugger listening on (ws:\/\/.*)$/);
|
|
232
|
+
const chromeMatchPromise = waitForLine(progress, launchedProcess, /^DevTools listening on (ws:\/\/.*)$/);
|
|
233
|
+
const debuggerDisconnectPromise = waitForLine(progress, launchedProcess, /Waiting for the debugger to disconnect\.\.\./);
|
|
234
|
+
const nodeMatch = await nodeMatchPromise;
|
|
218
235
|
const nodeTransport = await _transport.WebSocketTransport.connect(progress, nodeMatch[1]);
|
|
219
236
|
const nodeConnection = new _crConnection.CRConnection(nodeTransport, _helper.helper.debugProtocolLogger(), browserLogsCollector);
|
|
220
237
|
|
|
221
238
|
// Immediately release exiting process under debug.
|
|
222
|
-
|
|
239
|
+
debuggerDisconnectPromise.then(() => {
|
|
223
240
|
nodeTransport.close();
|
|
224
241
|
}).catch(() => {});
|
|
225
|
-
const chromeMatch = await Promise.race([
|
|
242
|
+
const chromeMatch = await Promise.race([chromeMatchPromise, waitForXserverError]);
|
|
226
243
|
const chromeTransport = await _transport.WebSocketTransport.connect(progress, chromeMatch[1]);
|
|
227
244
|
const browserProcess = {
|
|
228
245
|
onclose: undefined,
|
package/lib/server/fetch.js
CHANGED
|
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.GlobalAPIRequestContext = exports.BrowserContextAPIRequestContext = exports.APIRequestContext = void 0;
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var _http = _interopRequireDefault(require("http"));
|
|
8
|
+
var _https = _interopRequireDefault(require("https"));
|
|
9
9
|
var _stream = require("stream");
|
|
10
10
|
var _url = _interopRequireDefault(require("url"));
|
|
11
11
|
var _zlib = _interopRequireDefault(require("zlib"));
|
|
@@ -22,10 +22,9 @@ var _instrumentation = require("./instrumentation");
|
|
|
22
22
|
var _progress = require("./progress");
|
|
23
23
|
var _tracing = require("./trace/recorder/tracing");
|
|
24
24
|
var _network = require("./network");
|
|
25
|
+
var _socksClientCertificatesInterceptor = require("./socksClientCertificatesInterceptor");
|
|
25
26
|
var _fetch = require("../checkly/fetch");
|
|
26
27
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
28
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
29
28
|
/**
|
|
30
29
|
* Copyright (c) Microsoft Corporation.
|
|
31
30
|
*
|
|
@@ -74,7 +73,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
74
73
|
return uid;
|
|
75
74
|
}
|
|
76
75
|
async fetch(params, metadata) {
|
|
77
|
-
var _params$method;
|
|
76
|
+
var _params$method, _defaults$clientCerti;
|
|
78
77
|
const defaults = this._defaultOptions();
|
|
79
78
|
const headers = {
|
|
80
79
|
'user-agent': defaults.userAgent,
|
|
@@ -98,12 +97,17 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
98
97
|
for (const {
|
|
99
98
|
name,
|
|
100
99
|
value
|
|
101
|
-
} of params.params) requestUrl.searchParams.
|
|
100
|
+
} of params.params) requestUrl.searchParams.append(name, value);
|
|
102
101
|
}
|
|
102
|
+
const credentials = this._getHttpCredentials(requestUrl);
|
|
103
|
+
if ((credentials === null || credentials === void 0 ? void 0 : credentials.send) === 'always') setBasicAuthorizationHeader(headers, credentials);
|
|
103
104
|
const method = ((_params$method = params.method) === null || _params$method === void 0 ? void 0 : _params$method.toUpperCase()) || 'GET';
|
|
104
105
|
const proxy = defaults.proxy;
|
|
105
106
|
let agent;
|
|
106
|
-
|
|
107
|
+
// When `clientCertificates` is present, we set the `proxy` property to our own socks proxy
|
|
108
|
+
// for the browser to use. However, we don't need it here, because we already respect
|
|
109
|
+
// `clientCertificates` when fetching from Node.js.
|
|
110
|
+
if (proxy && !((_defaults$clientCerti = defaults.clientCertificates) !== null && _defaults$clientCerti !== void 0 && _defaults$clientCerti.length) && proxy.server !== 'per-context' && !shouldBypassProxy(requestUrl, proxy.bypass)) {
|
|
107
111
|
var _proxyOpts$protocol;
|
|
108
112
|
const proxyOpts = _url.default.parse(proxy.server);
|
|
109
113
|
if ((_proxyOpts$protocol = proxyOpts.protocol) !== null && _proxyOpts$protocol !== void 0 && _proxyOpts$protocol.startsWith('socks')) {
|
|
@@ -126,21 +130,30 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
126
130
|
maxRedirects: params.maxRedirects === 0 ? -1 : params.maxRedirects === undefined ? 20 : params.maxRedirects,
|
|
127
131
|
timeout,
|
|
128
132
|
deadline,
|
|
133
|
+
...(0, _socksClientCertificatesInterceptor.getMatchingTLSOptionsForOrigin)(this._defaultOptions().clientCertificates, requestUrl.origin),
|
|
129
134
|
__testHookLookup: params.__testHookLookup,
|
|
130
135
|
tokenizedURL: params.tokenizedURL,
|
|
131
136
|
...(0, _fetch.getClientCertificates)(params)
|
|
132
137
|
};
|
|
133
|
-
// rejectUnauthorized = undefined is treated as true in
|
|
138
|
+
// rejectUnauthorized = undefined is treated as true in Node.js 12.
|
|
134
139
|
if (params.ignoreHTTPSErrors || defaults.ignoreHTTPSErrors) options.rejectUnauthorized = false;
|
|
135
140
|
const postData = serializePostData(params, headers);
|
|
136
141
|
if (postData) setHeader(headers, 'content-length', String(postData.byteLength));
|
|
137
142
|
const controller = new _progress.ProgressController(metadata, this);
|
|
138
143
|
const fetchResponse = await controller.run(progress => {
|
|
139
|
-
return this.
|
|
144
|
+
return this._sendRequestWithRetries(progress, requestUrl, options, postData, params.maxRetries);
|
|
140
145
|
});
|
|
141
146
|
const fetchUid = this._storeResponseBody(fetchResponse.body);
|
|
142
147
|
this.fetchLog.set(fetchUid, controller.metadata.log);
|
|
143
|
-
if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400))
|
|
148
|
+
if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400)) {
|
|
149
|
+
let responseText = '';
|
|
150
|
+
if (fetchResponse.body.byteLength) {
|
|
151
|
+
let text = fetchResponse.body.toString('utf8');
|
|
152
|
+
if (text.length > 1000) text = text.substring(0, 997) + '...';
|
|
153
|
+
responseText = `\nResponse text:\n${text}`;
|
|
154
|
+
}
|
|
155
|
+
throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}${responseText}`);
|
|
156
|
+
}
|
|
144
157
|
return {
|
|
145
158
|
...fetchResponse,
|
|
146
159
|
fetchUid,
|
|
@@ -181,6 +194,25 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
181
194
|
setHeader(headers, 'cookie', valueArray.join('; '));
|
|
182
195
|
}
|
|
183
196
|
}
|
|
197
|
+
async _sendRequestWithRetries(progress, url, options, postData, maxRetries) {
|
|
198
|
+
var _maxRetries;
|
|
199
|
+
(_maxRetries = maxRetries) !== null && _maxRetries !== void 0 ? _maxRetries : maxRetries = 0;
|
|
200
|
+
let backoff = 250;
|
|
201
|
+
for (let i = 0; i <= maxRetries; i++) {
|
|
202
|
+
try {
|
|
203
|
+
return await this._sendRequest(progress, url, options, postData);
|
|
204
|
+
} catch (e) {
|
|
205
|
+
if (maxRetries === 0) throw e;
|
|
206
|
+
if (i === maxRetries || options.deadline && (0, _utils.monotonicTime)() + backoff > options.deadline) throw new Error(`Failed after ${i + 1} attempt(s): ${e}`);
|
|
207
|
+
// Retry on connection reset only.
|
|
208
|
+
if (e.code !== 'ECONNRESET') throw e;
|
|
209
|
+
progress.log(` Received ECONNRESET, will retry after ${backoff}ms.`);
|
|
210
|
+
await new Promise(f => setTimeout(f, backoff));
|
|
211
|
+
backoff *= 2;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
throw new Error('Unreachable');
|
|
215
|
+
}
|
|
184
216
|
async _sendRequest(progress, url, options, postData) {
|
|
185
217
|
var _getHeader;
|
|
186
218
|
await this._updateRequestCookieHeader(url, options.headers);
|
|
@@ -200,7 +232,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
200
232
|
};
|
|
201
233
|
this.emit(APIRequestContext.Events.Request, requestEvent);
|
|
202
234
|
return new Promise((fulfill, reject) => {
|
|
203
|
-
const requestConstructor = (url.protocol === 'https:' ?
|
|
235
|
+
const requestConstructor = (url.protocol === 'https:' ? _https.default : _http.default).request;
|
|
204
236
|
// If we have a proxy agent already, do not override it.
|
|
205
237
|
const agent = options.agent || (url.protocol === 'https:' ? _happyEyeballs.httpsHappyEyeballsAgent : _happyEyeballs.httpHappyEyeballsAgent);
|
|
206
238
|
const requestOptions = {
|
|
@@ -236,6 +268,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
236
268
|
}
|
|
237
269
|
}
|
|
238
270
|
if (redirectStatus.includes(response.statusCode) && options.maxRedirects >= 0) {
|
|
271
|
+
var _response$headers$loc;
|
|
239
272
|
if (!options.maxRedirects) {
|
|
240
273
|
reject(new Error('Max redirect count exceeded'));
|
|
241
274
|
request.destroy();
|
|
@@ -265,18 +298,22 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
265
298
|
maxRedirects: options.maxRedirects - 1,
|
|
266
299
|
timeout: options.timeout,
|
|
267
300
|
deadline: options.deadline,
|
|
301
|
+
...(0, _socksClientCertificatesInterceptor.getMatchingTLSOptionsForOrigin)(this._defaultOptions().clientCertificates, url.origin),
|
|
268
302
|
__testHookLookup: options.__testHookLookup
|
|
269
303
|
};
|
|
270
304
|
// rejectUnauthorized = undefined is treated as true in node 12.
|
|
271
305
|
if (options.rejectUnauthorized === false) redirectOptions.rejectUnauthorized = false;
|
|
272
306
|
|
|
273
307
|
// HTTP-redirect fetch step 4: If locationURL is null, then return response.
|
|
274
|
-
|
|
308
|
+
// Best-effort UTF-8 decoding, per spec it's US-ASCII only, but browsers are more lenient.
|
|
309
|
+
// Node.js parses it as Latin1 via std::v8::String, so we convert it to UTF-8.
|
|
310
|
+
const locationHeaderValue = Buffer.from((_response$headers$loc = response.headers.location) !== null && _response$headers$loc !== void 0 ? _response$headers$loc : '', 'latin1').toString('utf8');
|
|
311
|
+
if (locationHeaderValue) {
|
|
275
312
|
let locationURL;
|
|
276
313
|
try {
|
|
277
|
-
locationURL = new URL(
|
|
314
|
+
locationURL = new URL(locationHeaderValue, url);
|
|
278
315
|
} catch (error) {
|
|
279
|
-
reject(new Error(`uri requested responds with an invalid redirect URL: ${
|
|
316
|
+
reject(new Error(`uri requested responds with an invalid redirect URL: ${locationHeaderValue}`));
|
|
280
317
|
request.destroy();
|
|
281
318
|
return;
|
|
282
319
|
}
|
|
@@ -291,12 +328,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
291
328
|
const auth = response.headers['www-authenticate'];
|
|
292
329
|
const credentials = this._getHttpCredentials(url);
|
|
293
330
|
if (auth !== null && auth !== void 0 && auth.trim().startsWith('Basic') && credentials) {
|
|
294
|
-
|
|
295
|
-
username,
|
|
296
|
-
password
|
|
297
|
-
} = credentials;
|
|
298
|
-
const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
|
|
299
|
-
setHeader(options.headers, 'authorization', `Basic ${encoded}`);
|
|
331
|
+
setBasicAuthorizationHeader(options.headers, credentials);
|
|
300
332
|
notifyRequestFinished();
|
|
301
333
|
fulfill(this._sendRequest(progress, url, options, postData));
|
|
302
334
|
request.destroy();
|
|
@@ -334,7 +366,10 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
334
366
|
finishFlush: _zlib.default.constants.Z_SYNC_FLUSH
|
|
335
367
|
});
|
|
336
368
|
} else if (encoding === 'br') {
|
|
337
|
-
transform = _zlib.default.createBrotliDecompress(
|
|
369
|
+
transform = _zlib.default.createBrotliDecompress({
|
|
370
|
+
flush: _zlib.default.constants.BROTLI_OPERATION_FLUSH,
|
|
371
|
+
finishFlush: _zlib.default.constants.BROTLI_OPERATION_FLUSH
|
|
372
|
+
});
|
|
338
373
|
} else if (encoding === 'deflate') {
|
|
339
374
|
transform = _zlib.default.createInflate();
|
|
340
375
|
}
|
|
@@ -351,8 +386,8 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
351
386
|
body.on('data', chunk => chunks.push(chunk));
|
|
352
387
|
body.on('end', notifyBodyFinished);
|
|
353
388
|
});
|
|
389
|
+
request.on('error', error => reject((0, _socksClientCertificatesInterceptor.rewriteOpenSSLErrorIfNeeded)(error)));
|
|
354
390
|
(0, _fetch.addRequestListeners)(request, timings);
|
|
355
|
-
request.on('error', reject);
|
|
356
391
|
const disposeListener = () => {
|
|
357
392
|
reject(new Error('Request context disposed.'));
|
|
358
393
|
request.destroy();
|
|
@@ -417,7 +452,8 @@ class BrowserContextAPIRequestContext extends APIRequestContext {
|
|
|
417
452
|
tracing() {
|
|
418
453
|
return this._context.tracing;
|
|
419
454
|
}
|
|
420
|
-
async dispose() {
|
|
455
|
+
async dispose(options) {
|
|
456
|
+
this._closeReason = options.reason;
|
|
421
457
|
this.fetchResponses.clear();
|
|
422
458
|
}
|
|
423
459
|
_defaultOptions() {
|
|
@@ -428,7 +464,8 @@ class BrowserContextAPIRequestContext extends APIRequestContext {
|
|
|
428
464
|
proxy: this._context._options.proxy || this._context._browser.options.proxy,
|
|
429
465
|
timeoutSettings: this._context._timeoutSettings,
|
|
430
466
|
ignoreHTTPSErrors: this._context._options.ignoreHTTPSErrors,
|
|
431
|
-
baseURL: this._context._options.baseURL
|
|
467
|
+
baseURL: this._context._options.baseURL,
|
|
468
|
+
clientCertificates: this._context._options.clientCertificates
|
|
432
469
|
};
|
|
433
470
|
}
|
|
434
471
|
async _addCookies(cookies) {
|
|
@@ -457,17 +494,20 @@ class GlobalAPIRequestContext extends APIRequestContext {
|
|
|
457
494
|
let url = proxy === null || proxy === void 0 ? void 0 : proxy.server.trim();
|
|
458
495
|
if (!/^\w+:\/\//.test(url)) url = 'http://' + url;
|
|
459
496
|
proxy.server = url;
|
|
497
|
+
if (options.clientCertificates) throw new Error('Cannot specify both proxy and clientCertificates');
|
|
460
498
|
}
|
|
461
499
|
if (options.storageState) {
|
|
462
500
|
this._origins = options.storageState.origins;
|
|
463
501
|
this._cookieStore.addCookies(options.storageState.cookies || []);
|
|
464
502
|
}
|
|
503
|
+
(0, _browserContext.verifyClientCertificates)(options.clientCertificates);
|
|
465
504
|
this._options = {
|
|
466
505
|
baseURL: options.baseURL,
|
|
467
506
|
userAgent: options.userAgent || (0, _userAgent.getUserAgent)(),
|
|
468
507
|
extraHTTPHeaders: options.extraHTTPHeaders,
|
|
469
508
|
ignoreHTTPSErrors: !!options.ignoreHTTPSErrors,
|
|
470
509
|
httpCredentials: options.httpCredentials,
|
|
510
|
+
clientCertificates: options.clientCertificates,
|
|
471
511
|
proxy,
|
|
472
512
|
timeoutSettings
|
|
473
513
|
};
|
|
@@ -476,7 +516,8 @@ class GlobalAPIRequestContext extends APIRequestContext {
|
|
|
476
516
|
tracing() {
|
|
477
517
|
return this._tracing;
|
|
478
518
|
}
|
|
479
|
-
async dispose() {
|
|
519
|
+
async dispose(options) {
|
|
520
|
+
this._closeReason = options.reason;
|
|
480
521
|
await this._tracing.flush();
|
|
481
522
|
await this._tracing.deleteTmpTracesDir();
|
|
482
523
|
this._disposeImpl();
|
|
@@ -632,4 +673,12 @@ function shouldBypassProxy(url, bypass) {
|
|
|
632
673
|
});
|
|
633
674
|
const domain = '.' + url.hostname;
|
|
634
675
|
return domains.some(d => domain.endsWith(d));
|
|
676
|
+
}
|
|
677
|
+
function setBasicAuthorizationHeader(headers, credentials) {
|
|
678
|
+
const {
|
|
679
|
+
username,
|
|
680
|
+
password
|
|
681
|
+
} = credentials;
|
|
682
|
+
const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
|
|
683
|
+
setHeader(headers, 'authorization', `Basic ${encoded}`);
|
|
635
684
|
}
|
|
@@ -33,13 +33,16 @@ async function prepareFilesForUpload(frame, params) {
|
|
|
33
33
|
var _fileBuffers;
|
|
34
34
|
const {
|
|
35
35
|
payloads,
|
|
36
|
-
streams
|
|
36
|
+
streams,
|
|
37
|
+
directoryStream
|
|
37
38
|
} = params;
|
|
38
39
|
let {
|
|
39
|
-
localPaths
|
|
40
|
+
localPaths,
|
|
41
|
+
localDirectory
|
|
40
42
|
} = params;
|
|
41
|
-
if ([payloads, localPaths, streams].filter(Boolean).length !== 1) throw new Error('Exactly one of payloads, localPaths and streams must be provided');
|
|
43
|
+
if ([payloads, localPaths, localDirectory, streams, directoryStream].filter(Boolean).length !== 1) throw new Error('Exactly one of payloads, localPaths and streams must be provided');
|
|
42
44
|
if (streams) localPaths = streams.map(c => c.path());
|
|
45
|
+
if (directoryStream) localDirectory = directoryStream.path();
|
|
43
46
|
if (localPaths) {
|
|
44
47
|
for (const p of localPaths) (0, _utils.assert)(_path.default.isAbsolute(p) && _path.default.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
|
|
45
48
|
}
|
|
@@ -66,6 +69,7 @@ async function prepareFilesForUpload(frame, params) {
|
|
|
66
69
|
}));
|
|
67
70
|
return {
|
|
68
71
|
localPaths,
|
|
72
|
+
localDirectory,
|
|
69
73
|
filePayloads
|
|
70
74
|
};
|
|
71
75
|
}
|