@mswjs/interceptors 0.39.7 → 0.40.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/lib/browser/{chunk-PFGO5BSM.js → chunk-2HUMWGRD.js} +15 -3
- package/lib/browser/chunk-2HUMWGRD.js.map +1 -0
- package/lib/browser/{chunk-ZXAL3FMU.js → chunk-2MCNQOY3.js} +56 -51
- package/lib/browser/chunk-2MCNQOY3.js.map +1 -0
- package/lib/browser/chunk-57RIRQUY.js +218 -0
- package/lib/browser/chunk-57RIRQUY.js.map +1 -0
- package/lib/browser/chunk-FW45TRCB.js +178 -0
- package/lib/browser/chunk-FW45TRCB.js.map +1 -0
- package/lib/browser/{chunk-TIPR373R.js → chunk-JQ2S7G56.js} +19 -3
- package/lib/browser/chunk-JQ2S7G56.js.map +1 -0
- package/lib/browser/{chunk-3RXCRGL2.mjs → chunk-LIKZF2VU.mjs} +102 -1
- package/lib/browser/chunk-LIKZF2VU.mjs.map +1 -0
- package/lib/browser/{chunk-F2NPA2FP.js → chunk-MNT2FUCH.js} +61 -56
- package/lib/browser/chunk-MNT2FUCH.js.map +1 -0
- package/lib/browser/chunk-VOUOVDAW.mjs +178 -0
- package/lib/browser/chunk-VOUOVDAW.mjs.map +1 -0
- package/lib/browser/{chunk-TX5GBTFY.mjs → chunk-VYSDLBSS.mjs} +13 -1
- package/lib/browser/chunk-VYSDLBSS.mjs.map +1 -0
- package/lib/browser/{chunk-ZDGZFWQH.mjs → chunk-WADP6VHN.mjs} +49 -44
- package/lib/browser/chunk-WADP6VHN.mjs.map +1 -0
- package/lib/browser/{chunk-MDMPOBGY.mjs → chunk-WOWPV4GR.mjs} +52 -47
- package/lib/browser/chunk-WOWPV4GR.mjs.map +1 -0
- package/lib/browser/{chunk-QED3Q6Z2.mjs → chunk-Z5TSB3T6.mjs} +17 -1
- package/lib/browser/{chunk-QED3Q6Z2.mjs.map → chunk-Z5TSB3T6.mjs.map} +1 -1
- package/lib/browser/{glossary-7152281e.d.ts → glossary-f7ee1c9d.d.ts} +22 -17
- package/lib/browser/index.d.ts +1 -2
- package/lib/browser/index.js +6 -4
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/index.mjs +4 -2
- package/lib/browser/index.mjs.map +1 -1
- package/lib/browser/interceptors/WebSocket/index.js +9 -7
- package/lib/browser/interceptors/WebSocket/index.js.map +1 -1
- package/lib/browser/interceptors/WebSocket/index.mjs +6 -4
- package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -1
- package/lib/browser/interceptors/XMLHttpRequest/index.d.ts +1 -2
- package/lib/browser/interceptors/XMLHttpRequest/index.js +6 -6
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs +5 -5
- package/lib/browser/interceptors/fetch/index.d.ts +1 -2
- package/lib/browser/interceptors/fetch/index.js +6 -6
- package/lib/browser/interceptors/fetch/index.mjs +5 -5
- package/lib/browser/presets/browser.d.ts +1 -2
- package/lib/browser/presets/browser.js +8 -8
- package/lib/browser/presets/browser.mjs +6 -6
- package/lib/node/{BatchInterceptor-5b72232f.d.ts → BatchInterceptor-cb9a2eee.d.ts} +1 -1
- package/lib/node/{Interceptor-bc5a9d8e.d.ts → Interceptor-dc0a39b5.d.ts} +22 -16
- package/lib/node/RemoteHttpInterceptor.d.ts +2 -3
- package/lib/node/RemoteHttpInterceptor.js +31 -27
- package/lib/node/RemoteHttpInterceptor.js.map +1 -1
- package/lib/node/RemoteHttpInterceptor.mjs +28 -24
- package/lib/node/RemoteHttpInterceptor.mjs.map +1 -1
- package/lib/node/{chunk-EKNRB5ZS.mjs → chunk-5UGIB6OX.mjs} +40 -29
- package/lib/node/chunk-5UGIB6OX.mjs.map +1 -0
- package/lib/node/{chunk-4NEYTVWD.mjs → chunk-5V3SIIW2.mjs} +48 -43
- package/lib/node/chunk-5V3SIIW2.mjs.map +1 -0
- package/lib/node/{chunk-VV2LUF5K.js → chunk-6B3ZQOO2.js} +51 -46
- package/lib/node/chunk-6B3ZQOO2.js.map +1 -0
- package/lib/node/chunk-7Q53NNPV.js +189 -0
- package/lib/node/chunk-7Q53NNPV.js.map +1 -0
- package/lib/node/{chunk-A7U44ARP.js → chunk-DOWWQYXZ.js} +104 -3
- package/lib/node/chunk-DOWWQYXZ.js.map +1 -0
- package/lib/node/{chunk-Z5LWCBZS.js → chunk-FRZQJNBO.js} +56 -51
- package/lib/node/chunk-FRZQJNBO.js.map +1 -0
- package/lib/node/{chunk-TJDMZZXE.mjs → chunk-GKN5RBVR.mjs} +2 -2
- package/lib/node/{chunk-R6JVCM7X.js → chunk-J5MULIHT.js} +3 -3
- package/lib/node/{chunk-IHJSPMYM.mjs → chunk-JXGB54LE.mjs} +102 -1
- package/lib/node/chunk-JXGB54LE.mjs.map +1 -0
- package/lib/node/{chunk-3CNGDJFB.mjs → chunk-OFW5L5ET.mjs} +50 -45
- package/lib/node/chunk-OFW5L5ET.mjs.map +1 -0
- package/lib/node/{chunk-A7Q4RTDJ.mjs → chunk-R6T7CL5E.mjs} +55 -115
- package/lib/node/chunk-R6T7CL5E.mjs.map +1 -0
- package/lib/node/{chunk-RC2XPCC4.mjs → chunk-SQ6RHTJR.mjs} +2 -2
- package/lib/node/chunk-SRMAQGPM.js +30 -0
- package/lib/node/chunk-SRMAQGPM.js.map +1 -0
- package/lib/node/{chunk-4YBV77DG.js → chunk-T3TW4P64.js} +3 -3
- package/lib/node/{chunk-N4ZZFE24.js → chunk-VYO5XDY2.js} +56 -45
- package/lib/node/chunk-VYO5XDY2.js.map +1 -0
- package/lib/node/chunk-YWNGXXUQ.mjs +30 -0
- package/lib/node/{chunk-3GJB4JDF.mjs.map → chunk-YWNGXXUQ.mjs.map} +1 -1
- package/lib/node/index.d.ts +2 -3
- package/lib/node/index.js +6 -4
- package/lib/node/index.js.map +1 -1
- package/lib/node/index.mjs +5 -3
- package/lib/node/index.mjs.map +1 -1
- package/lib/node/interceptors/ClientRequest/index.d.ts +1 -2
- package/lib/node/interceptors/ClientRequest/index.js +6 -6
- package/lib/node/interceptors/ClientRequest/index.mjs +5 -5
- package/lib/node/interceptors/XMLHttpRequest/index.d.ts +1 -2
- package/lib/node/interceptors/XMLHttpRequest/index.js +5 -5
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +4 -4
- package/lib/node/interceptors/fetch/index.d.ts +1 -2
- package/lib/node/interceptors/fetch/index.js +5 -5
- package/lib/node/interceptors/fetch/index.mjs +4 -4
- package/lib/node/presets/node.d.ts +1 -2
- package/lib/node/presets/node.js +10 -10
- package/lib/node/presets/node.mjs +7 -7
- package/lib/node/utils/node/index.js +3 -3
- package/lib/node/utils/node/index.mjs +2 -2
- package/package.json +2 -1
- 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 +24 -3
- package/src/interceptors/ClientRequest/index.ts +14 -18
- package/src/interceptors/WebSocket/index.ts +6 -2
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +45 -35
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +24 -21
- package/src/interceptors/fetch/index.ts +61 -50
- package/src/utils/handleRequest.ts +65 -95
- package/lib/browser/chunk-3RXCRGL2.mjs.map +0 -1
- package/lib/browser/chunk-F2NPA2FP.js.map +0 -1
- package/lib/browser/chunk-MDMPOBGY.mjs.map +0 -1
- package/lib/browser/chunk-MMKGBEJO.mjs +0 -246
- package/lib/browser/chunk-MMKGBEJO.mjs.map +0 -1
- package/lib/browser/chunk-PFGO5BSM.js.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.map +0 -1
- package/lib/browser/chunk-TX5GBTFY.mjs.map +0 -1
- package/lib/browser/chunk-XX6WKANU.js +0 -246
- package/lib/browser/chunk-XX6WKANU.js.map +0 -1
- package/lib/browser/chunk-ZDGZFWQH.mjs.map +0 -1
- package/lib/browser/chunk-ZXAL3FMU.js.map +0 -1
- package/lib/node/chunk-3CNGDJFB.mjs.map +0 -1
- package/lib/node/chunk-3GJB4JDF.mjs +0 -14
- package/lib/node/chunk-4NEYTVWD.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-A7Q4RTDJ.mjs.map +0 -1
- package/lib/node/chunk-A7U44ARP.js.map +0 -1
- package/lib/node/chunk-EKNRB5ZS.mjs.map +0 -1
- package/lib/node/chunk-IHJSPMYM.mjs.map +0 -1
- package/lib/node/chunk-N4ZZFE24.js.map +0 -1
- package/lib/node/chunk-SMXZPJEA.js +0 -14
- package/lib/node/chunk-SMXZPJEA.js.map +0 -1
- package/lib/node/chunk-VV2LUF5K.js.map +0 -1
- package/lib/node/chunk-Z5LWCBZS.js.map +0 -1
- package/src/utils/RequestController.ts +0 -21
- /package/lib/node/{chunk-TJDMZZXE.mjs.map → chunk-GKN5RBVR.mjs.map} +0 -0
- /package/lib/node/{chunk-R6JVCM7X.js.map → chunk-J5MULIHT.js.map} +0 -0
- /package/lib/node/{chunk-RC2XPCC4.mjs.map → chunk-SQ6RHTJR.mjs.map} +0 -0
- /package/lib/node/{chunk-4YBV77DG.js.map → chunk-T3TW4P64.js.map} +0 -0
|
@@ -153,30 +153,26 @@ export class ClientRequestInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
|
153
153
|
request,
|
|
154
154
|
socket,
|
|
155
155
|
}) => {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const isRequestHandled = await handleRequest({
|
|
160
|
-
request,
|
|
161
|
-
requestId,
|
|
162
|
-
controller,
|
|
163
|
-
emitter: this.emitter,
|
|
164
|
-
onResponse: (response) => {
|
|
165
|
-
socket.respondWith(response)
|
|
156
|
+
const controller = new RequestController(request, {
|
|
157
|
+
passthrough() {
|
|
158
|
+
socket.passthrough()
|
|
166
159
|
},
|
|
167
|
-
|
|
168
|
-
socket.respondWith(response)
|
|
160
|
+
async respondWith(response) {
|
|
161
|
+
await socket.respondWith(response)
|
|
169
162
|
},
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
socket.errorWith(
|
|
163
|
+
errorWith(reason) {
|
|
164
|
+
if (reason instanceof Error) {
|
|
165
|
+
socket.errorWith(reason)
|
|
173
166
|
}
|
|
174
167
|
},
|
|
175
168
|
})
|
|
176
169
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
170
|
+
await handleRequest({
|
|
171
|
+
request,
|
|
172
|
+
requestId: Reflect.get(request, kRequestId),
|
|
173
|
+
controller,
|
|
174
|
+
emitter: this.emitter,
|
|
175
|
+
})
|
|
180
176
|
}
|
|
181
177
|
|
|
182
178
|
public onResponse: MockHttpSocketResponseCallback = async ({
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from './WebSocketOverride'
|
|
18
18
|
import { bindEvent } from './utils/bindEvent'
|
|
19
19
|
import { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'
|
|
20
|
+
import { emitAsync } from '../../utils/emitAsync'
|
|
20
21
|
|
|
21
22
|
export { type WebSocketData, WebSocketTransport } from './WebSocketTransport'
|
|
22
23
|
export {
|
|
@@ -102,7 +103,7 @@ export class WebSocketInterceptor extends Interceptor<WebSocketEventMap> {
|
|
|
102
103
|
// Emit the "connection" event to the interceptor on the next tick
|
|
103
104
|
// so the client can modify WebSocket options, like "binaryType"
|
|
104
105
|
// while the connection is already pending.
|
|
105
|
-
queueMicrotask(() => {
|
|
106
|
+
queueMicrotask(async () => {
|
|
106
107
|
try {
|
|
107
108
|
const server = new WebSocketServerConnection(
|
|
108
109
|
socket,
|
|
@@ -110,10 +111,13 @@ export class WebSocketInterceptor extends Interceptor<WebSocketEventMap> {
|
|
|
110
111
|
createConnection
|
|
111
112
|
)
|
|
112
113
|
|
|
114
|
+
const hasConnectionListeners =
|
|
115
|
+
this.emitter.listenerCount('connection') > 0
|
|
116
|
+
|
|
113
117
|
// The "globalThis.WebSocket" class stands for
|
|
114
118
|
// the client-side connection. Assume it's established
|
|
115
119
|
// as soon as the WebSocket instance is constructed.
|
|
116
|
-
|
|
120
|
+
await emitAsync(this.emitter, 'connection', {
|
|
117
121
|
client: new WebSocketClientConnection(socket, transport),
|
|
118
122
|
server,
|
|
119
123
|
info: {
|
|
@@ -57,7 +57,10 @@ export class XMLHttpRequestController {
|
|
|
57
57
|
Array<Function>
|
|
58
58
|
>
|
|
59
59
|
|
|
60
|
-
constructor(
|
|
60
|
+
constructor(
|
|
61
|
+
readonly initialRequest: XMLHttpRequest,
|
|
62
|
+
public logger: Logger
|
|
63
|
+
) {
|
|
61
64
|
this[kIsRequestHandled] = false
|
|
62
65
|
|
|
63
66
|
this.events = new Map()
|
|
@@ -111,7 +114,7 @@ export class XMLHttpRequestController {
|
|
|
111
114
|
case 'addEventListener': {
|
|
112
115
|
const [eventName, listener] = args as [
|
|
113
116
|
keyof XMLHttpRequestEventTargetEventMap,
|
|
114
|
-
Function
|
|
117
|
+
Function,
|
|
115
118
|
]
|
|
116
119
|
|
|
117
120
|
this.registerEvent(eventName, listener)
|
|
@@ -131,7 +134,7 @@ export class XMLHttpRequestController {
|
|
|
131
134
|
|
|
132
135
|
case 'send': {
|
|
133
136
|
const [body] = args as [
|
|
134
|
-
body?: XMLHttpRequestBodyInit | Document | null
|
|
137
|
+
body?: XMLHttpRequestBodyInit | Document | null,
|
|
135
138
|
]
|
|
136
139
|
|
|
137
140
|
this.request.addEventListener('load', () => {
|
|
@@ -166,38 +169,44 @@ export class XMLHttpRequestController {
|
|
|
166
169
|
const fetchRequest = this.toFetchApiRequest(requestBody)
|
|
167
170
|
this[kFetchRequest] = fetchRequest.clone()
|
|
168
171
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
* to process it once again.
|
|
187
|
-
*
|
|
188
|
-
* For instance, XMLHttpRequest is often implemented via "http.ClientRequest"
|
|
189
|
-
* and we don't want for both XHR and ClientRequest interceptors to
|
|
190
|
-
* handle the same request at the same time (e.g. emit the "response" event twice).
|
|
191
|
-
*/
|
|
192
|
-
if (IS_NODE) {
|
|
193
|
-
this.request.setRequestHeader(
|
|
194
|
-
INTERNAL_REQUEST_ID_HEADER_NAME,
|
|
195
|
-
this.requestId!
|
|
172
|
+
/**
|
|
173
|
+
* @note Start request handling on the next tick so that the user
|
|
174
|
+
* could add event listeners for "loadend" before the interceptor fires it.
|
|
175
|
+
*/
|
|
176
|
+
queueMicrotask(() => {
|
|
177
|
+
const onceRequestSettled =
|
|
178
|
+
this.onRequest?.call(this, {
|
|
179
|
+
request: fetchRequest,
|
|
180
|
+
requestId: this.requestId!,
|
|
181
|
+
}) || Promise.resolve()
|
|
182
|
+
|
|
183
|
+
onceRequestSettled.finally(() => {
|
|
184
|
+
// If the consumer didn't handle the request (called `.respondWith()`) perform it as-is.
|
|
185
|
+
if (!this[kIsRequestHandled]) {
|
|
186
|
+
this.logger.info(
|
|
187
|
+
'request callback settled but request has not been handled (readystate %d), performing as-is...',
|
|
188
|
+
this.request.readyState
|
|
196
189
|
)
|
|
197
|
-
}
|
|
198
190
|
|
|
199
|
-
|
|
200
|
-
|
|
191
|
+
/**
|
|
192
|
+
* @note Set the intercepted request ID on the original request in Node.js
|
|
193
|
+
* so that if it triggers any other interceptors, they don't attempt
|
|
194
|
+
* to process it once again.
|
|
195
|
+
*
|
|
196
|
+
* For instance, XMLHttpRequest is often implemented via "http.ClientRequest"
|
|
197
|
+
* and we don't want for both XHR and ClientRequest interceptors to
|
|
198
|
+
* handle the same request at the same time (e.g. emit the "response" event twice).
|
|
199
|
+
*/
|
|
200
|
+
if (IS_NODE) {
|
|
201
|
+
this.request.setRequestHeader(
|
|
202
|
+
INTERNAL_REQUEST_ID_HEADER_NAME,
|
|
203
|
+
this.requestId!
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return invoke()
|
|
208
|
+
}
|
|
209
|
+
})
|
|
201
210
|
})
|
|
202
211
|
|
|
203
212
|
break
|
|
@@ -241,7 +250,7 @@ export class XMLHttpRequestController {
|
|
|
241
250
|
case 'addEventListener': {
|
|
242
251
|
const [eventName, listener] = args as [
|
|
243
252
|
keyof XMLHttpRequestEventTargetEventMap,
|
|
244
|
-
Function
|
|
253
|
+
Function,
|
|
245
254
|
]
|
|
246
255
|
this.registerUploadEvent(eventName, listener)
|
|
247
256
|
this.logger.info('upload.addEventListener', eventName, listener)
|
|
@@ -312,6 +321,7 @@ export class XMLHttpRequestController {
|
|
|
312
321
|
loaded: totalRequestBodyLength,
|
|
313
322
|
total: totalRequestBodyLength,
|
|
314
323
|
})
|
|
324
|
+
|
|
315
325
|
this.trigger('loadend', this.request.upload, {
|
|
316
326
|
loaded: totalRequestBodyLength,
|
|
317
327
|
total: totalRequestBodyLength,
|
|
@@ -614,7 +624,7 @@ export class XMLHttpRequestController {
|
|
|
614
624
|
private trigger<
|
|
615
625
|
EventName extends keyof (XMLHttpRequestEventTargetEventMap & {
|
|
616
626
|
readystatechange: ProgressEvent<XMLHttpRequestEventTarget>
|
|
617
|
-
})
|
|
627
|
+
}),
|
|
618
628
|
>(
|
|
619
629
|
eventName: EventName,
|
|
620
630
|
target: XMLHttpRequest | XMLHttpRequestUpload,
|
|
@@ -3,6 +3,7 @@ import { XMLHttpRequestEmitter } from '.'
|
|
|
3
3
|
import { RequestController } from '../../RequestController'
|
|
4
4
|
import { XMLHttpRequestController } from './XMLHttpRequestController'
|
|
5
5
|
import { handleRequest } from '../../utils/handleRequest'
|
|
6
|
+
import { isResponseError } from '../../utils/responseUtils'
|
|
6
7
|
|
|
7
8
|
export interface XMLHttpRequestProxyOptions {
|
|
8
9
|
emitter: XMLHttpRequestEmitter
|
|
@@ -52,7 +53,28 @@ export function createXMLHttpRequestProxy({
|
|
|
52
53
|
)
|
|
53
54
|
|
|
54
55
|
xhrRequestController.onRequest = async function ({ request, requestId }) {
|
|
55
|
-
const controller = new RequestController(request
|
|
56
|
+
const controller = new RequestController(request, {
|
|
57
|
+
passthrough: () => {
|
|
58
|
+
this.logger.info(
|
|
59
|
+
'no mocked response received, performing request as-is...'
|
|
60
|
+
)
|
|
61
|
+
},
|
|
62
|
+
respondWith: async (response) => {
|
|
63
|
+
if (isResponseError(response)) {
|
|
64
|
+
this.errorWith(new TypeError('Network error'))
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await this.respondWith(response)
|
|
69
|
+
},
|
|
70
|
+
errorWith: (reason) => {
|
|
71
|
+
this.logger.info('request errored!', { error: reason })
|
|
72
|
+
|
|
73
|
+
if (reason instanceof Error) {
|
|
74
|
+
this.errorWith(reason)
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
})
|
|
56
78
|
|
|
57
79
|
this.logger.info('awaiting mocked response...')
|
|
58
80
|
|
|
@@ -61,31 +83,12 @@ export function createXMLHttpRequestProxy({
|
|
|
61
83
|
emitter.listenerCount('request')
|
|
62
84
|
)
|
|
63
85
|
|
|
64
|
-
|
|
86
|
+
await handleRequest({
|
|
65
87
|
request,
|
|
66
88
|
requestId,
|
|
67
89
|
controller,
|
|
68
90
|
emitter,
|
|
69
|
-
onResponse: async (response) => {
|
|
70
|
-
await this.respondWith(response)
|
|
71
|
-
},
|
|
72
|
-
onRequestError: () => {
|
|
73
|
-
this.errorWith(new TypeError('Network error'))
|
|
74
|
-
},
|
|
75
|
-
onError: (error) => {
|
|
76
|
-
this.logger.info('request errored!', { error })
|
|
77
|
-
|
|
78
|
-
if (error instanceof Error) {
|
|
79
|
-
this.errorWith(error)
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
91
|
})
|
|
83
|
-
|
|
84
|
-
if (!isRequestHandled) {
|
|
85
|
-
this.logger.info(
|
|
86
|
-
'no mocked response received, performing request as-is...'
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
xhrRequestController.onResponse = async function ({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { invariant } from 'outvariant'
|
|
2
|
+
import { until } from '@open-draft/until'
|
|
2
3
|
import { DeferredPromise } from '@open-draft/deferred-promise'
|
|
3
4
|
import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'
|
|
4
5
|
import { Interceptor } from '../../Interceptor'
|
|
@@ -13,6 +14,7 @@ import { decompressResponse } from './utils/decompression'
|
|
|
13
14
|
import { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'
|
|
14
15
|
import { FetchResponse } from '../../utils/fetchUtils'
|
|
15
16
|
import { setRawRequest } from '../../getRawRequest'
|
|
17
|
+
import { isResponseError } from '../../utils/responseUtils'
|
|
16
18
|
|
|
17
19
|
export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
18
20
|
static symbol = Symbol('fetch')
|
|
@@ -59,22 +61,54 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
const responsePromise = new DeferredPromise<Response>()
|
|
62
|
-
const controller = new RequestController(request)
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
const controller = new RequestController(request, {
|
|
66
|
+
passthrough: async () => {
|
|
67
|
+
this.logger.info('request has not been handled, passthrough...')
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
/**
|
|
70
|
+
* @note Clone the request instance right before performing it.
|
|
71
|
+
* This preserves any modifications made to the intercepted request
|
|
72
|
+
* in the "request" listener. This also allows the user to read the
|
|
73
|
+
* request body in the "response" listener (otherwise "unusable").
|
|
74
|
+
*/
|
|
75
|
+
const requestCloneForResponseEvent = request.clone()
|
|
76
|
+
|
|
77
|
+
// Perform the intercepted request as-is.
|
|
78
|
+
const { error: responseError, data: originalResponse } = await until(
|
|
79
|
+
() => pureFetch(request)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if (responseError) {
|
|
83
|
+
return responsePromise.reject(responseError)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.logger.info('original fetch performed', originalResponse)
|
|
87
|
+
|
|
88
|
+
if (this.emitter.listenerCount('response') > 0) {
|
|
89
|
+
this.logger.info('emitting the "response" event...')
|
|
90
|
+
|
|
91
|
+
const responseClone = originalResponse.clone()
|
|
92
|
+
await emitAsync(this.emitter, 'response', {
|
|
93
|
+
response: responseClone,
|
|
94
|
+
isMockedResponse: false,
|
|
95
|
+
request: requestCloneForResponseEvent,
|
|
96
|
+
requestId,
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Resolve the response promise with the original response
|
|
101
|
+
// since the `fetch()` return this internal promise.
|
|
102
|
+
responsePromise.resolve(originalResponse)
|
|
103
|
+
},
|
|
104
|
+
respondWith: async (rawResponse) => {
|
|
105
|
+
// Handle mocked `Response.error()` (i.e. request errors).
|
|
106
|
+
if (isResponseError(rawResponse)) {
|
|
107
|
+
this.logger.info('request has errored!', { response: rawResponse })
|
|
108
|
+
responsePromise.reject(createNetworkError(rawResponse))
|
|
109
|
+
return
|
|
110
|
+
}
|
|
71
111
|
|
|
72
|
-
const isRequestHandled = await handleRequest({
|
|
73
|
-
request,
|
|
74
|
-
requestId,
|
|
75
|
-
emitter: this.emitter,
|
|
76
|
-
controller,
|
|
77
|
-
onResponse: async (rawResponse) => {
|
|
78
112
|
this.logger.info('received mocked response!', {
|
|
79
113
|
rawResponse,
|
|
80
114
|
})
|
|
@@ -134,51 +168,28 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
|
134
168
|
|
|
135
169
|
responsePromise.resolve(response)
|
|
136
170
|
},
|
|
137
|
-
|
|
138
|
-
this.logger.info('request has
|
|
139
|
-
responsePromise.reject(
|
|
140
|
-
},
|
|
141
|
-
onError: (error) => {
|
|
142
|
-
this.logger.info('request has been aborted!', { error })
|
|
143
|
-
responsePromise.reject(error)
|
|
171
|
+
errorWith: (reason) => {
|
|
172
|
+
this.logger.info('request has been aborted!', { reason })
|
|
173
|
+
responsePromise.reject(reason)
|
|
144
174
|
},
|
|
145
175
|
})
|
|
146
176
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return responsePromise
|
|
150
|
-
}
|
|
177
|
+
this.logger.info('[%s] %s', request.method, request.url)
|
|
178
|
+
this.logger.info('awaiting for the mocked response...')
|
|
151
179
|
|
|
152
180
|
this.logger.info(
|
|
153
|
-
'
|
|
181
|
+
'emitting the "request" event for %s listener(s)...',
|
|
182
|
+
this.emitter.listenerCount('request')
|
|
154
183
|
)
|
|
155
184
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*/
|
|
162
|
-
const requestCloneForResponseEvent = request.clone()
|
|
163
|
-
|
|
164
|
-
return pureFetch(request).then(async (response) => {
|
|
165
|
-
this.logger.info('original fetch performed', response)
|
|
166
|
-
|
|
167
|
-
if (this.emitter.listenerCount('response') > 0) {
|
|
168
|
-
this.logger.info('emitting the "response" event...')
|
|
169
|
-
|
|
170
|
-
const responseClone = response.clone()
|
|
171
|
-
|
|
172
|
-
await emitAsync(this.emitter, 'response', {
|
|
173
|
-
response: responseClone,
|
|
174
|
-
isMockedResponse: false,
|
|
175
|
-
request: requestCloneForResponseEvent,
|
|
176
|
-
requestId,
|
|
177
|
-
})
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return response
|
|
185
|
+
await handleRequest({
|
|
186
|
+
request,
|
|
187
|
+
requestId,
|
|
188
|
+
emitter: this.emitter,
|
|
189
|
+
controller,
|
|
181
190
|
})
|
|
191
|
+
|
|
192
|
+
return responsePromise
|
|
182
193
|
}
|
|
183
194
|
|
|
184
195
|
Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {
|