@mswjs/interceptors 0.39.8 → 0.41.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/ClientRequest/package.json +7 -2
- package/RemoteHttpInterceptor/package.json +7 -2
- package/WebSocket/package.json +9 -2
- package/XMLHttpRequest/package.json +9 -3
- package/fetch/package.json +9 -3
- package/lib/browser/Interceptor-2mUoKZL1.d.mts +65 -0
- package/lib/browser/Interceptor-Deczogc8.d.cts +65 -0
- package/lib/browser/XMLHttpRequest-BUfglQD1.cjs +761 -0
- package/lib/browser/XMLHttpRequest-BUfglQD1.cjs.map +1 -0
- package/lib/browser/XMLHttpRequest-DS5fc8Qs.mjs +756 -0
- package/lib/browser/XMLHttpRequest-DS5fc8Qs.mjs.map +1 -0
- package/lib/browser/bufferUtils-BiiO6HZv.mjs +20 -0
- package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +1 -0
- package/lib/browser/bufferUtils-Uc0eRItL.cjs +38 -0
- package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +1 -0
- package/lib/browser/createRequestId-Cs4oXfa1.cjs +205 -0
- package/lib/browser/createRequestId-Cs4oXfa1.cjs.map +1 -0
- package/lib/browser/createRequestId-DQcIlohW.mjs +170 -0
- package/lib/browser/createRequestId-DQcIlohW.mjs.map +1 -0
- package/lib/browser/fetch-BHcqM3z7.cjs +253 -0
- package/lib/browser/fetch-BHcqM3z7.cjs.map +1 -0
- package/lib/browser/fetch-DSJoynSF.mjs +248 -0
- package/lib/browser/fetch-DSJoynSF.mjs.map +1 -0
- package/lib/browser/getRawRequest-BTaNLFr0.mjs +218 -0
- package/lib/browser/getRawRequest-BTaNLFr0.mjs.map +1 -0
- package/lib/browser/getRawRequest-zx8rUJL2.cjs +259 -0
- package/lib/browser/getRawRequest-zx8rUJL2.cjs.map +1 -0
- package/lib/browser/glossary-BdLS4k1H.d.cts +70 -0
- package/lib/browser/glossary-gEEJhK4S.d.mts +70 -0
- package/lib/browser/handleRequest-DI6a7Dty.cjs +189 -0
- package/lib/browser/handleRequest-DI6a7Dty.cjs.map +1 -0
- package/lib/browser/handleRequest-DxGbCTbb.mjs +178 -0
- package/lib/browser/handleRequest-DxGbCTbb.mjs.map +1 -0
- package/lib/browser/hasConfigurableGlobal-C8kXFDic.mjs +33 -0
- package/lib/browser/hasConfigurableGlobal-C8kXFDic.mjs.map +1 -0
- package/lib/browser/hasConfigurableGlobal-D7S3l5h6.cjs +45 -0
- package/lib/browser/hasConfigurableGlobal-D7S3l5h6.cjs.map +1 -0
- package/lib/browser/index.cjs +68 -0
- package/lib/browser/index.cjs.map +1 -0
- package/lib/browser/index.d.cts +87 -0
- package/lib/browser/index.d.mts +87 -0
- package/lib/browser/index.mjs +49 -75
- package/lib/browser/index.mjs.map +1 -1
- package/lib/browser/interceptors/WebSocket/index.cjs +621 -0
- package/lib/browser/interceptors/WebSocket/index.cjs.map +1 -0
- package/lib/browser/interceptors/WebSocket/index.d.cts +277 -0
- package/lib/browser/interceptors/WebSocket/index.d.mts +277 -0
- package/lib/browser/interceptors/WebSocket/index.mjs +587 -694
- package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -1
- package/lib/browser/interceptors/XMLHttpRequest/index.cjs +7 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +15 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +15 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs +7 -12
- package/lib/browser/interceptors/fetch/index.cjs +6 -0
- package/lib/browser/interceptors/fetch/index.d.cts +13 -0
- package/lib/browser/interceptors/fetch/index.d.mts +13 -0
- package/lib/browser/interceptors/fetch/index.mjs +6 -11
- package/lib/browser/presets/browser.cjs +17 -0
- package/lib/browser/presets/browser.cjs.map +1 -0
- package/lib/browser/presets/browser.d.cts +12 -0
- package/lib/browser/presets/browser.d.mts +14 -0
- package/lib/browser/presets/browser.mjs +15 -19
- package/lib/browser/presets/browser.mjs.map +1 -1
- package/lib/node/BatchInterceptor-3LnAnLTx.cjs +49 -0
- package/lib/node/BatchInterceptor-3LnAnLTx.cjs.map +1 -0
- package/lib/node/BatchInterceptor-D7mXzHcQ.d.mts +26 -0
- package/lib/node/BatchInterceptor-DFaBPilf.mjs +44 -0
- package/lib/node/BatchInterceptor-DFaBPilf.mjs.map +1 -0
- package/lib/node/BatchInterceptor-D_YqR8qU.d.cts +26 -0
- package/lib/node/ClientRequest-2rDe54Ui.cjs +1043 -0
- package/lib/node/ClientRequest-2rDe54Ui.cjs.map +1 -0
- package/lib/node/ClientRequest-Ca8Qykuv.mjs +1034 -0
- package/lib/node/ClientRequest-Ca8Qykuv.mjs.map +1 -0
- package/lib/node/Interceptor-DEazpLJd.d.mts +133 -0
- package/lib/node/Interceptor-DJ2akVWI.d.cts +133 -0
- package/lib/node/RemoteHttpInterceptor.cjs +154 -0
- package/lib/node/RemoteHttpInterceptor.cjs.map +1 -0
- package/lib/node/RemoteHttpInterceptor.d.cts +39 -0
- package/lib/node/RemoteHttpInterceptor.d.mts +39 -0
- package/lib/node/RemoteHttpInterceptor.mjs +145 -186
- package/lib/node/RemoteHttpInterceptor.mjs.map +1 -1
- package/lib/node/XMLHttpRequest-B7kJdYYI.cjs +763 -0
- package/lib/node/XMLHttpRequest-B7kJdYYI.cjs.map +1 -0
- package/lib/node/XMLHttpRequest-C8dIZpds.mjs +757 -0
- package/lib/node/XMLHttpRequest-C8dIZpds.mjs.map +1 -0
- package/lib/node/bufferUtils-DiCTqG-7.cjs +38 -0
- package/lib/node/bufferUtils-DiCTqG-7.cjs.map +1 -0
- package/lib/node/bufferUtils-_8XfKIfX.mjs +20 -0
- package/lib/node/bufferUtils-_8XfKIfX.mjs.map +1 -0
- package/lib/node/chunk-CbDLau6x.cjs +34 -0
- package/lib/node/fetch-BmXpK10r.cjs +272 -0
- package/lib/node/fetch-BmXpK10r.cjs.map +1 -0
- package/lib/node/fetch-G1DVwDKG.mjs +265 -0
- package/lib/node/fetch-G1DVwDKG.mjs.map +1 -0
- package/lib/node/fetchUtils-BaY5iWXw.cjs +419 -0
- package/lib/node/fetchUtils-BaY5iWXw.cjs.map +1 -0
- package/lib/node/fetchUtils-CoU35g3M.mjs +359 -0
- package/lib/node/fetchUtils-CoU35g3M.mjs.map +1 -0
- package/lib/node/getRawRequest-BavnMWh_.cjs +36 -0
- package/lib/node/getRawRequest-BavnMWh_.cjs.map +1 -0
- package/lib/node/getRawRequest-DnwmXyOW.mjs +24 -0
- package/lib/node/getRawRequest-DnwmXyOW.mjs.map +1 -0
- package/lib/node/glossary-BLKRyLBd.cjs +12 -0
- package/lib/node/glossary-BLKRyLBd.cjs.map +1 -0
- package/lib/node/glossary-glQBRnVD.mjs +6 -0
- package/lib/node/glossary-glQBRnVD.mjs.map +1 -0
- package/lib/node/handleRequest-Bb7Y-XLw.cjs +220 -0
- package/lib/node/handleRequest-Bb7Y-XLw.cjs.map +1 -0
- package/lib/node/handleRequest-Y97UwBbF.mjs +190 -0
- package/lib/node/handleRequest-Y97UwBbF.mjs.map +1 -0
- package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs +26 -0
- package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs.map +1 -0
- package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs +20 -0
- package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs.map +1 -0
- package/lib/node/index-BMbJ8FXL.d.cts +113 -0
- package/lib/node/index-C0YAQ36w.d.mts +113 -0
- package/lib/node/index.cjs +30 -0
- package/lib/node/index.cjs.map +1 -0
- package/lib/node/index.d.cts +66 -0
- package/lib/node/index.d.mts +66 -0
- package/lib/node/index.mjs +13 -39
- package/lib/node/index.mjs.map +1 -1
- package/lib/node/interceptors/ClientRequest/index.cjs +6 -0
- package/lib/node/interceptors/ClientRequest/index.d.cts +2 -0
- package/lib/node/interceptors/ClientRequest/index.d.mts +3 -0
- package/lib/node/interceptors/ClientRequest/index.mjs +6 -11
- package/lib/node/interceptors/XMLHttpRequest/index.cjs +6 -0
- package/lib/node/interceptors/XMLHttpRequest/index.d.cts +14 -0
- package/lib/node/interceptors/XMLHttpRequest/index.d.mts +14 -0
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -13
- package/lib/node/interceptors/fetch/index.cjs +5 -0
- package/lib/node/interceptors/fetch/index.d.cts +12 -0
- package/lib/node/interceptors/fetch/index.d.mts +12 -0
- package/lib/node/interceptors/fetch/index.mjs +5 -12
- package/lib/node/node-DwCc6iuP.mjs +27 -0
- package/lib/node/node-DwCc6iuP.mjs.map +1 -0
- package/lib/node/node-dKdAf3tC.cjs +39 -0
- package/lib/node/node-dKdAf3tC.cjs.map +1 -0
- package/lib/node/presets/node.cjs +22 -0
- package/lib/node/presets/node.cjs.map +1 -0
- package/lib/node/presets/node.d.cts +13 -0
- package/lib/node/presets/node.d.mts +15 -0
- package/lib/node/presets/node.mjs +18 -23
- package/lib/node/presets/node.mjs.map +1 -1
- package/lib/node/utils/node/index.cjs +4 -0
- package/lib/node/utils/node/{index.d.ts → index.d.cts} +5 -2
- package/lib/node/utils/node/index.d.mts +16 -0
- package/lib/node/utils/node/index.mjs +3 -10
- package/package.json +34 -59
- package/presets/browser/package.json +2 -3
- package/presets/node/package.json +7 -2
- package/src/RemoteHttpInterceptor.ts +18 -13
- package/src/RequestController.test.ts +78 -31
- package/src/RequestController.ts +63 -39
- package/src/index.ts +4 -0
- package/src/interceptors/ClientRequest/MockHttpSocket.ts +43 -9
- package/src/interceptors/ClientRequest/index.ts +14 -18
- package/src/interceptors/ClientRequest/utils/parserUtils.ts +48 -0
- package/src/interceptors/WebSocket/index.ts +4 -1
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +45 -35
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +24 -21
- package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts +2 -2
- package/src/interceptors/fetch/index.ts +61 -50
- package/src/utils/handleRequest.ts +65 -95
- package/lib/browser/Interceptor-af98b768.d.ts +0 -63
- package/lib/browser/chunk-2HUMWGRD.js +0 -37
- package/lib/browser/chunk-2HUMWGRD.js.map +0 -1
- package/lib/browser/chunk-2QICSCCS.js +0 -238
- package/lib/browser/chunk-2QICSCCS.js.map +0 -1
- package/lib/browser/chunk-3RXCRGL2.mjs +0 -117
- package/lib/browser/chunk-3RXCRGL2.mjs.map +0 -1
- package/lib/browser/chunk-6HYIRFX2.mjs +0 -22
- package/lib/browser/chunk-6HYIRFX2.mjs.map +0 -1
- package/lib/browser/chunk-E3CCOBRX.js +0 -846
- package/lib/browser/chunk-E3CCOBRX.js.map +0 -1
- package/lib/browser/chunk-E7UVBHVO.mjs +0 -846
- package/lib/browser/chunk-E7UVBHVO.mjs.map +0 -1
- package/lib/browser/chunk-H74PGQ4Y.js +0 -296
- package/lib/browser/chunk-H74PGQ4Y.js.map +0 -1
- package/lib/browser/chunk-LK6DILFK.js +0 -22
- package/lib/browser/chunk-LK6DILFK.js.map +0 -1
- package/lib/browser/chunk-PTTUYYVR.mjs +0 -238
- package/lib/browser/chunk-PTTUYYVR.mjs.map +0 -1
- package/lib/browser/chunk-Q7K2XAEP.mjs +0 -296
- package/lib/browser/chunk-Q7K2XAEP.mjs.map +0 -1
- package/lib/browser/chunk-QED3Q6Z2.mjs +0 -169
- package/lib/browser/chunk-QED3Q6Z2.mjs.map +0 -1
- package/lib/browser/chunk-T7TBRNJZ.js +0 -117
- package/lib/browser/chunk-T7TBRNJZ.js.map +0 -1
- package/lib/browser/chunk-TIPR373R.js +0 -169
- package/lib/browser/chunk-TIPR373R.js.map +0 -1
- package/lib/browser/chunk-VYSDLBSS.mjs +0 -37
- package/lib/browser/chunk-VYSDLBSS.mjs.map +0 -1
- package/lib/browser/glossary-7152281e.d.ts +0 -69
- package/lib/browser/index.d.ts +0 -83
- package/lib/browser/index.js +0 -81
- package/lib/browser/index.js.map +0 -1
- package/lib/browser/interceptors/WebSocket/index.d.ts +0 -271
- package/lib/browser/interceptors/WebSocket/index.js +0 -721
- package/lib/browser/interceptors/WebSocket/index.js.map +0 -1
- package/lib/browser/interceptors/XMLHttpRequest/index.d.ts +0 -15
- package/lib/browser/interceptors/XMLHttpRequest/index.js +0 -12
- package/lib/browser/interceptors/XMLHttpRequest/index.js.map +0 -1
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs.map +0 -1
- package/lib/browser/interceptors/fetch/index.d.ts +0 -14
- package/lib/browser/interceptors/fetch/index.js +0 -11
- package/lib/browser/interceptors/fetch/index.js.map +0 -1
- package/lib/browser/interceptors/fetch/index.mjs.map +0 -1
- package/lib/browser/presets/browser.d.ts +0 -15
- package/lib/browser/presets/browser.js +0 -21
- package/lib/browser/presets/browser.js.map +0 -1
- package/lib/node/BatchInterceptor-5b72232f.d.ts +0 -24
- package/lib/node/Interceptor-bc5a9d8e.d.ts +0 -130
- package/lib/node/RemoteHttpInterceptor.d.ts +0 -45
- package/lib/node/RemoteHttpInterceptor.js +0 -193
- package/lib/node/RemoteHttpInterceptor.js.map +0 -1
- package/lib/node/chunk-3CNGDJFB.mjs +0 -313
- package/lib/node/chunk-3CNGDJFB.mjs.map +0 -1
- package/lib/node/chunk-3GJB4JDF.mjs +0 -14
- package/lib/node/chunk-3GJB4JDF.mjs.map +0 -1
- package/lib/node/chunk-4NEYTVWD.mjs +0 -848
- package/lib/node/chunk-4NEYTVWD.mjs.map +0 -1
- package/lib/node/chunk-4YBV77DG.js +0 -32
- package/lib/node/chunk-4YBV77DG.js.map +0 -1
- package/lib/node/chunk-6HYIRFX2.mjs +0 -22
- package/lib/node/chunk-6HYIRFX2.mjs.map +0 -1
- package/lib/node/chunk-6YM4PLBI.mjs +0 -7
- package/lib/node/chunk-6YM4PLBI.mjs.map +0 -1
- package/lib/node/chunk-72ZIHMEB.js +0 -249
- package/lib/node/chunk-72ZIHMEB.js.map +0 -1
- package/lib/node/chunk-73NOP3T5.js +0 -7
- package/lib/node/chunk-73NOP3T5.js.map +0 -1
- package/lib/node/chunk-A7Q4RTDJ.mjs +0 -249
- package/lib/node/chunk-A7Q4RTDJ.mjs.map +0 -1
- package/lib/node/chunk-A7U44ARP.js +0 -268
- package/lib/node/chunk-A7U44ARP.js.map +0 -1
- package/lib/node/chunk-EKNRB5ZS.mjs +0 -1115
- package/lib/node/chunk-EKNRB5ZS.mjs.map +0 -1
- package/lib/node/chunk-IHJSPMYM.mjs +0 -268
- package/lib/node/chunk-IHJSPMYM.mjs.map +0 -1
- package/lib/node/chunk-LK6DILFK.js +0 -22
- package/lib/node/chunk-LK6DILFK.js.map +0 -1
- package/lib/node/chunk-N4ZZFE24.js +0 -1115
- package/lib/node/chunk-N4ZZFE24.js.map +0 -1
- package/lib/node/chunk-PFGO5BSM.js +0 -25
- package/lib/node/chunk-PFGO5BSM.js.map +0 -1
- package/lib/node/chunk-R6JVCM7X.js +0 -51
- package/lib/node/chunk-R6JVCM7X.js.map +0 -1
- package/lib/node/chunk-RC2XPCC4.mjs +0 -51
- package/lib/node/chunk-RC2XPCC4.mjs.map +0 -1
- package/lib/node/chunk-SMXZPJEA.js +0 -14
- package/lib/node/chunk-SMXZPJEA.js.map +0 -1
- package/lib/node/chunk-TJDMZZXE.mjs +0 -32
- package/lib/node/chunk-TJDMZZXE.mjs.map +0 -1
- package/lib/node/chunk-TX5GBTFY.mjs +0 -25
- package/lib/node/chunk-TX5GBTFY.mjs.map +0 -1
- package/lib/node/chunk-VV2LUF5K.js +0 -848
- package/lib/node/chunk-VV2LUF5K.js.map +0 -1
- package/lib/node/chunk-Z5LWCBZS.js +0 -313
- package/lib/node/chunk-Z5LWCBZS.js.map +0 -1
- package/lib/node/index.d.ts +0 -62
- package/lib/node/index.js +0 -43
- package/lib/node/index.js.map +0 -1
- package/lib/node/interceptors/ClientRequest/index.d.ts +0 -111
- package/lib/node/interceptors/ClientRequest/index.js +0 -11
- package/lib/node/interceptors/ClientRequest/index.js.map +0 -1
- package/lib/node/interceptors/ClientRequest/index.mjs.map +0 -1
- package/lib/node/interceptors/XMLHttpRequest/index.d.ts +0 -14
- package/lib/node/interceptors/XMLHttpRequest/index.js +0 -13
- package/lib/node/interceptors/XMLHttpRequest/index.js.map +0 -1
- package/lib/node/interceptors/XMLHttpRequest/index.mjs.map +0 -1
- package/lib/node/interceptors/fetch/index.d.ts +0 -13
- package/lib/node/interceptors/fetch/index.js +0 -12
- package/lib/node/interceptors/fetch/index.js.map +0 -1
- package/lib/node/interceptors/fetch/index.mjs.map +0 -1
- package/lib/node/presets/node.d.ts +0 -16
- package/lib/node/presets/node.js +0 -27
- package/lib/node/presets/node.js.map +0 -1
- package/lib/node/utils/node/index.js +0 -10
- package/lib/node/utils/node/index.js.map +0 -1
- package/lib/node/utils/node/index.mjs.map +0 -1
- package/src/utils/RequestController.ts +0 -21
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
import { t as IS_PATCHED_MODULE } from "./glossary-glQBRnVD.mjs";
|
|
2
|
+
import { i as RequestController, o as INTERNAL_REQUEST_ID_HEADER_NAME, r as createRequestId, s as Interceptor, t as FetchResponse } from "./fetchUtils-CoU35g3M.mjs";
|
|
3
|
+
import { n as encodeBuffer, r as toArrayBuffer, t as decodeBuffer } from "./bufferUtils-_8XfKIfX.mjs";
|
|
4
|
+
import { n as setRawRequest } from "./getRawRequest-DnwmXyOW.mjs";
|
|
5
|
+
import { n as isResponseError, t as handleRequest } from "./handleRequest-Y97UwBbF.mjs";
|
|
6
|
+
import { t as hasConfigurableGlobal } from "./hasConfigurableGlobal-DBJA0vjm.mjs";
|
|
7
|
+
import { invariant } from "outvariant";
|
|
8
|
+
import { isNodeProcess } from "is-node-process";
|
|
9
|
+
|
|
10
|
+
//#region src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts
|
|
11
|
+
/**
|
|
12
|
+
* Concatenate two `Uint8Array` buffers.
|
|
13
|
+
*/
|
|
14
|
+
function concatArrayBuffer(left, right) {
|
|
15
|
+
const result = new Uint8Array(left.byteLength + right.byteLength);
|
|
16
|
+
result.set(left, 0);
|
|
17
|
+
result.set(right, left.byteLength);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts
|
|
23
|
+
var EventPolyfill = class {
|
|
24
|
+
constructor(type, options) {
|
|
25
|
+
this.NONE = 0;
|
|
26
|
+
this.CAPTURING_PHASE = 1;
|
|
27
|
+
this.AT_TARGET = 2;
|
|
28
|
+
this.BUBBLING_PHASE = 3;
|
|
29
|
+
this.type = "";
|
|
30
|
+
this.srcElement = null;
|
|
31
|
+
this.currentTarget = null;
|
|
32
|
+
this.eventPhase = 0;
|
|
33
|
+
this.isTrusted = true;
|
|
34
|
+
this.composed = false;
|
|
35
|
+
this.cancelable = true;
|
|
36
|
+
this.defaultPrevented = false;
|
|
37
|
+
this.bubbles = true;
|
|
38
|
+
this.lengthComputable = true;
|
|
39
|
+
this.loaded = 0;
|
|
40
|
+
this.total = 0;
|
|
41
|
+
this.cancelBubble = false;
|
|
42
|
+
this.returnValue = true;
|
|
43
|
+
this.type = type;
|
|
44
|
+
this.target = options?.target || null;
|
|
45
|
+
this.currentTarget = options?.currentTarget || null;
|
|
46
|
+
this.timeStamp = Date.now();
|
|
47
|
+
}
|
|
48
|
+
composedPath() {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
initEvent(type, bubbles, cancelable) {
|
|
52
|
+
this.type = type;
|
|
53
|
+
this.bubbles = !!bubbles;
|
|
54
|
+
this.cancelable = !!cancelable;
|
|
55
|
+
}
|
|
56
|
+
preventDefault() {
|
|
57
|
+
this.defaultPrevented = true;
|
|
58
|
+
}
|
|
59
|
+
stopPropagation() {}
|
|
60
|
+
stopImmediatePropagation() {}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts
|
|
65
|
+
var ProgressEventPolyfill = class extends EventPolyfill {
|
|
66
|
+
constructor(type, init) {
|
|
67
|
+
super(type);
|
|
68
|
+
this.lengthComputable = init?.lengthComputable || false;
|
|
69
|
+
this.composed = init?.composed || false;
|
|
70
|
+
this.loaded = init?.loaded || 0;
|
|
71
|
+
this.total = init?.total || 0;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/interceptors/XMLHttpRequest/utils/createEvent.ts
|
|
77
|
+
const SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== "undefined";
|
|
78
|
+
function createEvent(target, type, init) {
|
|
79
|
+
const progressEvents = [
|
|
80
|
+
"error",
|
|
81
|
+
"progress",
|
|
82
|
+
"loadstart",
|
|
83
|
+
"loadend",
|
|
84
|
+
"load",
|
|
85
|
+
"timeout",
|
|
86
|
+
"abort"
|
|
87
|
+
];
|
|
88
|
+
/**
|
|
89
|
+
* `ProgressEvent` is not supported in React Native.
|
|
90
|
+
* @see https://github.com/mswjs/interceptors/issues/40
|
|
91
|
+
*/
|
|
92
|
+
const ProgressEventClass = SUPPORTS_PROGRESS_EVENT ? ProgressEvent : ProgressEventPolyfill;
|
|
93
|
+
return progressEvents.includes(type) ? new ProgressEventClass(type, {
|
|
94
|
+
lengthComputable: true,
|
|
95
|
+
loaded: init?.loaded || 0,
|
|
96
|
+
total: init?.total || 0
|
|
97
|
+
}) : new EventPolyfill(type, {
|
|
98
|
+
target,
|
|
99
|
+
currentTarget: target
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/utils/findPropertySource.ts
|
|
105
|
+
/**
|
|
106
|
+
* Returns the source object of the given property on the target object
|
|
107
|
+
* (the target itself, any parent in its prototype, or null).
|
|
108
|
+
*/
|
|
109
|
+
function findPropertySource(target, propertyName) {
|
|
110
|
+
if (!(propertyName in target)) return null;
|
|
111
|
+
if (Object.prototype.hasOwnProperty.call(target, propertyName)) return target;
|
|
112
|
+
const prototype = Reflect.getPrototypeOf(target);
|
|
113
|
+
return prototype ? findPropertySource(prototype, propertyName) : null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/utils/createProxy.ts
|
|
118
|
+
function createProxy(target, options) {
|
|
119
|
+
return new Proxy(target, optionsToProxyHandler(options));
|
|
120
|
+
}
|
|
121
|
+
function optionsToProxyHandler(options) {
|
|
122
|
+
const { constructorCall, methodCall, getProperty, setProperty } = options;
|
|
123
|
+
const handler = {};
|
|
124
|
+
if (typeof constructorCall !== "undefined") handler.construct = function(target, args, newTarget) {
|
|
125
|
+
const next = Reflect.construct.bind(null, target, args, newTarget);
|
|
126
|
+
return constructorCall.call(newTarget, args, next);
|
|
127
|
+
};
|
|
128
|
+
handler.set = function(target, propertyName, nextValue) {
|
|
129
|
+
const next = () => {
|
|
130
|
+
const propertySource = findPropertySource(target, propertyName) || target;
|
|
131
|
+
const ownDescriptors = Reflect.getOwnPropertyDescriptor(propertySource, propertyName);
|
|
132
|
+
if (typeof ownDescriptors?.set !== "undefined") {
|
|
133
|
+
ownDescriptors.set.apply(target, [nextValue]);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
return Reflect.defineProperty(propertySource, propertyName, {
|
|
137
|
+
writable: true,
|
|
138
|
+
enumerable: true,
|
|
139
|
+
configurable: true,
|
|
140
|
+
value: nextValue
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
if (typeof setProperty !== "undefined") return setProperty.call(target, [propertyName, nextValue], next);
|
|
144
|
+
return next();
|
|
145
|
+
};
|
|
146
|
+
handler.get = function(target, propertyName, receiver) {
|
|
147
|
+
/**
|
|
148
|
+
* @note Using `Reflect.get()` here causes "TypeError: Illegal invocation".
|
|
149
|
+
*/
|
|
150
|
+
const next = () => target[propertyName];
|
|
151
|
+
const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next();
|
|
152
|
+
if (typeof value === "function") return (...args) => {
|
|
153
|
+
const next$1 = value.bind(target, ...args);
|
|
154
|
+
if (typeof methodCall !== "undefined") return methodCall.call(target, [propertyName, args], next$1);
|
|
155
|
+
return next$1();
|
|
156
|
+
};
|
|
157
|
+
return value;
|
|
158
|
+
};
|
|
159
|
+
return handler;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts
|
|
164
|
+
function isDomParserSupportedType(type) {
|
|
165
|
+
return [
|
|
166
|
+
"application/xhtml+xml",
|
|
167
|
+
"application/xml",
|
|
168
|
+
"image/svg+xml",
|
|
169
|
+
"text/html",
|
|
170
|
+
"text/xml"
|
|
171
|
+
].some((supportedType) => {
|
|
172
|
+
return type.startsWith(supportedType);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/utils/parseJson.ts
|
|
178
|
+
/**
|
|
179
|
+
* Parses a given string into JSON.
|
|
180
|
+
* Gracefully handles invalid JSON by returning `null`.
|
|
181
|
+
*/
|
|
182
|
+
function parseJson(data) {
|
|
183
|
+
try {
|
|
184
|
+
return JSON.parse(data);
|
|
185
|
+
} catch (_) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region src/interceptors/XMLHttpRequest/utils/createResponse.ts
|
|
192
|
+
/**
|
|
193
|
+
* Creates a Fetch API `Response` instance from the given
|
|
194
|
+
* `XMLHttpRequest` instance and a response body.
|
|
195
|
+
*/
|
|
196
|
+
function createResponse(request, body) {
|
|
197
|
+
return new FetchResponse(FetchResponse.isResponseWithBody(request.status) ? body : null, {
|
|
198
|
+
url: request.responseURL,
|
|
199
|
+
status: request.status,
|
|
200
|
+
statusText: request.statusText,
|
|
201
|
+
headers: createHeadersFromXMLHttpRequestHeaders(request.getAllResponseHeaders())
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function createHeadersFromXMLHttpRequestHeaders(headersString) {
|
|
205
|
+
const headers = new Headers();
|
|
206
|
+
const lines = headersString.split(/[\r\n]+/);
|
|
207
|
+
for (const line of lines) {
|
|
208
|
+
if (line.trim() === "") continue;
|
|
209
|
+
const [name, ...parts] = line.split(": ");
|
|
210
|
+
const value = parts.join(": ");
|
|
211
|
+
headers.append(name, value);
|
|
212
|
+
}
|
|
213
|
+
return headers;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts
|
|
218
|
+
/**
|
|
219
|
+
* Return a total byte length of the given request/response body.
|
|
220
|
+
* If the `Content-Length` header is present, it will be used as the byte length.
|
|
221
|
+
*/
|
|
222
|
+
async function getBodyByteLength(input) {
|
|
223
|
+
const explicitContentLength = input.headers.get("content-length");
|
|
224
|
+
if (explicitContentLength != null && explicitContentLength !== "") return Number(explicitContentLength);
|
|
225
|
+
return (await input.arrayBuffer()).byteLength;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts
|
|
230
|
+
const kIsRequestHandled = Symbol("kIsRequestHandled");
|
|
231
|
+
const IS_NODE = isNodeProcess();
|
|
232
|
+
const kFetchRequest = Symbol("kFetchRequest");
|
|
233
|
+
/**
|
|
234
|
+
* An `XMLHttpRequest` instance controller that allows us
|
|
235
|
+
* to handle any given request instance (e.g. responding to it).
|
|
236
|
+
*/
|
|
237
|
+
var XMLHttpRequestController = class {
|
|
238
|
+
constructor(initialRequest, logger) {
|
|
239
|
+
this.initialRequest = initialRequest;
|
|
240
|
+
this.logger = logger;
|
|
241
|
+
this.method = "GET";
|
|
242
|
+
this.url = null;
|
|
243
|
+
this[kIsRequestHandled] = false;
|
|
244
|
+
this.events = /* @__PURE__ */ new Map();
|
|
245
|
+
this.uploadEvents = /* @__PURE__ */ new Map();
|
|
246
|
+
this.requestId = createRequestId();
|
|
247
|
+
this.requestHeaders = new Headers();
|
|
248
|
+
this.responseBuffer = new Uint8Array();
|
|
249
|
+
this.request = createProxy(initialRequest, {
|
|
250
|
+
setProperty: ([propertyName, nextValue], invoke) => {
|
|
251
|
+
switch (propertyName) {
|
|
252
|
+
case "ontimeout": {
|
|
253
|
+
const eventName = propertyName.slice(2);
|
|
254
|
+
/**
|
|
255
|
+
* @note Proxy callbacks to event listeners because JSDOM has trouble
|
|
256
|
+
* translating these properties to callbacks. It seemed to be operating
|
|
257
|
+
* on events exclusively.
|
|
258
|
+
*/
|
|
259
|
+
this.request.addEventListener(eventName, nextValue);
|
|
260
|
+
return invoke();
|
|
261
|
+
}
|
|
262
|
+
default: return invoke();
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
methodCall: ([methodName, args], invoke) => {
|
|
266
|
+
switch (methodName) {
|
|
267
|
+
case "open": {
|
|
268
|
+
const [method, url] = args;
|
|
269
|
+
if (typeof url === "undefined") {
|
|
270
|
+
this.method = "GET";
|
|
271
|
+
this.url = toAbsoluteUrl(method);
|
|
272
|
+
} else {
|
|
273
|
+
this.method = method;
|
|
274
|
+
this.url = toAbsoluteUrl(url);
|
|
275
|
+
}
|
|
276
|
+
this.logger = this.logger.extend(`${this.method} ${this.url.href}`);
|
|
277
|
+
this.logger.info("open", this.method, this.url.href);
|
|
278
|
+
return invoke();
|
|
279
|
+
}
|
|
280
|
+
case "addEventListener": {
|
|
281
|
+
const [eventName, listener] = args;
|
|
282
|
+
this.registerEvent(eventName, listener);
|
|
283
|
+
this.logger.info("addEventListener", eventName, listener);
|
|
284
|
+
return invoke();
|
|
285
|
+
}
|
|
286
|
+
case "setRequestHeader": {
|
|
287
|
+
const [name, value] = args;
|
|
288
|
+
this.requestHeaders.set(name, value);
|
|
289
|
+
this.logger.info("setRequestHeader", name, value);
|
|
290
|
+
return invoke();
|
|
291
|
+
}
|
|
292
|
+
case "send": {
|
|
293
|
+
const [body] = args;
|
|
294
|
+
this.request.addEventListener("load", () => {
|
|
295
|
+
if (typeof this.onResponse !== "undefined") {
|
|
296
|
+
const fetchResponse = createResponse(
|
|
297
|
+
this.request,
|
|
298
|
+
/**
|
|
299
|
+
* The `response` property is the right way to read
|
|
300
|
+
* the ambiguous response body, as the request's "responseType" may differ.
|
|
301
|
+
* @see https://xhr.spec.whatwg.org/#the-response-attribute
|
|
302
|
+
*/
|
|
303
|
+
this.request.response
|
|
304
|
+
);
|
|
305
|
+
this.onResponse.call(this, {
|
|
306
|
+
response: fetchResponse,
|
|
307
|
+
isMockedResponse: this[kIsRequestHandled],
|
|
308
|
+
request: fetchRequest,
|
|
309
|
+
requestId: this.requestId
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
const requestBody = typeof body === "string" ? encodeBuffer(body) : body;
|
|
314
|
+
const fetchRequest = this.toFetchApiRequest(requestBody);
|
|
315
|
+
this[kFetchRequest] = fetchRequest.clone();
|
|
316
|
+
/**
|
|
317
|
+
* @note Start request handling on the next tick so that the user
|
|
318
|
+
* could add event listeners for "loadend" before the interceptor fires it.
|
|
319
|
+
*/
|
|
320
|
+
queueMicrotask(() => {
|
|
321
|
+
(this.onRequest?.call(this, {
|
|
322
|
+
request: fetchRequest,
|
|
323
|
+
requestId: this.requestId
|
|
324
|
+
}) || Promise.resolve()).finally(() => {
|
|
325
|
+
if (!this[kIsRequestHandled]) {
|
|
326
|
+
this.logger.info("request callback settled but request has not been handled (readystate %d), performing as-is...", this.request.readyState);
|
|
327
|
+
/**
|
|
328
|
+
* @note Set the intercepted request ID on the original request in Node.js
|
|
329
|
+
* so that if it triggers any other interceptors, they don't attempt
|
|
330
|
+
* to process it once again.
|
|
331
|
+
*
|
|
332
|
+
* For instance, XMLHttpRequest is often implemented via "http.ClientRequest"
|
|
333
|
+
* and we don't want for both XHR and ClientRequest interceptors to
|
|
334
|
+
* handle the same request at the same time (e.g. emit the "response" event twice).
|
|
335
|
+
*/
|
|
336
|
+
if (IS_NODE) this.request.setRequestHeader(INTERNAL_REQUEST_ID_HEADER_NAME, this.requestId);
|
|
337
|
+
return invoke();
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
default: return invoke();
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
/**
|
|
348
|
+
* Proxy the `.upload` property to gather the event listeners/callbacks.
|
|
349
|
+
*/
|
|
350
|
+
define(this.request, "upload", createProxy(this.request.upload, {
|
|
351
|
+
setProperty: ([propertyName, nextValue], invoke) => {
|
|
352
|
+
switch (propertyName) {
|
|
353
|
+
case "onloadstart":
|
|
354
|
+
case "onprogress":
|
|
355
|
+
case "onaboart":
|
|
356
|
+
case "onerror":
|
|
357
|
+
case "onload":
|
|
358
|
+
case "ontimeout":
|
|
359
|
+
case "onloadend": {
|
|
360
|
+
const eventName = propertyName.slice(2);
|
|
361
|
+
this.registerUploadEvent(eventName, nextValue);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return invoke();
|
|
365
|
+
},
|
|
366
|
+
methodCall: ([methodName, args], invoke) => {
|
|
367
|
+
switch (methodName) {
|
|
368
|
+
case "addEventListener": {
|
|
369
|
+
const [eventName, listener] = args;
|
|
370
|
+
this.registerUploadEvent(eventName, listener);
|
|
371
|
+
this.logger.info("upload.addEventListener", eventName, listener);
|
|
372
|
+
return invoke();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}));
|
|
377
|
+
}
|
|
378
|
+
registerEvent(eventName, listener) {
|
|
379
|
+
const nextEvents = (this.events.get(eventName) || []).concat(listener);
|
|
380
|
+
this.events.set(eventName, nextEvents);
|
|
381
|
+
this.logger.info("registered event \"%s\"", eventName, listener);
|
|
382
|
+
}
|
|
383
|
+
registerUploadEvent(eventName, listener) {
|
|
384
|
+
const nextEvents = (this.uploadEvents.get(eventName) || []).concat(listener);
|
|
385
|
+
this.uploadEvents.set(eventName, nextEvents);
|
|
386
|
+
this.logger.info("registered upload event \"%s\"", eventName, listener);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Responds to the current request with the given
|
|
390
|
+
* Fetch API `Response` instance.
|
|
391
|
+
*/
|
|
392
|
+
async respondWith(response) {
|
|
393
|
+
/**
|
|
394
|
+
* @note Since `XMLHttpRequestController` delegates the handling of the responses
|
|
395
|
+
* to the "load" event listener that doesn't distinguish between the mocked and original
|
|
396
|
+
* responses, mark the request that had a mocked response with a corresponding symbol.
|
|
397
|
+
*
|
|
398
|
+
* Mark this request as having a mocked response immediately since
|
|
399
|
+
* calculating request/response total body length is asynchronous.
|
|
400
|
+
*/
|
|
401
|
+
this[kIsRequestHandled] = true;
|
|
402
|
+
/**
|
|
403
|
+
* Dispatch request upload events for requests with a body.
|
|
404
|
+
* @see https://github.com/mswjs/interceptors/issues/573
|
|
405
|
+
*/
|
|
406
|
+
if (this[kFetchRequest]) {
|
|
407
|
+
const totalRequestBodyLength = await getBodyByteLength(this[kFetchRequest]);
|
|
408
|
+
this.trigger("loadstart", this.request.upload, {
|
|
409
|
+
loaded: 0,
|
|
410
|
+
total: totalRequestBodyLength
|
|
411
|
+
});
|
|
412
|
+
this.trigger("progress", this.request.upload, {
|
|
413
|
+
loaded: totalRequestBodyLength,
|
|
414
|
+
total: totalRequestBodyLength
|
|
415
|
+
});
|
|
416
|
+
this.trigger("load", this.request.upload, {
|
|
417
|
+
loaded: totalRequestBodyLength,
|
|
418
|
+
total: totalRequestBodyLength
|
|
419
|
+
});
|
|
420
|
+
this.trigger("loadend", this.request.upload, {
|
|
421
|
+
loaded: totalRequestBodyLength,
|
|
422
|
+
total: totalRequestBodyLength
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
this.logger.info("responding with a mocked response: %d %s", response.status, response.statusText);
|
|
426
|
+
define(this.request, "status", response.status);
|
|
427
|
+
define(this.request, "statusText", response.statusText);
|
|
428
|
+
define(this.request, "responseURL", this.url.href);
|
|
429
|
+
this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, { apply: (_, __, args) => {
|
|
430
|
+
this.logger.info("getResponseHeader", args[0]);
|
|
431
|
+
if (this.request.readyState < this.request.HEADERS_RECEIVED) {
|
|
432
|
+
this.logger.info("headers not received yet, returning null");
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
const headerValue = response.headers.get(args[0]);
|
|
436
|
+
this.logger.info("resolved response header \"%s\" to", args[0], headerValue);
|
|
437
|
+
return headerValue;
|
|
438
|
+
} });
|
|
439
|
+
this.request.getAllResponseHeaders = new Proxy(this.request.getAllResponseHeaders, { apply: () => {
|
|
440
|
+
this.logger.info("getAllResponseHeaders");
|
|
441
|
+
if (this.request.readyState < this.request.HEADERS_RECEIVED) {
|
|
442
|
+
this.logger.info("headers not received yet, returning empty string");
|
|
443
|
+
return "";
|
|
444
|
+
}
|
|
445
|
+
const allHeaders = Array.from(response.headers.entries()).map(([headerName, headerValue]) => {
|
|
446
|
+
return `${headerName}: ${headerValue}`;
|
|
447
|
+
}).join("\r\n");
|
|
448
|
+
this.logger.info("resolved all response headers to", allHeaders);
|
|
449
|
+
return allHeaders;
|
|
450
|
+
} });
|
|
451
|
+
Object.defineProperties(this.request, {
|
|
452
|
+
response: {
|
|
453
|
+
enumerable: true,
|
|
454
|
+
configurable: false,
|
|
455
|
+
get: () => this.response
|
|
456
|
+
},
|
|
457
|
+
responseText: {
|
|
458
|
+
enumerable: true,
|
|
459
|
+
configurable: false,
|
|
460
|
+
get: () => this.responseText
|
|
461
|
+
},
|
|
462
|
+
responseXML: {
|
|
463
|
+
enumerable: true,
|
|
464
|
+
configurable: false,
|
|
465
|
+
get: () => this.responseXML
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
const totalResponseBodyLength = await getBodyByteLength(response.clone());
|
|
469
|
+
this.logger.info("calculated response body length", totalResponseBodyLength);
|
|
470
|
+
this.trigger("loadstart", this.request, {
|
|
471
|
+
loaded: 0,
|
|
472
|
+
total: totalResponseBodyLength
|
|
473
|
+
});
|
|
474
|
+
this.setReadyState(this.request.HEADERS_RECEIVED);
|
|
475
|
+
this.setReadyState(this.request.LOADING);
|
|
476
|
+
const finalizeResponse = () => {
|
|
477
|
+
this.logger.info("finalizing the mocked response...");
|
|
478
|
+
this.setReadyState(this.request.DONE);
|
|
479
|
+
this.trigger("load", this.request, {
|
|
480
|
+
loaded: this.responseBuffer.byteLength,
|
|
481
|
+
total: totalResponseBodyLength
|
|
482
|
+
});
|
|
483
|
+
this.trigger("loadend", this.request, {
|
|
484
|
+
loaded: this.responseBuffer.byteLength,
|
|
485
|
+
total: totalResponseBodyLength
|
|
486
|
+
});
|
|
487
|
+
};
|
|
488
|
+
if (response.body) {
|
|
489
|
+
this.logger.info("mocked response has body, streaming...");
|
|
490
|
+
const reader = response.body.getReader();
|
|
491
|
+
const readNextResponseBodyChunk = async () => {
|
|
492
|
+
const { value, done } = await reader.read();
|
|
493
|
+
if (done) {
|
|
494
|
+
this.logger.info("response body stream done!");
|
|
495
|
+
finalizeResponse();
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (value) {
|
|
499
|
+
this.logger.info("read response body chunk:", value);
|
|
500
|
+
this.responseBuffer = concatArrayBuffer(this.responseBuffer, value);
|
|
501
|
+
this.trigger("progress", this.request, {
|
|
502
|
+
loaded: this.responseBuffer.byteLength,
|
|
503
|
+
total: totalResponseBodyLength
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
readNextResponseBodyChunk();
|
|
507
|
+
};
|
|
508
|
+
readNextResponseBodyChunk();
|
|
509
|
+
} else finalizeResponse();
|
|
510
|
+
}
|
|
511
|
+
responseBufferToText() {
|
|
512
|
+
return decodeBuffer(this.responseBuffer);
|
|
513
|
+
}
|
|
514
|
+
get response() {
|
|
515
|
+
this.logger.info("getResponse (responseType: %s)", this.request.responseType);
|
|
516
|
+
if (this.request.readyState !== this.request.DONE) return null;
|
|
517
|
+
switch (this.request.responseType) {
|
|
518
|
+
case "json": {
|
|
519
|
+
const responseJson = parseJson(this.responseBufferToText());
|
|
520
|
+
this.logger.info("resolved response JSON", responseJson);
|
|
521
|
+
return responseJson;
|
|
522
|
+
}
|
|
523
|
+
case "arraybuffer": {
|
|
524
|
+
const arrayBuffer = toArrayBuffer(this.responseBuffer);
|
|
525
|
+
this.logger.info("resolved response ArrayBuffer", arrayBuffer);
|
|
526
|
+
return arrayBuffer;
|
|
527
|
+
}
|
|
528
|
+
case "blob": {
|
|
529
|
+
const mimeType = this.request.getResponseHeader("Content-Type") || "text/plain";
|
|
530
|
+
const responseBlob = new Blob([this.responseBufferToText()], { type: mimeType });
|
|
531
|
+
this.logger.info("resolved response Blob (mime type: %s)", responseBlob, mimeType);
|
|
532
|
+
return responseBlob;
|
|
533
|
+
}
|
|
534
|
+
default: {
|
|
535
|
+
const responseText = this.responseBufferToText();
|
|
536
|
+
this.logger.info("resolving \"%s\" response type as text", this.request.responseType, responseText);
|
|
537
|
+
return responseText;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
get responseText() {
|
|
542
|
+
/**
|
|
543
|
+
* Throw when trying to read the response body as text when the
|
|
544
|
+
* "responseType" doesn't expect text. This just respects the spec better.
|
|
545
|
+
* @see https://xhr.spec.whatwg.org/#the-responsetext-attribute
|
|
546
|
+
*/
|
|
547
|
+
invariant(this.request.responseType === "" || this.request.responseType === "text", "InvalidStateError: The object is in invalid state.");
|
|
548
|
+
if (this.request.readyState !== this.request.LOADING && this.request.readyState !== this.request.DONE) return "";
|
|
549
|
+
const responseText = this.responseBufferToText();
|
|
550
|
+
this.logger.info("getResponseText: \"%s\"", responseText);
|
|
551
|
+
return responseText;
|
|
552
|
+
}
|
|
553
|
+
get responseXML() {
|
|
554
|
+
invariant(this.request.responseType === "" || this.request.responseType === "document", "InvalidStateError: The object is in invalid state.");
|
|
555
|
+
if (this.request.readyState !== this.request.DONE) return null;
|
|
556
|
+
const contentType = this.request.getResponseHeader("Content-Type") || "";
|
|
557
|
+
if (typeof DOMParser === "undefined") {
|
|
558
|
+
console.warn("Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.");
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
if (isDomParserSupportedType(contentType)) return new DOMParser().parseFromString(this.responseBufferToText(), contentType);
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
errorWith(error) {
|
|
565
|
+
/**
|
|
566
|
+
* @note Mark this request as handled even if it received a mock error.
|
|
567
|
+
* This prevents the controller from trying to perform this request as-is.
|
|
568
|
+
*/
|
|
569
|
+
this[kIsRequestHandled] = true;
|
|
570
|
+
this.logger.info("responding with an error");
|
|
571
|
+
this.setReadyState(this.request.DONE);
|
|
572
|
+
this.trigger("error", this.request);
|
|
573
|
+
this.trigger("loadend", this.request);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Transitions this request's `readyState` to the given one.
|
|
577
|
+
*/
|
|
578
|
+
setReadyState(nextReadyState) {
|
|
579
|
+
this.logger.info("setReadyState: %d -> %d", this.request.readyState, nextReadyState);
|
|
580
|
+
if (this.request.readyState === nextReadyState) {
|
|
581
|
+
this.logger.info("ready state identical, skipping transition...");
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
define(this.request, "readyState", nextReadyState);
|
|
585
|
+
this.logger.info("set readyState to: %d", nextReadyState);
|
|
586
|
+
if (nextReadyState !== this.request.UNSENT) {
|
|
587
|
+
this.logger.info("triggering \"readystatechange\" event...");
|
|
588
|
+
this.trigger("readystatechange", this.request);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Triggers given event on the `XMLHttpRequest` instance.
|
|
593
|
+
*/
|
|
594
|
+
trigger(eventName, target, options) {
|
|
595
|
+
const callback = target[`on${eventName}`];
|
|
596
|
+
const event = createEvent(target, eventName, options);
|
|
597
|
+
this.logger.info("trigger \"%s\"", eventName, options || "");
|
|
598
|
+
if (typeof callback === "function") {
|
|
599
|
+
this.logger.info("found a direct \"%s\" callback, calling...", eventName);
|
|
600
|
+
callback.call(target, event);
|
|
601
|
+
}
|
|
602
|
+
const events = target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events;
|
|
603
|
+
for (const [registeredEventName, listeners] of events) if (registeredEventName === eventName) {
|
|
604
|
+
this.logger.info("found %d listener(s) for \"%s\" event, calling...", listeners.length, eventName);
|
|
605
|
+
listeners.forEach((listener) => listener.call(target, event));
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance.
|
|
610
|
+
*/
|
|
611
|
+
toFetchApiRequest(body) {
|
|
612
|
+
this.logger.info("converting request to a Fetch API Request...");
|
|
613
|
+
const resolvedBody = body instanceof Document ? body.documentElement.innerText : body;
|
|
614
|
+
const fetchRequest = new Request(this.url.href, {
|
|
615
|
+
method: this.method,
|
|
616
|
+
headers: this.requestHeaders,
|
|
617
|
+
credentials: this.request.withCredentials ? "include" : "same-origin",
|
|
618
|
+
body: ["GET", "HEAD"].includes(this.method.toUpperCase()) ? null : resolvedBody
|
|
619
|
+
});
|
|
620
|
+
define(fetchRequest, "headers", createProxy(fetchRequest.headers, { methodCall: ([methodName, args], invoke) => {
|
|
621
|
+
switch (methodName) {
|
|
622
|
+
case "append":
|
|
623
|
+
case "set": {
|
|
624
|
+
const [headerName, headerValue] = args;
|
|
625
|
+
this.request.setRequestHeader(headerName, headerValue);
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
case "delete": {
|
|
629
|
+
const [headerName] = args;
|
|
630
|
+
console.warn(`XMLHttpRequest: Cannot remove a "${headerName}" header from the Fetch API representation of the "${fetchRequest.method} ${fetchRequest.url}" request. XMLHttpRequest headers cannot be removed.`);
|
|
631
|
+
break;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return invoke();
|
|
635
|
+
} }));
|
|
636
|
+
setRawRequest(fetchRequest, this.request);
|
|
637
|
+
this.logger.info("converted request to a Fetch API Request!", fetchRequest);
|
|
638
|
+
return fetchRequest;
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
function toAbsoluteUrl(url) {
|
|
642
|
+
/**
|
|
643
|
+
* @note XMLHttpRequest interceptor may run in environments
|
|
644
|
+
* that implement XMLHttpRequest but don't implement "location"
|
|
645
|
+
* (for example, React Native). If that's the case, return the
|
|
646
|
+
* input URL as-is (nothing to be relative to).
|
|
647
|
+
* @see https://github.com/mswjs/msw/issues/1777
|
|
648
|
+
*/
|
|
649
|
+
if (typeof location === "undefined") return new URL(url);
|
|
650
|
+
return new URL(url.toString(), location.href);
|
|
651
|
+
}
|
|
652
|
+
function define(target, property, value) {
|
|
653
|
+
Reflect.defineProperty(target, property, {
|
|
654
|
+
writable: true,
|
|
655
|
+
enumerable: true,
|
|
656
|
+
value
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
//#endregion
|
|
661
|
+
//#region src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts
|
|
662
|
+
/**
|
|
663
|
+
* Create a proxied `XMLHttpRequest` class.
|
|
664
|
+
* The proxied class establishes spies on certain methods,
|
|
665
|
+
* allowing us to intercept requests and respond to them.
|
|
666
|
+
*/
|
|
667
|
+
function createXMLHttpRequestProxy({ emitter, logger }) {
|
|
668
|
+
return new Proxy(globalThis.XMLHttpRequest, { construct(target, args, newTarget) {
|
|
669
|
+
logger.info("constructed new XMLHttpRequest");
|
|
670
|
+
const originalRequest = Reflect.construct(target, args, newTarget);
|
|
671
|
+
/**
|
|
672
|
+
* @note Forward prototype descriptors onto the proxied object.
|
|
673
|
+
* XMLHttpRequest is implemented in JSDOM in a way that assigns
|
|
674
|
+
* a bunch of descriptors, like "set responseType()" on the prototype.
|
|
675
|
+
* With this propagation, we make sure that those descriptors trigger
|
|
676
|
+
* when the user operates with the proxied request instance.
|
|
677
|
+
*/
|
|
678
|
+
const prototypeDescriptors = Object.getOwnPropertyDescriptors(target.prototype);
|
|
679
|
+
for (const propertyName in prototypeDescriptors) Reflect.defineProperty(originalRequest, propertyName, prototypeDescriptors[propertyName]);
|
|
680
|
+
const xhrRequestController = new XMLHttpRequestController(originalRequest, logger);
|
|
681
|
+
xhrRequestController.onRequest = async function({ request, requestId }) {
|
|
682
|
+
const controller = new RequestController(request, {
|
|
683
|
+
passthrough: () => {
|
|
684
|
+
this.logger.info("no mocked response received, performing request as-is...");
|
|
685
|
+
},
|
|
686
|
+
respondWith: async (response) => {
|
|
687
|
+
if (isResponseError(response)) {
|
|
688
|
+
this.errorWith(/* @__PURE__ */ new TypeError("Network error"));
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
await this.respondWith(response);
|
|
692
|
+
},
|
|
693
|
+
errorWith: (reason) => {
|
|
694
|
+
this.logger.info("request errored!", { error: reason });
|
|
695
|
+
if (reason instanceof Error) this.errorWith(reason);
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
this.logger.info("awaiting mocked response...");
|
|
699
|
+
this.logger.info("emitting the \"request\" event for %s listener(s)...", emitter.listenerCount("request"));
|
|
700
|
+
await handleRequest({
|
|
701
|
+
request,
|
|
702
|
+
requestId,
|
|
703
|
+
controller,
|
|
704
|
+
emitter
|
|
705
|
+
});
|
|
706
|
+
};
|
|
707
|
+
xhrRequestController.onResponse = async function({ response, isMockedResponse, request, requestId }) {
|
|
708
|
+
this.logger.info("emitting the \"response\" event for %s listener(s)...", emitter.listenerCount("response"));
|
|
709
|
+
emitter.emit("response", {
|
|
710
|
+
response,
|
|
711
|
+
isMockedResponse,
|
|
712
|
+
request,
|
|
713
|
+
requestId
|
|
714
|
+
});
|
|
715
|
+
};
|
|
716
|
+
return xhrRequestController.request;
|
|
717
|
+
} });
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
//#endregion
|
|
721
|
+
//#region src/interceptors/XMLHttpRequest/index.ts
|
|
722
|
+
var XMLHttpRequestInterceptor = class XMLHttpRequestInterceptor extends Interceptor {
|
|
723
|
+
static {
|
|
724
|
+
this.interceptorSymbol = Symbol("xhr");
|
|
725
|
+
}
|
|
726
|
+
constructor() {
|
|
727
|
+
super(XMLHttpRequestInterceptor.interceptorSymbol);
|
|
728
|
+
}
|
|
729
|
+
checkEnvironment() {
|
|
730
|
+
return hasConfigurableGlobal("XMLHttpRequest");
|
|
731
|
+
}
|
|
732
|
+
setup() {
|
|
733
|
+
const logger = this.logger.extend("setup");
|
|
734
|
+
logger.info("patching \"XMLHttpRequest\" module...");
|
|
735
|
+
const PureXMLHttpRequest = globalThis.XMLHttpRequest;
|
|
736
|
+
invariant(!PureXMLHttpRequest[IS_PATCHED_MODULE], "Failed to patch the \"XMLHttpRequest\" module: already patched.");
|
|
737
|
+
globalThis.XMLHttpRequest = createXMLHttpRequestProxy({
|
|
738
|
+
emitter: this.emitter,
|
|
739
|
+
logger: this.logger
|
|
740
|
+
});
|
|
741
|
+
logger.info("native \"XMLHttpRequest\" module patched!", globalThis.XMLHttpRequest.name);
|
|
742
|
+
Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {
|
|
743
|
+
enumerable: true,
|
|
744
|
+
configurable: true,
|
|
745
|
+
value: true
|
|
746
|
+
});
|
|
747
|
+
this.subscriptions.push(() => {
|
|
748
|
+
Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { value: void 0 });
|
|
749
|
+
globalThis.XMLHttpRequest = PureXMLHttpRequest;
|
|
750
|
+
logger.info("native \"XMLHttpRequest\" module restored!", globalThis.XMLHttpRequest.name);
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
//#endregion
|
|
756
|
+
export { XMLHttpRequestInterceptor as t };
|
|
757
|
+
//# sourceMappingURL=XMLHttpRequest-C8dIZpds.mjs.map
|