@mswjs/interceptors 0.22.3 → 0.22.4

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.
@@ -121,12 +121,28 @@ function optionsToProxyHandler(options) {
121
121
  return constructorCall.call(newTarget, args, next);
122
122
  };
123
123
  }
124
- if (typeof setProperty !== "undefined") {
125
- handler.set = function(target, propertyName, nextValue, receiver) {
126
- const next = () => Reflect.set(target, propertyName, nextValue, receiver);
127
- return setProperty.call(target, [propertyName, nextValue], next);
124
+ handler.set = function(target, propertyName, nextValue, receiver) {
125
+ const next = () => {
126
+ const ownDescriptors = Reflect.getOwnPropertyDescriptor(
127
+ target,
128
+ propertyName
129
+ );
130
+ if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") {
131
+ ownDescriptors.set.apply(target, [nextValue]);
132
+ return true;
133
+ }
134
+ return Reflect.defineProperty(target, propertyName, {
135
+ writable: true,
136
+ enumerable: true,
137
+ configurable: true,
138
+ value: nextValue
139
+ });
128
140
  };
129
- }
141
+ if (typeof setProperty !== "undefined") {
142
+ return setProperty.call(target, [propertyName, nextValue], next);
143
+ }
144
+ return next();
145
+ };
130
146
  handler.get = function(target, propertyName, receiver) {
131
147
  const next = () => target[propertyName];
132
148
  const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next();
@@ -191,11 +207,25 @@ var XMLHttpRequestController = class {
191
207
  this.responseBuffer = new Uint8Array();
192
208
  this.request = createProxy(initialRequest, {
193
209
  setProperty: ([propertyName, nextValue], invoke) => {
194
- if (propertyName === "withCredentials") {
195
- define(this.request, "withCredentials", nextValue);
196
- return true;
210
+ switch (propertyName) {
211
+ case "onabort":
212
+ case "onerror":
213
+ case "onload":
214
+ case "onloadend":
215
+ case "onloadstart":
216
+ case "onprogress":
217
+ case "ontimeout":
218
+ case "onreadystatechange": {
219
+ const eventName = propertyName.slice(
220
+ 2
221
+ );
222
+ this.request.addEventListener(eventName, nextValue);
223
+ return invoke();
224
+ }
225
+ default: {
226
+ return invoke();
227
+ }
197
228
  }
198
- return invoke();
199
229
  },
200
230
  methodCall: ([methodName, args], invoke) => {
201
231
  var _a;
@@ -259,21 +289,6 @@ var XMLHttpRequestController = class {
259
289
  });
260
290
  break;
261
291
  }
262
- case "onabort":
263
- case "onerror":
264
- case "onload":
265
- case "onloadend":
266
- case "onloadstart":
267
- case "onprogress":
268
- case "ontimeout":
269
- case "onreadystatechange": {
270
- const [listener] = args;
271
- this.registerEvent(
272
- methodName,
273
- listener
274
- );
275
- return invoke();
276
- }
277
292
  default: {
278
293
  return invoke();
279
294
  }
@@ -326,14 +341,17 @@ var XMLHttpRequestController = class {
326
341
  Object.defineProperties(this.request, {
327
342
  response: {
328
343
  enumerable: true,
344
+ configurable: false,
329
345
  get: () => this.response
330
346
  },
331
347
  responseText: {
332
348
  enumerable: true,
349
+ configurable: false,
333
350
  get: () => this.responseText
334
351
  },
335
352
  responseXML: {
336
353
  enumerable: true,
354
+ configurable: false,
337
355
  get: () => this.responseXML
338
356
  }
339
357
  });
@@ -547,9 +565,19 @@ function createXMLHttpRequestProxy({
547
565
  log
548
566
  }) {
549
567
  const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {
550
- construct(target, args) {
568
+ construct(target, args, newTarget) {
551
569
  log("constructed new XMLHttpRequest");
552
- const originalRequest = Reflect.construct(target, args);
570
+ const originalRequest = Reflect.construct(target, args, newTarget);
571
+ const prototypeDescriptors = Object.getOwnPropertyDescriptors(
572
+ target.prototype
573
+ );
574
+ for (const propertyName in prototypeDescriptors) {
575
+ Reflect.defineProperty(
576
+ originalRequest,
577
+ propertyName,
578
+ prototypeDescriptors[propertyName]
579
+ );
580
+ }
553
581
  const requestController = new XMLHttpRequestController(
554
582
  originalRequest,
555
583
  log
@@ -121,12 +121,28 @@ function optionsToProxyHandler(options) {
121
121
  return constructorCall.call(newTarget, args, next);
122
122
  };
123
123
  }
124
- if (typeof setProperty !== "undefined") {
125
- handler.set = function(target, propertyName, nextValue, receiver) {
126
- const next = () => Reflect.set(target, propertyName, nextValue, receiver);
127
- return setProperty.call(target, [propertyName, nextValue], next);
124
+ handler.set = function(target, propertyName, nextValue, receiver) {
125
+ const next = () => {
126
+ const ownDescriptors = Reflect.getOwnPropertyDescriptor(
127
+ target,
128
+ propertyName
129
+ );
130
+ if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") {
131
+ ownDescriptors.set.apply(target, [nextValue]);
132
+ return true;
133
+ }
134
+ return Reflect.defineProperty(target, propertyName, {
135
+ writable: true,
136
+ enumerable: true,
137
+ configurable: true,
138
+ value: nextValue
139
+ });
128
140
  };
129
- }
141
+ if (typeof setProperty !== "undefined") {
142
+ return setProperty.call(target, [propertyName, nextValue], next);
143
+ }
144
+ return next();
145
+ };
130
146
  handler.get = function(target, propertyName, receiver) {
131
147
  const next = () => target[propertyName];
132
148
  const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next();
@@ -191,11 +207,25 @@ var XMLHttpRequestController = class {
191
207
  this.responseBuffer = new Uint8Array();
192
208
  this.request = createProxy(initialRequest, {
193
209
  setProperty: ([propertyName, nextValue], invoke) => {
194
- if (propertyName === "withCredentials") {
195
- define(this.request, "withCredentials", nextValue);
196
- return true;
210
+ switch (propertyName) {
211
+ case "onabort":
212
+ case "onerror":
213
+ case "onload":
214
+ case "onloadend":
215
+ case "onloadstart":
216
+ case "onprogress":
217
+ case "ontimeout":
218
+ case "onreadystatechange": {
219
+ const eventName = propertyName.slice(
220
+ 2
221
+ );
222
+ this.request.addEventListener(eventName, nextValue);
223
+ return invoke();
224
+ }
225
+ default: {
226
+ return invoke();
227
+ }
197
228
  }
198
- return invoke();
199
229
  },
200
230
  methodCall: ([methodName, args], invoke) => {
201
231
  var _a;
@@ -259,21 +289,6 @@ var XMLHttpRequestController = class {
259
289
  });
260
290
  break;
261
291
  }
262
- case "onabort":
263
- case "onerror":
264
- case "onload":
265
- case "onloadend":
266
- case "onloadstart":
267
- case "onprogress":
268
- case "ontimeout":
269
- case "onreadystatechange": {
270
- const [listener] = args;
271
- this.registerEvent(
272
- methodName,
273
- listener
274
- );
275
- return invoke();
276
- }
277
292
  default: {
278
293
  return invoke();
279
294
  }
@@ -326,14 +341,17 @@ var XMLHttpRequestController = class {
326
341
  Object.defineProperties(this.request, {
327
342
  response: {
328
343
  enumerable: true,
344
+ configurable: false,
329
345
  get: () => this.response
330
346
  },
331
347
  responseText: {
332
348
  enumerable: true,
349
+ configurable: false,
333
350
  get: () => this.responseText
334
351
  },
335
352
  responseXML: {
336
353
  enumerable: true,
354
+ configurable: false,
337
355
  get: () => this.responseXML
338
356
  }
339
357
  });
@@ -547,9 +565,19 @@ function createXMLHttpRequestProxy({
547
565
  log
548
566
  }) {
549
567
  const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {
550
- construct(target, args) {
568
+ construct(target, args, newTarget) {
551
569
  log("constructed new XMLHttpRequest");
552
- const originalRequest = Reflect.construct(target, args);
570
+ const originalRequest = Reflect.construct(target, args, newTarget);
571
+ const prototypeDescriptors = Object.getOwnPropertyDescriptors(
572
+ target.prototype
573
+ );
574
+ for (const propertyName in prototypeDescriptors) {
575
+ Reflect.defineProperty(
576
+ originalRequest,
577
+ propertyName,
578
+ prototypeDescriptors[propertyName]
579
+ );
580
+ }
553
581
  const requestController = new XMLHttpRequestController(
554
582
  originalRequest,
555
583
  log
@@ -9,6 +9,7 @@ var _chunkQWL3EOEYjs = require('../../chunk-QWL3EOEY.js');
9
9
 
10
10
  // src/interceptors/fetch/index.ts
11
11
  var _outvariant = require('outvariant');
12
+ var _until = require('@open-draft/until');
12
13
  var _FetchInterceptor = class extends _chunkQWL3EOEYjs.Interceptor {
13
14
  constructor() {
14
15
  super(_FetchInterceptor.symbol);
@@ -33,15 +34,25 @@ var _FetchInterceptor = class extends _chunkQWL3EOEYjs.Interceptor {
33
34
  );
34
35
  this.emitter.emit("request", interactiveRequest, requestId);
35
36
  this.log("awaiting for the mocked response...");
36
- await this.emitter.untilIdle(
37
- "request",
38
- ({ args: [, pendingRequestId] }) => {
39
- return pendingRequestId === requestId;
40
- }
41
- );
42
- this.log("all request listeners have been resolved!");
43
- const [mockedResponse] = await interactiveRequest.respondWith.invoked();
44
- this.log("event.respondWith called with:", mockedResponse);
37
+ const [middlewareException, mockedResponse] = await _until.until.call(void 0, async () => {
38
+ await this.emitter.untilIdle(
39
+ "request",
40
+ ({ args: [, pendingRequestId] }) => {
41
+ return pendingRequestId === requestId;
42
+ }
43
+ );
44
+ this.log("all request listeners have been resolved!");
45
+ const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
46
+ this.log("event.respondWith called with:", mockedResponse2);
47
+ return mockedResponse2;
48
+ });
49
+ if (middlewareException) {
50
+ console.error(`${request.method} ${request.url} net::ERR_FAILED`);
51
+ const error = Object.assign(new TypeError("Failed to fetch"), {
52
+ cause: middlewareException
53
+ });
54
+ return Promise.reject(error);
55
+ }
45
56
  if (mockedResponse) {
46
57
  this.log("received mocked response:", mockedResponse);
47
58
  const responseCloine = mockedResponse.clone();
@@ -9,6 +9,7 @@ import {
9
9
 
10
10
  // src/interceptors/fetch/index.ts
11
11
  import { invariant } from "outvariant";
12
+ import { until } from "@open-draft/until";
12
13
  var _FetchInterceptor = class extends Interceptor {
13
14
  constructor() {
14
15
  super(_FetchInterceptor.symbol);
@@ -33,15 +34,25 @@ var _FetchInterceptor = class extends Interceptor {
33
34
  );
34
35
  this.emitter.emit("request", interactiveRequest, requestId);
35
36
  this.log("awaiting for the mocked response...");
36
- await this.emitter.untilIdle(
37
- "request",
38
- ({ args: [, pendingRequestId] }) => {
39
- return pendingRequestId === requestId;
40
- }
41
- );
42
- this.log("all request listeners have been resolved!");
43
- const [mockedResponse] = await interactiveRequest.respondWith.invoked();
44
- this.log("event.respondWith called with:", mockedResponse);
37
+ const [middlewareException, mockedResponse] = await until(async () => {
38
+ await this.emitter.untilIdle(
39
+ "request",
40
+ ({ args: [, pendingRequestId] }) => {
41
+ return pendingRequestId === requestId;
42
+ }
43
+ );
44
+ this.log("all request listeners have been resolved!");
45
+ const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
46
+ this.log("event.respondWith called with:", mockedResponse2);
47
+ return mockedResponse2;
48
+ });
49
+ if (middlewareException) {
50
+ console.error(`${request.method} ${request.url} net::ERR_FAILED`);
51
+ const error = Object.assign(new TypeError("Failed to fetch"), {
52
+ cause: middlewareException
53
+ });
54
+ return Promise.reject(error);
55
+ }
45
56
  if (mockedResponse) {
46
57
  this.log("received mocked response:", mockedResponse);
47
58
  const responseCloine = mockedResponse.clone();
@@ -6,7 +6,7 @@ var _chunkQ56TMOP5js = require('./chunk-Q56TMOP5.js');
6
6
  var _chunkXLZJAPVSjs = require('./chunk-XLZJAPVS.js');
7
7
 
8
8
 
9
- var _chunkGGD5JOGBjs = require('./chunk-GGD5JOGB.js');
9
+ var _chunkRVLLS44Wjs = require('./chunk-RVLLS44W.js');
10
10
  require('./chunk-SNNL2EXF.js');
11
11
  require('./chunk-VQ4DZOBB.js');
12
12
 
@@ -24,7 +24,7 @@ var RemoteHttpInterceptor = class extends _chunkQ56TMOP5js.BatchInterceptor {
24
24
  name: "remote-interceptor",
25
25
  interceptors: [
26
26
  new (0, _chunkXLZJAPVSjs.ClientRequestInterceptor)(),
27
- new (0, _chunkGGD5JOGBjs.XMLHttpRequestInterceptor)()
27
+ new (0, _chunkRVLLS44Wjs.XMLHttpRequestInterceptor)()
28
28
  ]
29
29
  });
30
30
  }
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-FGPCRIW6.mjs";
7
7
  import {
8
8
  XMLHttpRequestInterceptor
9
- } from "./chunk-CYWTKHFI.mjs";
9
+ } from "./chunk-P7NKDCFD.mjs";
10
10
  import "./chunk-G6ZTHYZQ.mjs";
11
11
  import "./chunk-GFH37L5D.mjs";
12
12
  import {
@@ -123,12 +123,28 @@ function optionsToProxyHandler(options) {
123
123
  return constructorCall.call(newTarget, args, next);
124
124
  };
125
125
  }
126
- if (typeof setProperty !== "undefined") {
127
- handler.set = function(target, propertyName, nextValue, receiver) {
128
- const next = () => Reflect.set(target, propertyName, nextValue, receiver);
129
- return setProperty.call(target, [propertyName, nextValue], next);
126
+ handler.set = function(target, propertyName, nextValue, receiver) {
127
+ const next = () => {
128
+ const ownDescriptors = Reflect.getOwnPropertyDescriptor(
129
+ target,
130
+ propertyName
131
+ );
132
+ if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") {
133
+ ownDescriptors.set.apply(target, [nextValue]);
134
+ return true;
135
+ }
136
+ return Reflect.defineProperty(target, propertyName, {
137
+ writable: true,
138
+ enumerable: true,
139
+ configurable: true,
140
+ value: nextValue
141
+ });
130
142
  };
131
- }
143
+ if (typeof setProperty !== "undefined") {
144
+ return setProperty.call(target, [propertyName, nextValue], next);
145
+ }
146
+ return next();
147
+ };
132
148
  handler.get = function(target, propertyName, receiver) {
133
149
  const next = () => target[propertyName];
134
150
  const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next();
@@ -193,11 +209,25 @@ var XMLHttpRequestController = class {
193
209
  this.responseBuffer = new Uint8Array();
194
210
  this.request = createProxy(initialRequest, {
195
211
  setProperty: ([propertyName, nextValue], invoke) => {
196
- if (propertyName === "withCredentials") {
197
- define(this.request, "withCredentials", nextValue);
198
- return true;
212
+ switch (propertyName) {
213
+ case "onabort":
214
+ case "onerror":
215
+ case "onload":
216
+ case "onloadend":
217
+ case "onloadstart":
218
+ case "onprogress":
219
+ case "ontimeout":
220
+ case "onreadystatechange": {
221
+ const eventName = propertyName.slice(
222
+ 2
223
+ );
224
+ this.request.addEventListener(eventName, nextValue);
225
+ return invoke();
226
+ }
227
+ default: {
228
+ return invoke();
229
+ }
199
230
  }
200
- return invoke();
201
231
  },
202
232
  methodCall: ([methodName, args], invoke) => {
203
233
  var _a;
@@ -261,21 +291,6 @@ var XMLHttpRequestController = class {
261
291
  });
262
292
  break;
263
293
  }
264
- case "onabort":
265
- case "onerror":
266
- case "onload":
267
- case "onloadend":
268
- case "onloadstart":
269
- case "onprogress":
270
- case "ontimeout":
271
- case "onreadystatechange": {
272
- const [listener] = args;
273
- this.registerEvent(
274
- methodName,
275
- listener
276
- );
277
- return invoke();
278
- }
279
294
  default: {
280
295
  return invoke();
281
296
  }
@@ -328,14 +343,17 @@ var XMLHttpRequestController = class {
328
343
  Object.defineProperties(this.request, {
329
344
  response: {
330
345
  enumerable: true,
346
+ configurable: false,
331
347
  get: () => this.response
332
348
  },
333
349
  responseText: {
334
350
  enumerable: true,
351
+ configurable: false,
335
352
  get: () => this.responseText
336
353
  },
337
354
  responseXML: {
338
355
  enumerable: true,
356
+ configurable: false,
339
357
  get: () => this.responseXML
340
358
  }
341
359
  });
@@ -549,9 +567,19 @@ function createXMLHttpRequestProxy({
549
567
  log
550
568
  }) {
551
569
  const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {
552
- construct(target, args) {
570
+ construct(target, args, newTarget) {
553
571
  log("constructed new XMLHttpRequest");
554
- const originalRequest = Reflect.construct(target, args);
572
+ const originalRequest = Reflect.construct(target, args, newTarget);
573
+ const prototypeDescriptors = Object.getOwnPropertyDescriptors(
574
+ target.prototype
575
+ );
576
+ for (const propertyName in prototypeDescriptors) {
577
+ Reflect.defineProperty(
578
+ originalRequest,
579
+ propertyName,
580
+ prototypeDescriptors[propertyName]
581
+ );
582
+ }
555
583
  const requestController = new XMLHttpRequestController(
556
584
  originalRequest,
557
585
  log
@@ -123,12 +123,28 @@ function optionsToProxyHandler(options) {
123
123
  return constructorCall.call(newTarget, args, next);
124
124
  };
125
125
  }
126
- if (typeof setProperty !== "undefined") {
127
- handler.set = function(target, propertyName, nextValue, receiver) {
128
- const next = () => Reflect.set(target, propertyName, nextValue, receiver);
129
- return setProperty.call(target, [propertyName, nextValue], next);
126
+ handler.set = function(target, propertyName, nextValue, receiver) {
127
+ const next = () => {
128
+ const ownDescriptors = Reflect.getOwnPropertyDescriptor(
129
+ target,
130
+ propertyName
131
+ );
132
+ if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") {
133
+ ownDescriptors.set.apply(target, [nextValue]);
134
+ return true;
135
+ }
136
+ return Reflect.defineProperty(target, propertyName, {
137
+ writable: true,
138
+ enumerable: true,
139
+ configurable: true,
140
+ value: nextValue
141
+ });
130
142
  };
131
- }
143
+ if (typeof setProperty !== "undefined") {
144
+ return setProperty.call(target, [propertyName, nextValue], next);
145
+ }
146
+ return next();
147
+ };
132
148
  handler.get = function(target, propertyName, receiver) {
133
149
  const next = () => target[propertyName];
134
150
  const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next();
@@ -193,11 +209,25 @@ var XMLHttpRequestController = class {
193
209
  this.responseBuffer = new Uint8Array();
194
210
  this.request = createProxy(initialRequest, {
195
211
  setProperty: ([propertyName, nextValue], invoke) => {
196
- if (propertyName === "withCredentials") {
197
- define(this.request, "withCredentials", nextValue);
198
- return true;
212
+ switch (propertyName) {
213
+ case "onabort":
214
+ case "onerror":
215
+ case "onload":
216
+ case "onloadend":
217
+ case "onloadstart":
218
+ case "onprogress":
219
+ case "ontimeout":
220
+ case "onreadystatechange": {
221
+ const eventName = propertyName.slice(
222
+ 2
223
+ );
224
+ this.request.addEventListener(eventName, nextValue);
225
+ return invoke();
226
+ }
227
+ default: {
228
+ return invoke();
229
+ }
199
230
  }
200
- return invoke();
201
231
  },
202
232
  methodCall: ([methodName, args], invoke) => {
203
233
  var _a;
@@ -261,21 +291,6 @@ var XMLHttpRequestController = class {
261
291
  });
262
292
  break;
263
293
  }
264
- case "onabort":
265
- case "onerror":
266
- case "onload":
267
- case "onloadend":
268
- case "onloadstart":
269
- case "onprogress":
270
- case "ontimeout":
271
- case "onreadystatechange": {
272
- const [listener] = args;
273
- this.registerEvent(
274
- methodName,
275
- listener
276
- );
277
- return invoke();
278
- }
279
294
  default: {
280
295
  return invoke();
281
296
  }
@@ -328,14 +343,17 @@ var XMLHttpRequestController = class {
328
343
  Object.defineProperties(this.request, {
329
344
  response: {
330
345
  enumerable: true,
346
+ configurable: false,
331
347
  get: () => this.response
332
348
  },
333
349
  responseText: {
334
350
  enumerable: true,
351
+ configurable: false,
335
352
  get: () => this.responseText
336
353
  },
337
354
  responseXML: {
338
355
  enumerable: true,
356
+ configurable: false,
339
357
  get: () => this.responseXML
340
358
  }
341
359
  });
@@ -549,9 +567,19 @@ function createXMLHttpRequestProxy({
549
567
  log
550
568
  }) {
551
569
  const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {
552
- construct(target, args) {
570
+ construct(target, args, newTarget) {
553
571
  log("constructed new XMLHttpRequest");
554
- const originalRequest = Reflect.construct(target, args);
572
+ const originalRequest = Reflect.construct(target, args, newTarget);
573
+ const prototypeDescriptors = Object.getOwnPropertyDescriptors(
574
+ target.prototype
575
+ );
576
+ for (const propertyName in prototypeDescriptors) {
577
+ Reflect.defineProperty(
578
+ originalRequest,
579
+ propertyName,
580
+ prototypeDescriptors[propertyName]
581
+ );
582
+ }
555
583
  const requestController = new XMLHttpRequestController(
556
584
  originalRequest,
557
585
  log
@@ -1,10 +1,10 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkGGD5JOGBjs = require('../../chunk-GGD5JOGB.js');
3
+ var _chunkRVLLS44Wjs = require('../../chunk-RVLLS44W.js');
4
4
  require('../../chunk-SNNL2EXF.js');
5
5
  require('../../chunk-VQ4DZOBB.js');
6
6
  require('../../chunk-ZJOF5MEZ.js');
7
7
  require('../../chunk-WWHITCCI.js');
8
8
 
9
9
 
10
- exports.XMLHttpRequestInterceptor = _chunkGGD5JOGBjs.XMLHttpRequestInterceptor;
10
+ exports.XMLHttpRequestInterceptor = _chunkRVLLS44Wjs.XMLHttpRequestInterceptor;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  XMLHttpRequestInterceptor
3
- } from "../../chunk-CYWTKHFI.mjs";
3
+ } from "../../chunk-P7NKDCFD.mjs";
4
4
  import "../../chunk-G6ZTHYZQ.mjs";
5
5
  import "../../chunk-GFH37L5D.mjs";
6
6
  import "../../chunk-STA6QBYM.mjs";
@@ -11,6 +11,7 @@ var _chunkWWHITCCIjs = require('../../chunk-WWHITCCI.js');
11
11
 
12
12
  // src/interceptors/fetch/index.ts
13
13
  var _outvariant = require('outvariant');
14
+ var _until = require('@open-draft/until');
14
15
  var _FetchInterceptor = class extends _chunkWWHITCCIjs.Interceptor {
15
16
  constructor() {
16
17
  super(_FetchInterceptor.symbol);
@@ -35,15 +36,25 @@ var _FetchInterceptor = class extends _chunkWWHITCCIjs.Interceptor {
35
36
  );
36
37
  this.emitter.emit("request", interactiveRequest, requestId);
37
38
  this.log("awaiting for the mocked response...");
38
- await this.emitter.untilIdle(
39
- "request",
40
- ({ args: [, pendingRequestId] }) => {
41
- return pendingRequestId === requestId;
42
- }
43
- );
44
- this.log("all request listeners have been resolved!");
45
- const [mockedResponse] = await interactiveRequest.respondWith.invoked();
46
- this.log("event.respondWith called with:", mockedResponse);
39
+ const [middlewareException, mockedResponse] = await _until.until.call(void 0, async () => {
40
+ await this.emitter.untilIdle(
41
+ "request",
42
+ ({ args: [, pendingRequestId] }) => {
43
+ return pendingRequestId === requestId;
44
+ }
45
+ );
46
+ this.log("all request listeners have been resolved!");
47
+ const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
48
+ this.log("event.respondWith called with:", mockedResponse2);
49
+ return mockedResponse2;
50
+ });
51
+ if (middlewareException) {
52
+ console.error(`${request.method} ${request.url} net::ERR_FAILED`);
53
+ const error = Object.assign(new TypeError("Failed to fetch"), {
54
+ cause: middlewareException
55
+ });
56
+ return Promise.reject(error);
57
+ }
47
58
  if (mockedResponse) {
48
59
  this.log("received mocked response:", mockedResponse);
49
60
  const responseCloine = mockedResponse.clone();
@@ -11,6 +11,7 @@ import {
11
11
 
12
12
  // src/interceptors/fetch/index.ts
13
13
  import { invariant } from "outvariant";
14
+ import { until } from "@open-draft/until";
14
15
  var _FetchInterceptor = class extends Interceptor {
15
16
  constructor() {
16
17
  super(_FetchInterceptor.symbol);
@@ -35,15 +36,25 @@ var _FetchInterceptor = class extends Interceptor {
35
36
  );
36
37
  this.emitter.emit("request", interactiveRequest, requestId);
37
38
  this.log("awaiting for the mocked response...");
38
- await this.emitter.untilIdle(
39
- "request",
40
- ({ args: [, pendingRequestId] }) => {
41
- return pendingRequestId === requestId;
42
- }
43
- );
44
- this.log("all request listeners have been resolved!");
45
- const [mockedResponse] = await interactiveRequest.respondWith.invoked();
46
- this.log("event.respondWith called with:", mockedResponse);
39
+ const [middlewareException, mockedResponse] = await until(async () => {
40
+ await this.emitter.untilIdle(
41
+ "request",
42
+ ({ args: [, pendingRequestId] }) => {
43
+ return pendingRequestId === requestId;
44
+ }
45
+ );
46
+ this.log("all request listeners have been resolved!");
47
+ const [mockedResponse2] = await interactiveRequest.respondWith.invoked();
48
+ this.log("event.respondWith called with:", mockedResponse2);
49
+ return mockedResponse2;
50
+ });
51
+ if (middlewareException) {
52
+ console.error(`${request.method} ${request.url} net::ERR_FAILED`);
53
+ const error = Object.assign(new TypeError("Failed to fetch"), {
54
+ cause: middlewareException
55
+ });
56
+ return Promise.reject(error);
57
+ }
47
58
  if (mockedResponse) {
48
59
  this.log("received mocked response:", mockedResponse);
49
60
  const responseCloine = mockedResponse.clone();
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.22.3",
4
+ "version": "0.22.4",
5
5
  "main": "./lib/node/index.js",
6
6
  "module": "./lib/node/index.mjs",
7
7
  "types": "./lib/node/index.d.ts",
@@ -85,7 +85,7 @@
85
85
  "devDependencies": {
86
86
  "@commitlint/cli": "^16.0.2",
87
87
  "@commitlint/config-conventional": "^16.0.0",
88
- "@open-draft/test-server": "^0.4.2",
88
+ "@open-draft/test-server": "^0.5.1",
89
89
  "@ossjs/release": "^0.4.0",
90
90
  "@playwright/test": "^1.31.1",
91
91
  "@types/cors": "^2.8.12",
@@ -47,17 +47,32 @@ export class XMLHttpRequestController {
47
47
 
48
48
  this.request = createProxy(initialRequest, {
49
49
  setProperty: ([propertyName, nextValue], invoke) => {
50
- /**
51
- * @note Setting the "withCredentials" property on the XHR proxy
52
- * causes the "TypeError: Illegal invocation" error. Instead,
53
- * define the property on the original XHR instance itself.
54
- */
55
- if (propertyName === 'withCredentials') {
56
- define(this.request, 'withCredentials', nextValue)
57
- return true
58
- }
50
+ switch (propertyName) {
51
+ case 'onabort':
52
+ case 'onerror':
53
+ case 'onload':
54
+ case 'onloadend':
55
+ case 'onloadstart':
56
+ case 'onprogress':
57
+ case 'ontimeout':
58
+ case 'onreadystatechange': {
59
+ const eventName = propertyName.slice(
60
+ 2
61
+ ) as keyof XMLHttpRequestEventTargetEventMap
62
+
63
+ /**
64
+ * @note Proxy callbacks to event listeners because JSDOM has trouble
65
+ * translating these properties to callbacks. It seemed to be operating
66
+ * on events exclusively.
67
+ */
68
+ this.request.addEventListener(eventName, nextValue as any)
69
+ return invoke()
70
+ }
59
71
 
60
- return invoke()
72
+ default: {
73
+ return invoke()
74
+ }
75
+ }
61
76
  },
62
77
  methodCall: ([methodName, args], invoke) => {
63
78
  switch (methodName) {
@@ -85,8 +100,8 @@ export class XMLHttpRequestController {
85
100
  keyof XMLHttpRequestEventTargetEventMap,
86
101
  Function
87
102
  ]
88
- this.registerEvent(eventName, listener)
89
103
 
104
+ this.registerEvent(eventName, listener)
90
105
  this.log('addEventListener', eventName, listener.name)
91
106
 
92
107
  return invoke()
@@ -120,8 +135,7 @@ export class XMLHttpRequestController {
120
135
  this.request,
121
136
  /**
122
137
  * The `response` property is the right way to read
123
- * the ambiguous response body, as the request's "responseTyoe"
124
- * may differ.
138
+ * the ambiguous response body, as the request's "responseType" may differ.
125
139
  * @see https://xhr.spec.whatwg.org/#the-response-attribute
126
140
  */
127
141
  this.request.response
@@ -171,22 +185,6 @@ export class XMLHttpRequestController {
171
185
  break
172
186
  }
173
187
 
174
- case 'onabort':
175
- case 'onerror':
176
- case 'onload':
177
- case 'onloadend':
178
- case 'onloadstart':
179
- case 'onprogress':
180
- case 'ontimeout':
181
- case 'onreadystatechange': {
182
- const [listener] = args as [Function]
183
- this.registerEvent(
184
- methodName as keyof XMLHttpRequestEventTargetEventMap,
185
- listener
186
- )
187
- return invoke()
188
- }
189
-
190
188
  default: {
191
189
  return invoke()
192
190
  }
@@ -264,14 +262,17 @@ export class XMLHttpRequestController {
264
262
  Object.defineProperties(this.request, {
265
263
  response: {
266
264
  enumerable: true,
265
+ configurable: false,
267
266
  get: () => this.response,
268
267
  },
269
268
  responseText: {
270
269
  enumerable: true,
270
+ configurable: false,
271
271
  get: () => this.responseText,
272
272
  },
273
273
  responseXML: {
274
274
  enumerable: true,
275
+ configurable: false,
275
276
  get: () => this.responseXML,
276
277
  },
277
278
  })
@@ -19,10 +19,28 @@ export function createXMLHttpRequestProxy({
19
19
  log,
20
20
  }: XMLHttpRequestProxyOptions) {
21
21
  const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {
22
- construct(target, args) {
22
+ construct(target, args, newTarget) {
23
23
  log('constructed new XMLHttpRequest')
24
24
 
25
- const originalRequest = Reflect.construct(target, args)
25
+ const originalRequest = Reflect.construct(target, args, newTarget)
26
+
27
+ /**
28
+ * @note Forward prototype descriptors onto the proxied object.
29
+ * XMLHttpRequest is implemented in JSDOM in a way that assigns
30
+ * a bunch of descriptors, like "set responseType()" on the prototype.
31
+ * With this propagation, we make sure that those descriptors trigger
32
+ * when the user operates with the proxied request instance.
33
+ */
34
+ const prototypeDescriptors = Object.getOwnPropertyDescriptors(
35
+ target.prototype
36
+ )
37
+ for (const propertyName in prototypeDescriptors) {
38
+ Reflect.defineProperty(
39
+ originalRequest,
40
+ propertyName,
41
+ prototypeDescriptors[propertyName]
42
+ )
43
+ }
26
44
 
27
45
  const requestController = new XMLHttpRequestController(
28
46
  originalRequest,
@@ -2,7 +2,7 @@ import { stringToHeaders } from 'headers-polyfill'
2
2
 
3
3
  export function createResponse(
4
4
  request: XMLHttpRequest,
5
- responseBody: Uint8Array
5
+ responseBody: BodyInit | null
6
6
  ): Response {
7
7
  return new Response(responseBody, {
8
8
  status: request.status,
@@ -3,6 +3,7 @@ import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'
3
3
  import { Interceptor } from '../../Interceptor'
4
4
  import { uuidv4 } from '../../utils/uuid'
5
5
  import { toInteractiveRequest } from '../../utils/toInteractiveRequest'
6
+ import { until } from '@open-draft/until'
6
7
 
7
8
  export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
8
9
  static symbol = Symbol('fetch')
@@ -42,16 +43,28 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
42
43
 
43
44
  this.log('awaiting for the mocked response...')
44
45
 
45
- await this.emitter.untilIdle(
46
- 'request',
47
- ({ args: [, pendingRequestId] }) => {
48
- return pendingRequestId === requestId
49
- }
50
- )
51
- this.log('all request listeners have been resolved!')
46
+ const [middlewareException, mockedResponse] = await until(async () => {
47
+ await this.emitter.untilIdle(
48
+ 'request',
49
+ ({ args: [, pendingRequestId] }) => {
50
+ return pendingRequestId === requestId
51
+ }
52
+ )
53
+ this.log('all request listeners have been resolved!')
52
54
 
53
- const [mockedResponse] = await interactiveRequest.respondWith.invoked()
54
- this.log('event.respondWith called with:', mockedResponse)
55
+ const [mockedResponse] = await interactiveRequest.respondWith.invoked()
56
+ this.log('event.respondWith called with:', mockedResponse)
57
+
58
+ return mockedResponse
59
+ })
60
+
61
+ if (middlewareException) {
62
+ console.error(`${request.method} ${request.url} net::ERR_FAILED`)
63
+ const error = Object.assign(new TypeError('Failed to fetch'), {
64
+ cause: middlewareException,
65
+ })
66
+ return Promise.reject(error)
67
+ }
55
68
 
56
69
  if (mockedResponse) {
57
70
  this.log('received mocked response:', mockedResponse)
@@ -0,0 +1,149 @@
1
+ import { vi, it, expect } from 'vitest'
2
+ import { createProxy } from './createProxy'
3
+
4
+ it('does not interfere with default constructors', () => {
5
+ const ProxyClass = createProxy(
6
+ class {
7
+ constructor(public name: string) {}
8
+ },
9
+ {}
10
+ )
11
+
12
+ const instance = new ProxyClass('John')
13
+ expect(instance.name).toBe('John')
14
+ })
15
+
16
+ it('does not interfere with default getters', () => {
17
+ const proxy = createProxy({ foo: 'initial' }, {})
18
+ expect(proxy.foo).toBe('initial')
19
+ })
20
+
21
+ it('does not interfere with default setters', () => {
22
+ const proxy = createProxy({ foo: 'initial' }, {})
23
+ proxy.foo = 'next'
24
+
25
+ expect(proxy.foo).toBe('next')
26
+ })
27
+
28
+ it('does not interfere with default methods', () => {
29
+ const proxy = createProxy({ getValue: () => 'initial' }, {})
30
+ expect(proxy.getValue()).toBe('initial')
31
+ })
32
+
33
+ it('does not interfere with existing descriptors', () => {
34
+ const target = {} as { foo: string; bar: number }
35
+ let internalBar = 0
36
+
37
+ Object.defineProperties(target, {
38
+ foo: {
39
+ get: () => 'initial',
40
+ },
41
+ bar: {
42
+ set: (value) => {
43
+ internalBar = value + 10
44
+ },
45
+ },
46
+ })
47
+
48
+ const proxy = createProxy(target, {
49
+ getProperty(data, next) {
50
+ return next()
51
+ },
52
+ })
53
+ expect(proxy.foo).toBe('initial')
54
+
55
+ proxy.bar = 5
56
+ expect(proxy.bar).toBeUndefined()
57
+ expect(internalBar).toBe(15)
58
+ })
59
+
60
+ it('infer prototype descriptors', () => {
61
+ class Child {
62
+ ok: boolean
63
+
64
+ set status(nextStatus: number) {
65
+ this.ok = nextStatus >= 200 && nextStatus < 300
66
+ }
67
+ }
68
+
69
+ Object.defineProperties(Child.prototype, {
70
+ status: { enumerable: true },
71
+ })
72
+
73
+ const scope = {} as { child: typeof Child }
74
+
75
+ Object.defineProperty(scope, 'child', {
76
+ enumerable: true,
77
+ value: Child,
78
+ })
79
+
80
+ const ProxyClass = createProxy(scope.child, {})
81
+ const instance = new ProxyClass()
82
+
83
+ instance.status = 201
84
+ expect(instance.ok).toBe(true)
85
+ })
86
+
87
+ it('spies on the constructor', () => {
88
+ const OriginalClass = class {
89
+ constructor(public name: string, public age: number) {}
90
+ }
91
+
92
+ const constructorCall = vi.fn<
93
+ [ConstructorParameters<typeof OriginalClass>, Function],
94
+ typeof OriginalClass
95
+ >((args, next) => next())
96
+
97
+ const ProxyClass = createProxy(OriginalClass, {
98
+ constructorCall,
99
+ })
100
+
101
+ new ProxyClass('John', 32)
102
+
103
+ expect(constructorCall).toHaveBeenCalledTimes(1)
104
+ expect(constructorCall).toHaveBeenCalledWith(
105
+ ['John', 32],
106
+ expect.any(Function)
107
+ )
108
+ })
109
+
110
+ it('spies on property getters', () => {
111
+ const getProperty = vi.fn((args, next) => next())
112
+ const proxy = createProxy({ foo: 'initial' }, { getProperty })
113
+
114
+ proxy.foo
115
+
116
+ expect(getProperty).toHaveBeenCalledTimes(1)
117
+ expect(getProperty).toHaveBeenCalledWith(['foo', proxy], expect.any(Function))
118
+ })
119
+
120
+ it('spies on property setters', () => {
121
+ const setProperty = vi.fn((args, next) => next())
122
+ const proxy = createProxy({ foo: 'initial' }, { setProperty })
123
+
124
+ proxy.foo = 'next'
125
+
126
+ expect(setProperty).toHaveBeenCalledTimes(1)
127
+ expect(setProperty).toHaveBeenCalledWith(
128
+ ['foo', 'next'],
129
+ expect.any(Function)
130
+ )
131
+ })
132
+
133
+ it('spies on method calls', () => {
134
+ const methodCall = vi.fn((args, next) => next())
135
+ const proxy = createProxy(
136
+ {
137
+ greet: (name: string) => `hello ${name}`,
138
+ },
139
+ { methodCall }
140
+ )
141
+
142
+ proxy.greet('Clair')
143
+
144
+ expect(methodCall).toHaveBeenCalledTimes(1)
145
+ expect(methodCall).toHaveBeenCalledWith(
146
+ ['greet', ['Clair']],
147
+ expect.any(Function)
148
+ )
149
+ })
@@ -9,8 +9,8 @@ export interface ProxyOptions<Target extends Record<string, any>> {
9
9
 
10
10
  setProperty?(
11
11
  data: [propertyName: string | symbol, nextValue: unknown],
12
- next: NextFunction<void>
13
- ): void
12
+ next: NextFunction<boolean>
13
+ ): boolean
14
14
 
15
15
  getProperty?(
16
16
  data: [propertyName: string | symbol, receiver: Target],
@@ -25,6 +25,7 @@ export function createProxy<Target extends object>(
25
25
  options: ProxyOptions<Target>
26
26
  ): Target {
27
27
  const proxy = new Proxy(target, optionsToProxyHandler(options))
28
+
28
29
  return proxy
29
30
  }
30
31
 
@@ -41,11 +42,31 @@ function optionsToProxyHandler<T extends Record<string, any>>(
41
42
  }
42
43
  }
43
44
 
44
- if (typeof setProperty !== 'undefined') {
45
- handler.set = function (target, propertyName, nextValue, receiver) {
46
- const next = () => Reflect.set(target, propertyName, nextValue, receiver)
47
- return setProperty.call(target, [propertyName, nextValue], next) as any
45
+ handler.set = function (target, propertyName, nextValue, receiver) {
46
+ const next = () => {
47
+ const ownDescriptors = Reflect.getOwnPropertyDescriptor(
48
+ target,
49
+ propertyName
50
+ )
51
+
52
+ if (typeof ownDescriptors?.set !== 'undefined') {
53
+ ownDescriptors.set.apply(target, [nextValue])
54
+ return true
55
+ }
56
+
57
+ return Reflect.defineProperty(target, propertyName, {
58
+ writable: true,
59
+ enumerable: true,
60
+ configurable: true,
61
+ value: nextValue,
62
+ })
63
+ }
64
+
65
+ if (typeof setProperty !== 'undefined') {
66
+ return setProperty.call(target, [propertyName, nextValue], next)
48
67
  }
68
+
69
+ return next()
49
70
  }
50
71
 
51
72
  handler.get = function (target, propertyName, receiver) {