@mswjs/interceptors 0.24.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/{chunk-B74BGPYH.mjs → chunk-BRIUGDYQ.mjs} +3 -1
- package/lib/browser/{chunk-LHYX2GOM.mjs → chunk-KSCN3JS4.mjs} +15 -1
- package/lib/browser/{chunk-2TENISKM.js → chunk-XAQQ5IUC.js} +15 -1
- package/lib/browser/{chunk-UGP4JOAM.js → chunk-Y4XXQXAW.js} +3 -1
- package/lib/browser/interceptors/XMLHttpRequest/index.js +2 -2
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs +1 -1
- package/lib/browser/interceptors/fetch/index.js +2 -2
- package/lib/browser/interceptors/fetch/index.mjs +1 -1
- package/lib/browser/presets/browser.js +4 -4
- package/lib/browser/presets/browser.mjs +2 -2
- package/lib/node/RemoteHttpInterceptor.js +2 -2
- package/lib/node/RemoteHttpInterceptor.mjs +1 -1
- package/lib/node/{chunk-YCEMBJEM.js → chunk-NM5BWVVB.js} +3 -1
- package/lib/node/{chunk-UWSK5F3S.mjs → chunk-SOWOSKLO.mjs} +3 -1
- package/lib/node/interceptors/XMLHttpRequest/index.js +2 -2
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +1 -1
- package/lib/node/interceptors/fetch/index.js +15 -1
- package/lib/node/interceptors/fetch/index.mjs +15 -1
- package/lib/node/presets/node.js +2 -2
- package/lib/node/presets/node.mjs +1 -1
- package/package.json +5 -5
- package/src/interceptors/ClientRequest/index.test.ts +28 -0
- package/src/interceptors/XMLHttpRequest/utils/createResponse.ts +15 -1
- package/src/interceptors/fetch/index.ts +21 -1
|
@@ -202,8 +202,10 @@ function parseJson(data) {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
// src/interceptors/XMLHttpRequest/utils/createResponse.ts
|
|
205
|
+
var statusCodesWithoutBody = [204, 205, 304];
|
|
205
206
|
function createResponse(request, body) {
|
|
206
|
-
|
|
207
|
+
const responseBodyOrNull = statusCodesWithoutBody.includes(request.status) ? null : body;
|
|
208
|
+
return new Response(responseBodyOrNull, {
|
|
207
209
|
status: request.status,
|
|
208
210
|
statusText: request.statusText,
|
|
209
211
|
headers: createHeadersFromXMLHttpReqestHeaders(
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-GXJLJMOT.mjs";
|
|
9
9
|
|
|
10
10
|
// src/interceptors/fetch/index.ts
|
|
11
|
+
import { DeferredPromise } from "@open-draft/deferred-promise";
|
|
11
12
|
import { invariant } from "outvariant";
|
|
12
13
|
import { until } from "@open-draft/until";
|
|
13
14
|
var _FetchInterceptor = class extends Interceptor {
|
|
@@ -38,18 +39,31 @@ var _FetchInterceptor = class extends Interceptor {
|
|
|
38
39
|
requestId
|
|
39
40
|
});
|
|
40
41
|
this.logger.info("awaiting for the mocked response...");
|
|
42
|
+
const signal = interactiveRequest.signal;
|
|
43
|
+
const requestAborted = new DeferredPromise();
|
|
44
|
+
signal.addEventListener(
|
|
45
|
+
"abort",
|
|
46
|
+
() => {
|
|
47
|
+
requestAborted.reject(signal.reason);
|
|
48
|
+
},
|
|
49
|
+
{ once: true }
|
|
50
|
+
);
|
|
41
51
|
const resolverResult = await until(async () => {
|
|
42
|
-
|
|
52
|
+
const allListenersResolved = this.emitter.untilIdle(
|
|
43
53
|
"request",
|
|
44
54
|
({ args: [{ requestId: pendingRequestId }] }) => {
|
|
45
55
|
return pendingRequestId === requestId;
|
|
46
56
|
}
|
|
47
57
|
);
|
|
58
|
+
await Promise.race([requestAborted, allListenersResolved]);
|
|
48
59
|
this.logger.info("all request listeners have been resolved!");
|
|
49
60
|
const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
|
|
50
61
|
this.logger.info("event.respondWith called with:", mockedResponse2);
|
|
51
62
|
return mockedResponse2;
|
|
52
63
|
});
|
|
64
|
+
if (requestAborted.state === "rejected") {
|
|
65
|
+
return Promise.reject(requestAborted.rejectionReason);
|
|
66
|
+
}
|
|
53
67
|
if (resolverResult.error) {
|
|
54
68
|
const error = Object.assign(new TypeError("Failed to fetch"), {
|
|
55
69
|
cause: resolverResult.error
|
|
@@ -8,6 +8,7 @@ var _chunkPCFJD76Xjs = require('./chunk-PCFJD76X.js');
|
|
|
8
8
|
var _chunk4CFMDU7Zjs = require('./chunk-4CFMDU7Z.js');
|
|
9
9
|
|
|
10
10
|
// src/interceptors/fetch/index.ts
|
|
11
|
+
var _deferredpromise = require('@open-draft/deferred-promise');
|
|
11
12
|
var _outvariant = require('outvariant');
|
|
12
13
|
var _until = require('@open-draft/until');
|
|
13
14
|
var _FetchInterceptor = class extends _chunk4CFMDU7Zjs.Interceptor {
|
|
@@ -38,18 +39,31 @@ var _FetchInterceptor = class extends _chunk4CFMDU7Zjs.Interceptor {
|
|
|
38
39
|
requestId
|
|
39
40
|
});
|
|
40
41
|
this.logger.info("awaiting for the mocked response...");
|
|
42
|
+
const signal = interactiveRequest.signal;
|
|
43
|
+
const requestAborted = new (0, _deferredpromise.DeferredPromise)();
|
|
44
|
+
signal.addEventListener(
|
|
45
|
+
"abort",
|
|
46
|
+
() => {
|
|
47
|
+
requestAborted.reject(signal.reason);
|
|
48
|
+
},
|
|
49
|
+
{ once: true }
|
|
50
|
+
);
|
|
41
51
|
const resolverResult = await _until.until.call(void 0, async () => {
|
|
42
|
-
|
|
52
|
+
const allListenersResolved = this.emitter.untilIdle(
|
|
43
53
|
"request",
|
|
44
54
|
({ args: [{ requestId: pendingRequestId }] }) => {
|
|
45
55
|
return pendingRequestId === requestId;
|
|
46
56
|
}
|
|
47
57
|
);
|
|
58
|
+
await Promise.race([requestAborted, allListenersResolved]);
|
|
48
59
|
this.logger.info("all request listeners have been resolved!");
|
|
49
60
|
const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
|
|
50
61
|
this.logger.info("event.respondWith called with:", mockedResponse2);
|
|
51
62
|
return mockedResponse2;
|
|
52
63
|
});
|
|
64
|
+
if (requestAborted.state === "rejected") {
|
|
65
|
+
return Promise.reject(requestAborted.rejectionReason);
|
|
66
|
+
}
|
|
53
67
|
if (resolverResult.error) {
|
|
54
68
|
const error = Object.assign(new TypeError("Failed to fetch"), {
|
|
55
69
|
cause: resolverResult.error
|
|
@@ -202,8 +202,10 @@ function parseJson(data) {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
// src/interceptors/XMLHttpRequest/utils/createResponse.ts
|
|
205
|
+
var statusCodesWithoutBody = [204, 205, 304];
|
|
205
206
|
function createResponse(request, body) {
|
|
206
|
-
|
|
207
|
+
const responseBodyOrNull = statusCodesWithoutBody.includes(request.status) ? null : body;
|
|
208
|
+
return new Response(responseBodyOrNull, {
|
|
207
209
|
status: request.status,
|
|
208
210
|
statusText: request.statusText,
|
|
209
211
|
headers: createHeadersFromXMLHttpReqestHeaders(
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkY4XXQXAWjs = require('../../chunk-Y4XXQXAW.js');
|
|
4
4
|
require('../../chunk-3LFH2WCF.js');
|
|
5
5
|
require('../../chunk-PCFJD76X.js');
|
|
6
6
|
require('../../chunk-4CFMDU7Z.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
exports.XMLHttpRequestInterceptor =
|
|
9
|
+
exports.XMLHttpRequestInterceptor = _chunkY4XXQXAWjs.XMLHttpRequestInterceptor;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkXAQQ5IUCjs = require('../../chunk-XAQQ5IUC.js');
|
|
4
4
|
require('../../chunk-PCFJD76X.js');
|
|
5
5
|
require('../../chunk-4CFMDU7Z.js');
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
exports.FetchInterceptor =
|
|
8
|
+
exports.FetchInterceptor = _chunkXAQQ5IUCjs.FetchInterceptor;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkY4XXQXAWjs = require('../chunk-Y4XXQXAW.js');
|
|
4
4
|
require('../chunk-3LFH2WCF.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkXAQQ5IUCjs = require('../chunk-XAQQ5IUC.js');
|
|
8
8
|
require('../chunk-PCFJD76X.js');
|
|
9
9
|
require('../chunk-4CFMDU7Z.js');
|
|
10
10
|
|
|
11
11
|
// src/presets/browser.ts
|
|
12
12
|
var browser_default = [
|
|
13
|
-
new (0,
|
|
14
|
-
new (0,
|
|
13
|
+
new (0, _chunkXAQQ5IUCjs.FetchInterceptor)(),
|
|
14
|
+
new (0, _chunkY4XXQXAWjs.XMLHttpRequestInterceptor)()
|
|
15
15
|
];
|
|
16
16
|
|
|
17
17
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
XMLHttpRequestInterceptor
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-BRIUGDYQ.mjs";
|
|
4
4
|
import "../chunk-7II4SWKS.mjs";
|
|
5
5
|
import {
|
|
6
6
|
FetchInterceptor
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-KSCN3JS4.mjs";
|
|
8
8
|
import "../chunk-RT3ATOJH.mjs";
|
|
9
9
|
import "../chunk-GXJLJMOT.mjs";
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@ var _chunkMVPEJK4Vjs = require('./chunk-MVPEJK4V.js');
|
|
|
6
6
|
var _chunkOOSIWXHXjs = require('./chunk-OOSIWXHX.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunkNM5BWVVBjs = require('./chunk-NM5BWVVB.js');
|
|
10
10
|
require('./chunk-3LFH2WCF.js');
|
|
11
11
|
require('./chunk-VQ4DZOBB.js');
|
|
12
12
|
|
|
@@ -23,7 +23,7 @@ var RemoteHttpInterceptor = class extends _chunkMVPEJK4Vjs.BatchInterceptor {
|
|
|
23
23
|
name: "remote-interceptor",
|
|
24
24
|
interceptors: [
|
|
25
25
|
new (0, _chunkOOSIWXHXjs.ClientRequestInterceptor)(),
|
|
26
|
-
new (0,
|
|
26
|
+
new (0, _chunkNM5BWVVBjs.XMLHttpRequestInterceptor)()
|
|
27
27
|
]
|
|
28
28
|
});
|
|
29
29
|
}
|
|
@@ -204,8 +204,10 @@ function parseJson(data) {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
// src/interceptors/XMLHttpRequest/utils/createResponse.ts
|
|
207
|
+
var statusCodesWithoutBody = [204, 205, 304];
|
|
207
208
|
function createResponse(request, body) {
|
|
208
|
-
|
|
209
|
+
const responseBodyOrNull = statusCodesWithoutBody.includes(request.status) ? null : body;
|
|
210
|
+
return new Response(responseBodyOrNull, {
|
|
209
211
|
status: request.status,
|
|
210
212
|
statusText: request.statusText,
|
|
211
213
|
headers: createHeadersFromXMLHttpReqestHeaders(
|
|
@@ -204,8 +204,10 @@ function parseJson(data) {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
// src/interceptors/XMLHttpRequest/utils/createResponse.ts
|
|
207
|
+
var statusCodesWithoutBody = [204, 205, 304];
|
|
207
208
|
function createResponse(request, body) {
|
|
208
|
-
|
|
209
|
+
const responseBodyOrNull = statusCodesWithoutBody.includes(request.status) ? null : body;
|
|
210
|
+
return new Response(responseBodyOrNull, {
|
|
209
211
|
status: request.status,
|
|
210
212
|
statusText: request.statusText,
|
|
211
213
|
headers: createHeadersFromXMLHttpReqestHeaders(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkNM5BWVVBjs = require('../../chunk-NM5BWVVB.js');
|
|
4
4
|
require('../../chunk-3LFH2WCF.js');
|
|
5
5
|
require('../../chunk-VQ4DZOBB.js');
|
|
6
6
|
require('../../chunk-ZJOF5MEZ.js');
|
|
7
7
|
require('../../chunk-XYZRP5S2.js');
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
exports.XMLHttpRequestInterceptor =
|
|
10
|
+
exports.XMLHttpRequestInterceptor = _chunkNM5BWVVBjs.XMLHttpRequestInterceptor;
|
|
@@ -10,6 +10,7 @@ var _chunkZJOF5MEZjs = require('../../chunk-ZJOF5MEZ.js');
|
|
|
10
10
|
var _chunkXYZRP5S2js = require('../../chunk-XYZRP5S2.js');
|
|
11
11
|
|
|
12
12
|
// src/interceptors/fetch/index.ts
|
|
13
|
+
var _deferredpromise = require('@open-draft/deferred-promise');
|
|
13
14
|
var _outvariant = require('outvariant');
|
|
14
15
|
var _until = require('@open-draft/until');
|
|
15
16
|
var _FetchInterceptor = class extends _chunkXYZRP5S2js.Interceptor {
|
|
@@ -40,18 +41,31 @@ var _FetchInterceptor = class extends _chunkXYZRP5S2js.Interceptor {
|
|
|
40
41
|
requestId
|
|
41
42
|
});
|
|
42
43
|
this.logger.info("awaiting for the mocked response...");
|
|
44
|
+
const signal = interactiveRequest.signal;
|
|
45
|
+
const requestAborted = new (0, _deferredpromise.DeferredPromise)();
|
|
46
|
+
signal.addEventListener(
|
|
47
|
+
"abort",
|
|
48
|
+
() => {
|
|
49
|
+
requestAborted.reject(signal.reason);
|
|
50
|
+
},
|
|
51
|
+
{ once: true }
|
|
52
|
+
);
|
|
43
53
|
const resolverResult = await _until.until.call(void 0, async () => {
|
|
44
|
-
|
|
54
|
+
const allListenersResolved = this.emitter.untilIdle(
|
|
45
55
|
"request",
|
|
46
56
|
({ args: [{ requestId: pendingRequestId }] }) => {
|
|
47
57
|
return pendingRequestId === requestId;
|
|
48
58
|
}
|
|
49
59
|
);
|
|
60
|
+
await Promise.race([requestAborted, allListenersResolved]);
|
|
50
61
|
this.logger.info("all request listeners have been resolved!");
|
|
51
62
|
const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
|
|
52
63
|
this.logger.info("event.respondWith called with:", mockedResponse2);
|
|
53
64
|
return mockedResponse2;
|
|
54
65
|
});
|
|
66
|
+
if (requestAborted.state === "rejected") {
|
|
67
|
+
return Promise.reject(requestAborted.rejectionReason);
|
|
68
|
+
}
|
|
55
69
|
if (resolverResult.error) {
|
|
56
70
|
const error = Object.assign(new TypeError("Failed to fetch"), {
|
|
57
71
|
cause: resolverResult.error
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "../../chunk-RGYCLCLK.mjs";
|
|
11
11
|
|
|
12
12
|
// src/interceptors/fetch/index.ts
|
|
13
|
+
import { DeferredPromise } from "@open-draft/deferred-promise";
|
|
13
14
|
import { invariant } from "outvariant";
|
|
14
15
|
import { until } from "@open-draft/until";
|
|
15
16
|
var _FetchInterceptor = class extends Interceptor {
|
|
@@ -40,18 +41,31 @@ var _FetchInterceptor = class extends Interceptor {
|
|
|
40
41
|
requestId
|
|
41
42
|
});
|
|
42
43
|
this.logger.info("awaiting for the mocked response...");
|
|
44
|
+
const signal = interactiveRequest.signal;
|
|
45
|
+
const requestAborted = new DeferredPromise();
|
|
46
|
+
signal.addEventListener(
|
|
47
|
+
"abort",
|
|
48
|
+
() => {
|
|
49
|
+
requestAborted.reject(signal.reason);
|
|
50
|
+
},
|
|
51
|
+
{ once: true }
|
|
52
|
+
);
|
|
43
53
|
const resolverResult = await until(async () => {
|
|
44
|
-
|
|
54
|
+
const allListenersResolved = this.emitter.untilIdle(
|
|
45
55
|
"request",
|
|
46
56
|
({ args: [{ requestId: pendingRequestId }] }) => {
|
|
47
57
|
return pendingRequestId === requestId;
|
|
48
58
|
}
|
|
49
59
|
);
|
|
60
|
+
await Promise.race([requestAborted, allListenersResolved]);
|
|
50
61
|
this.logger.info("all request listeners have been resolved!");
|
|
51
62
|
const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
|
|
52
63
|
this.logger.info("event.respondWith called with:", mockedResponse2);
|
|
53
64
|
return mockedResponse2;
|
|
54
65
|
});
|
|
66
|
+
if (requestAborted.state === "rejected") {
|
|
67
|
+
return Promise.reject(requestAborted.rejectionReason);
|
|
68
|
+
}
|
|
55
69
|
if (resolverResult.error) {
|
|
56
70
|
const error = Object.assign(new TypeError("Failed to fetch"), {
|
|
57
71
|
cause: resolverResult.error
|
package/lib/node/presets/node.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var _chunkOOSIWXHXjs = require('../chunk-OOSIWXHX.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkNM5BWVVBjs = require('../chunk-NM5BWVVB.js');
|
|
7
7
|
require('../chunk-3LFH2WCF.js');
|
|
8
8
|
require('../chunk-VQ4DZOBB.js');
|
|
9
9
|
require('../chunk-ZJOF5MEZ.js');
|
|
@@ -12,7 +12,7 @@ require('../chunk-XYZRP5S2.js');
|
|
|
12
12
|
// src/presets/node.ts
|
|
13
13
|
var node_default = [
|
|
14
14
|
new (0, _chunkOOSIWXHXjs.ClientRequestInterceptor)(),
|
|
15
|
-
new (0,
|
|
15
|
+
new (0, _chunkNM5BWVVBjs.XMLHttpRequestInterceptor)()
|
|
16
16
|
];
|
|
17
17
|
|
|
18
18
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mswjs/interceptors",
|
|
3
3
|
"description": "Low-level HTTP/HTTPS/XHR/fetch request interception library.",
|
|
4
|
-
"version": "0.24.
|
|
4
|
+
"version": "0.24.1",
|
|
5
5
|
"main": "./lib/node/index.js",
|
|
6
6
|
"module": "./lib/node/index.mjs",
|
|
7
7
|
"types": "./lib/node/index.d.ts",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"./RemoteHttpInterceptor": {
|
|
47
47
|
"browser": null,
|
|
48
|
-
"types": "./lib/node/
|
|
49
|
-
"require": "./lib/node/
|
|
50
|
-
"import": "./lib/node/
|
|
51
|
-
"default": "./lib/node/
|
|
48
|
+
"types": "./lib/node/RemoteHttpInterceptor.d.ts",
|
|
49
|
+
"require": "./lib/node/RemoteHttpInterceptor.js",
|
|
50
|
+
"import": "./lib/node/RemoteHttpInterceptor.mjs",
|
|
51
|
+
"default": "./lib/node/RemoteHttpInterceptor.js"
|
|
52
52
|
},
|
|
53
53
|
"./presets/node": {
|
|
54
54
|
"browser": null,
|
|
@@ -3,6 +3,7 @@ import http from 'http'
|
|
|
3
3
|
import { HttpServer } from '@open-draft/test-server/http'
|
|
4
4
|
import { DeferredPromise } from '@open-draft/deferred-promise'
|
|
5
5
|
import { ClientRequestInterceptor } from '.'
|
|
6
|
+
import { sleep } from '../../../test/helpers'
|
|
6
7
|
|
|
7
8
|
const httpServer = new HttpServer((app) => {
|
|
8
9
|
app.get('/', (_req, res) => {
|
|
@@ -55,3 +56,30 @@ it('forbids calling "respondWith" multiple times for the same request', async ()
|
|
|
55
56
|
expect(response.statusCode).toBe(200)
|
|
56
57
|
expect(response.statusMessage).toBe('')
|
|
57
58
|
})
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
it('abort the request if the abort signal is emitted', async () => {
|
|
62
|
+
const requestUrl = httpServer.http.url('/')
|
|
63
|
+
|
|
64
|
+
const requestEmitted = new DeferredPromise<void>()
|
|
65
|
+
interceptor.on('request', async function delayedResponse({ request }) {
|
|
66
|
+
requestEmitted.resolve()
|
|
67
|
+
await sleep(10000)
|
|
68
|
+
request.respondWith(new Response())
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const abortController = new AbortController()
|
|
72
|
+
const request = http.get(requestUrl, { signal: abortController.signal })
|
|
73
|
+
|
|
74
|
+
await requestEmitted
|
|
75
|
+
|
|
76
|
+
abortController.abort()
|
|
77
|
+
|
|
78
|
+
const requestAborted = new DeferredPromise<void>()
|
|
79
|
+
request.on('error', function(err) {
|
|
80
|
+
expect(err.name).toEqual('AbortError')
|
|
81
|
+
requestAborted.resolve()
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
await requestAborted
|
|
85
|
+
})
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const statusCodesWithoutBody = [204, 205, 304]
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Creates a Fetch API `Response` instance from the given
|
|
3
5
|
* `XMLHttpRequest` instance and a response body.
|
|
@@ -6,7 +8,19 @@ export function createResponse(
|
|
|
6
8
|
request: XMLHttpRequest,
|
|
7
9
|
body: BodyInit | null
|
|
8
10
|
): Response {
|
|
9
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Handle XMLHttpRequest responses that must have null as the
|
|
13
|
+
* response body when represented using Fetch API Response.
|
|
14
|
+
* XMLHttpRequest response will always have an empty string
|
|
15
|
+
* as the "request.response" in those cases, resulting in an error
|
|
16
|
+
* when constructing a Response instance.
|
|
17
|
+
* @see https://github.com/mswjs/interceptors/issues/379
|
|
18
|
+
*/
|
|
19
|
+
const responseBodyOrNull = statusCodesWithoutBody.includes(request.status)
|
|
20
|
+
? null
|
|
21
|
+
: body
|
|
22
|
+
|
|
23
|
+
return new Response(responseBodyOrNull, {
|
|
10
24
|
status: request.status,
|
|
11
25
|
statusText: request.statusText,
|
|
12
26
|
headers: createHeadersFromXMLHttpReqestHeaders(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DeferredPromise } from '@open-draft/deferred-promise'
|
|
1
2
|
import { invariant } from 'outvariant'
|
|
2
3
|
import { until } from '@open-draft/until'
|
|
3
4
|
import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'
|
|
@@ -46,13 +47,27 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
|
46
47
|
|
|
47
48
|
this.logger.info('awaiting for the mocked response...')
|
|
48
49
|
|
|
50
|
+
const signal = interactiveRequest.signal
|
|
51
|
+
const requestAborted = new DeferredPromise()
|
|
52
|
+
|
|
53
|
+
signal.addEventListener(
|
|
54
|
+
'abort',
|
|
55
|
+
() => {
|
|
56
|
+
requestAborted.reject(signal.reason)
|
|
57
|
+
},
|
|
58
|
+
{ once: true }
|
|
59
|
+
)
|
|
60
|
+
|
|
49
61
|
const resolverResult = await until(async () => {
|
|
50
|
-
|
|
62
|
+
const allListenersResolved = this.emitter.untilIdle(
|
|
51
63
|
'request',
|
|
52
64
|
({ args: [{ requestId: pendingRequestId }] }) => {
|
|
53
65
|
return pendingRequestId === requestId
|
|
54
66
|
}
|
|
55
67
|
)
|
|
68
|
+
|
|
69
|
+
await Promise.race([requestAborted, allListenersResolved])
|
|
70
|
+
|
|
56
71
|
this.logger.info('all request listeners have been resolved!')
|
|
57
72
|
|
|
58
73
|
const [mockedResponse] = await interactiveRequest.respondWith.invoked()
|
|
@@ -61,10 +76,15 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
|
61
76
|
return mockedResponse
|
|
62
77
|
})
|
|
63
78
|
|
|
79
|
+
if (requestAborted.state === 'rejected') {
|
|
80
|
+
return Promise.reject(requestAborted.rejectionReason)
|
|
81
|
+
}
|
|
82
|
+
|
|
64
83
|
if (resolverResult.error) {
|
|
65
84
|
const error = Object.assign(new TypeError('Failed to fetch'), {
|
|
66
85
|
cause: resolverResult.error,
|
|
67
86
|
})
|
|
87
|
+
|
|
68
88
|
return Promise.reject(error)
|
|
69
89
|
}
|
|
70
90
|
|