@mswjs/interceptors 0.26.13 → 0.26.15

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.
Files changed (104) hide show
  1. package/README.md +29 -14
  2. package/lib/browser/{chunk-5E3BR6QC.mjs → chunk-3FNUI33J.mjs} +5 -4
  3. package/lib/browser/chunk-3FNUI33J.mjs.map +1 -0
  4. package/lib/browser/{chunk-5HSEVANC.js → chunk-65PS3XCB.js} +6 -5
  5. package/lib/browser/chunk-65PS3XCB.js.map +1 -0
  6. package/lib/browser/{chunk-N6P4WNMD.js → chunk-DFOMNPZ4.js} +5 -4
  7. package/lib/browser/chunk-DFOMNPZ4.js.map +1 -0
  8. package/lib/{node/chunk-TNNJTZLG.mjs → browser/chunk-QED3Q6Z2.mjs} +8 -6
  9. package/lib/browser/chunk-QED3Q6Z2.mjs.map +1 -0
  10. package/lib/browser/{chunk-3PGRU2BR.js → chunk-TIPR373R.js} +8 -2
  11. package/lib/browser/chunk-TIPR373R.js.map +1 -0
  12. package/lib/browser/{chunk-WVYFUFZR.mjs → chunk-VYFS2IF2.mjs} +5 -4
  13. package/lib/browser/chunk-VYFS2IF2.mjs.map +1 -0
  14. package/lib/browser/index.d.ts +9 -1
  15. package/lib/browser/index.js +5 -3
  16. package/lib/browser/index.js.map +1 -1
  17. package/lib/browser/index.mjs +3 -1
  18. package/lib/browser/index.mjs.map +1 -1
  19. package/lib/browser/interceptors/WebSocket/index.js +29 -7
  20. package/lib/browser/interceptors/WebSocket/index.js.map +1 -1
  21. package/lib/browser/interceptors/WebSocket/index.mjs +29 -7
  22. package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -1
  23. package/lib/browser/interceptors/XMLHttpRequest/index.js +3 -3
  24. package/lib/browser/interceptors/XMLHttpRequest/index.mjs +2 -2
  25. package/lib/browser/interceptors/fetch/index.js +3 -3
  26. package/lib/browser/interceptors/fetch/index.mjs +2 -2
  27. package/lib/browser/presets/browser.js +5 -5
  28. package/lib/browser/presets/browser.mjs +3 -3
  29. package/lib/node/RemoteHttpInterceptor.js +15 -15
  30. package/lib/node/RemoteHttpInterceptor.mjs +9 -9
  31. package/lib/node/{chunk-ORI3LFXR.mjs → chunk-6HYIRFX2.mjs} +1 -1
  32. package/lib/node/{chunk-ZOS6ZFFL.js → chunk-7I24Q7UY.js} +13 -13
  33. package/lib/node/chunk-7I24Q7UY.js.map +1 -0
  34. package/lib/node/{chunk-OIJM4NGH.mjs → chunk-CCASONWB.mjs} +7 -7
  35. package/lib/node/chunk-CCASONWB.mjs.map +1 -0
  36. package/lib/node/{chunk-CDO7LUCB.mjs → chunk-DERTLGL3.mjs} +1 -1
  37. package/lib/node/{chunk-HOHLBCZO.js → chunk-FZJKKO5H.js} +1 -1
  38. package/lib/node/{chunk-66HWDCQ2.mjs → chunk-GUY7XK43.mjs} +2 -2
  39. package/lib/node/{chunk-YQUDKP67.mjs → chunk-HAGW22AN.mjs} +1 -1
  40. package/lib/node/{chunk-LVMKW3BV.mjs → chunk-IBYBTTYK.mjs} +1 -1
  41. package/lib/node/{chunk-XRANZXDY.js → chunk-JSSEHRRB.js} +1 -1
  42. package/lib/node/{chunk-WJBJLZSK.js → chunk-K74ZLSG6.js} +18 -18
  43. package/lib/node/chunk-K74ZLSG6.js.map +1 -0
  44. package/lib/node/{chunk-DWNXSX4R.js → chunk-LK6DILFK.js} +1 -1
  45. package/lib/node/{chunk-Z2GCDAWN.js → chunk-LMCO6WE2.js} +3 -3
  46. package/lib/node/{chunk-AQD7SRYT.js → chunk-MQJ3JOOK.js} +1 -1
  47. package/lib/node/{chunk-7GOGV57P.mjs → chunk-OUWBQF3Z.mjs} +1 -1
  48. package/lib/{browser/chunk-KHZ3VYHS.mjs → node/chunk-QED3Q6Z2.mjs} +8 -2
  49. package/lib/node/chunk-QED3Q6Z2.mjs.map +1 -0
  50. package/lib/node/{chunk-Q2ZAXW2V.js → chunk-TIPR373R.js} +8 -6
  51. package/lib/node/chunk-TIPR373R.js.map +1 -0
  52. package/lib/node/{chunk-5JPIH6H2.mjs → chunk-VUILOQBY.mjs} +8 -8
  53. package/lib/node/chunk-VUILOQBY.mjs.map +1 -0
  54. package/lib/node/{chunk-OQFUVENL.js → chunk-Y6GRL6UD.js} +1 -1
  55. package/lib/node/index.d.ts +9 -1
  56. package/lib/node/index.js +8 -6
  57. package/lib/node/index.js.map +1 -1
  58. package/lib/node/index.mjs +7 -5
  59. package/lib/node/index.mjs.map +1 -1
  60. package/lib/node/interceptors/ClientRequest/index.js +6 -6
  61. package/lib/node/interceptors/ClientRequest/index.mjs +5 -5
  62. package/lib/node/interceptors/XMLHttpRequest/index.js +7 -7
  63. package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -6
  64. package/lib/node/interceptors/fetch/index.js +12 -12
  65. package/lib/node/interceptors/fetch/index.js.map +1 -1
  66. package/lib/node/interceptors/fetch/index.mjs +6 -6
  67. package/lib/node/interceptors/fetch/index.mjs.map +1 -1
  68. package/lib/node/presets/node.js +10 -10
  69. package/lib/node/presets/node.mjs +8 -8
  70. package/package.json +1 -1
  71. package/src/createRequestId.test.ts +7 -0
  72. package/src/createRequestId.ts +9 -0
  73. package/src/index.ts +1 -0
  74. package/src/interceptors/ClientRequest/NodeClientRequest.ts +2 -1
  75. package/src/interceptors/WebSocket/WebSocketClientConnection.ts +2 -1
  76. package/src/interceptors/WebSocket/WebSocketServerConnection.ts +23 -0
  77. package/src/interceptors/WebSocket/utils/bindEvent.ts +12 -4
  78. package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +2 -1
  79. package/src/interceptors/fetch/index.ts +2 -1
  80. package/lib/browser/chunk-3PGRU2BR.js.map +0 -1
  81. package/lib/browser/chunk-5E3BR6QC.mjs.map +0 -1
  82. package/lib/browser/chunk-5HSEVANC.js.map +0 -1
  83. package/lib/browser/chunk-KHZ3VYHS.mjs.map +0 -1
  84. package/lib/browser/chunk-N6P4WNMD.js.map +0 -1
  85. package/lib/browser/chunk-WVYFUFZR.mjs.map +0 -1
  86. package/lib/node/chunk-5JPIH6H2.mjs.map +0 -1
  87. package/lib/node/chunk-OIJM4NGH.mjs.map +0 -1
  88. package/lib/node/chunk-Q2ZAXW2V.js.map +0 -1
  89. package/lib/node/chunk-TNNJTZLG.mjs.map +0 -1
  90. package/lib/node/chunk-WJBJLZSK.js.map +0 -1
  91. package/lib/node/chunk-ZOS6ZFFL.js.map +0 -1
  92. package/src/crypto-shim.ts +0 -3
  93. /package/lib/node/{chunk-ORI3LFXR.mjs.map → chunk-6HYIRFX2.mjs.map} +0 -0
  94. /package/lib/node/{chunk-CDO7LUCB.mjs.map → chunk-DERTLGL3.mjs.map} +0 -0
  95. /package/lib/node/{chunk-HOHLBCZO.js.map → chunk-FZJKKO5H.js.map} +0 -0
  96. /package/lib/node/{chunk-66HWDCQ2.mjs.map → chunk-GUY7XK43.mjs.map} +0 -0
  97. /package/lib/node/{chunk-YQUDKP67.mjs.map → chunk-HAGW22AN.mjs.map} +0 -0
  98. /package/lib/node/{chunk-LVMKW3BV.mjs.map → chunk-IBYBTTYK.mjs.map} +0 -0
  99. /package/lib/node/{chunk-XRANZXDY.js.map → chunk-JSSEHRRB.js.map} +0 -0
  100. /package/lib/node/{chunk-DWNXSX4R.js.map → chunk-LK6DILFK.js.map} +0 -0
  101. /package/lib/node/{chunk-Z2GCDAWN.js.map → chunk-LMCO6WE2.js.map} +0 -0
  102. /package/lib/node/{chunk-AQD7SRYT.js.map → chunk-MQJ3JOOK.js.map} +0 -0
  103. /package/lib/node/{chunk-7GOGV57P.mjs.map → chunk-OUWBQF3Z.mjs.map} +0 -0
  104. /package/lib/node/{chunk-OQFUVENL.js.map → chunk-Y6GRL6UD.js.map} +0 -0
@@ -1,12 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkWJBJLZSKjs = require('../../chunk-WJBJLZSK.js');
4
- require('../../chunk-DWNXSX4R.js');
5
- require('../../chunk-XRANZXDY.js');
6
- require('../../chunk-HOHLBCZO.js');
7
- require('../../chunk-AQD7SRYT.js');
8
- require('../../chunk-Q2ZAXW2V.js');
3
+ var _chunkK74ZLSG6js = require('../../chunk-K74ZLSG6.js');
4
+ require('../../chunk-LK6DILFK.js');
5
+ require('../../chunk-JSSEHRRB.js');
6
+ require('../../chunk-FZJKKO5H.js');
7
+ require('../../chunk-MQJ3JOOK.js');
8
+ require('../../chunk-TIPR373R.js');
9
9
 
10
10
 
11
- exports.XMLHttpRequestInterceptor = _chunkWJBJLZSKjs.XMLHttpRequestInterceptor;
11
+ exports.XMLHttpRequestInterceptor = _chunkK74ZLSG6js.XMLHttpRequestInterceptor;
12
12
  //# sourceMappingURL=index.js.map
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  XMLHttpRequestInterceptor
3
- } from "../../chunk-5JPIH6H2.mjs";
4
- import "../../chunk-ORI3LFXR.mjs";
5
- import "../../chunk-LVMKW3BV.mjs";
6
- import "../../chunk-YQUDKP67.mjs";
7
- import "../../chunk-7GOGV57P.mjs";
8
- import "../../chunk-TNNJTZLG.mjs";
3
+ } from "../../chunk-VUILOQBY.mjs";
4
+ import "../../chunk-6HYIRFX2.mjs";
5
+ import "../../chunk-IBYBTTYK.mjs";
6
+ import "../../chunk-HAGW22AN.mjs";
7
+ import "../../chunk-OUWBQF3Z.mjs";
8
+ import "../../chunk-QED3Q6Z2.mjs";
9
9
  export {
10
10
  XMLHttpRequestInterceptor
11
11
  };
@@ -1,17 +1,17 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkOQFUVENLjs = require('../../chunk-OQFUVENL.js');
3
+ var _chunkY6GRL6UDjs = require('../../chunk-Y6GRL6UD.js');
4
4
 
5
5
 
6
- var _chunkHOHLBCZOjs = require('../../chunk-HOHLBCZO.js');
6
+ var _chunkFZJKKO5Hjs = require('../../chunk-FZJKKO5H.js');
7
7
 
8
8
 
9
9
 
10
- var _chunkAQD7SRYTjs = require('../../chunk-AQD7SRYT.js');
10
+ var _chunkMQJ3JOOKjs = require('../../chunk-MQJ3JOOK.js');
11
11
 
12
12
 
13
13
 
14
- var _chunkQ2ZAXW2Vjs = require('../../chunk-Q2ZAXW2V.js');
14
+ var _chunkTIPR373Rjs = require('../../chunk-TIPR373R.js');
15
15
 
16
16
  // src/interceptors/fetch/index.ts
17
17
  var _outvariant = require('outvariant');
@@ -29,7 +29,7 @@ function canParseUrl(url) {
29
29
  }
30
30
 
31
31
  // src/interceptors/fetch/index.ts
32
- var _FetchInterceptor = class extends _chunkQ2ZAXW2Vjs.Interceptor {
32
+ var _FetchInterceptor = class extends _chunkTIPR373Rjs.Interceptor {
33
33
  constructor() {
34
34
  super(_FetchInterceptor.symbol);
35
35
  }
@@ -39,16 +39,16 @@ var _FetchInterceptor = class extends _chunkQ2ZAXW2Vjs.Interceptor {
39
39
  async setup() {
40
40
  const pureFetch = globalThis.fetch;
41
41
  _outvariant.invariant.call(void 0,
42
- !pureFetch[_chunkHOHLBCZOjs.IS_PATCHED_MODULE],
42
+ !pureFetch[_chunkFZJKKO5Hjs.IS_PATCHED_MODULE],
43
43
  'Failed to patch the "fetch" module: already patched.'
44
44
  );
45
45
  globalThis.fetch = async (input, init) => {
46
46
  var _a;
47
- const requestId = _chunkQ2ZAXW2Vjs.crypto.randomUUID();
47
+ const requestId = _chunkTIPR373Rjs.createRequestId.call(void 0, );
48
48
  const resolvedInput = typeof input === "string" && typeof location !== "undefined" && !canParseUrl(input) ? new URL(input, location.origin) : input;
49
49
  const request = new Request(resolvedInput, init);
50
50
  this.logger.info("[%s] %s", request.method, request.url);
51
- const { interactiveRequest, requestController } = _chunkAQD7SRYTjs.toInteractiveRequest.call(void 0, request);
51
+ const { interactiveRequest, requestController } = _chunkMQJ3JOOKjs.toInteractiveRequest.call(void 0, request);
52
52
  this.logger.info(
53
53
  'emitting the "request" event for %d listener(s)...',
54
54
  this.emitter.listenerCount("request")
@@ -74,7 +74,7 @@ var _FetchInterceptor = class extends _chunkQ2ZAXW2Vjs.Interceptor {
74
74
  );
75
75
  }
76
76
  const resolverResult = await _until.until.call(void 0, async () => {
77
- const listenersFinished = _chunkAQD7SRYTjs.emitAsync.call(void 0, this.emitter, "request", {
77
+ const listenersFinished = _chunkMQJ3JOOKjs.emitAsync.call(void 0, this.emitter, "request", {
78
78
  request: interactiveRequest,
79
79
  requestId
80
80
  });
@@ -100,7 +100,7 @@ var _FetchInterceptor = class extends _chunkQ2ZAXW2Vjs.Interceptor {
100
100
  const mockedResponse = resolverResult.data;
101
101
  if (mockedResponse && !((_a = request.signal) == null ? void 0 : _a.aborted)) {
102
102
  this.logger.info("received mocked response:", mockedResponse);
103
- if (_chunkOQFUVENLjs.isPropertyAccessible.call(void 0, mockedResponse, "type") && mockedResponse.type === "error") {
103
+ if (_chunkY6GRL6UDjs.isPropertyAccessible.call(void 0, mockedResponse, "type") && mockedResponse.type === "error") {
104
104
  this.logger.info(
105
105
  "received a network error response, rejecting the request promise..."
106
106
  );
@@ -134,13 +134,13 @@ var _FetchInterceptor = class extends _chunkQ2ZAXW2Vjs.Interceptor {
134
134
  return response;
135
135
  });
136
136
  };
137
- Object.defineProperty(globalThis.fetch, _chunkHOHLBCZOjs.IS_PATCHED_MODULE, {
137
+ Object.defineProperty(globalThis.fetch, _chunkFZJKKO5Hjs.IS_PATCHED_MODULE, {
138
138
  enumerable: true,
139
139
  configurable: true,
140
140
  value: true
141
141
  });
142
142
  this.subscriptions.push(() => {
143
- Object.defineProperty(globalThis.fetch, _chunkHOHLBCZOjs.IS_PATCHED_MODULE, {
143
+ Object.defineProperty(globalThis.fetch, _chunkFZJKKO5Hjs.IS_PATCHED_MODULE, {
144
144
  value: void 0
145
145
  });
146
146
  globalThis.fetch = pureFetch;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/interceptors/fetch/index.ts","../../../../src/utils/canParseUrl.ts"],"names":["mockedResponse"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { toInteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { canParseUrl } from '../../utils/canParseUrl'\n\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch !== 'undefined'\n )\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = crypto.randomUUID()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n\n this.logger.info('[%s] %s', request.method, request.url)\n\n const { interactiveRequest, requestController } =\n toInteractiveRequest(request)\n\n this.logger.info(\n 'emitting the \"request\" event for %d listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n this.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== requestId) {\n return\n }\n\n if (requestController.responsePromise.state === 'pending') {\n requestController.responsePromise.resolve(undefined)\n }\n })\n\n this.logger.info('awaiting for the mocked response...')\n\n const signal = interactiveRequest.signal\n const requestAborted = new DeferredPromise()\n\n // Signal isn't always defined in react-native.\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n requestAborted.reject(signal.reason)\n },\n { once: true }\n )\n }\n\n const resolverResult = await until(async () => {\n const listenersFinished = emitAsync(this.emitter, 'request', {\n request: interactiveRequest,\n requestId,\n })\n\n await Promise.race([\n requestAborted,\n // Put the listeners invocation Promise in the same race condition\n // with the request abort Promise because otherwise awaiting the listeners\n // would always yield some response (or undefined).\n listenersFinished,\n requestController.responsePromise,\n ])\n\n this.logger.info('all request listeners have been resolved!')\n\n const mockedResponse = await requestController.responsePromise\n this.logger.info('event.respondWith called with:', mockedResponse)\n\n return mockedResponse\n })\n\n if (requestAborted.state === 'rejected') {\n return Promise.reject(requestAborted.rejectionReason)\n }\n\n if (resolverResult.error) {\n return Promise.reject(createNetworkError(resolverResult.error))\n }\n\n const mockedResponse = resolverResult.data\n\n if (mockedResponse && !request.signal?.aborted) {\n this.logger.info('received mocked response:', mockedResponse)\n\n // Reject the request Promise on mocked \"Response.error\" responses.\n if (\n isPropertyAccessible(mockedResponse, 'type') &&\n mockedResponse.type === 'error'\n ) {\n this.logger.info(\n 'received a network error response, rejecting the request promise...'\n )\n\n /**\n * Set the cause of the request promise rejection to the\n * network error Response instance. This different from Undici.\n * Undici will forward the \"response.error\" custom property\n * as the rejection reason but for \"Response.error()\" static method\n * \"response.error\" will equal to undefined, making \"cause\" an empty Error.\n * @see https://github.com/nodejs/undici/blob/83cb522ae0157a19d149d72c7d03d46e34510d0a/lib/fetch/response.js#L344\n */\n return Promise.reject(createNetworkError(mockedResponse))\n }\n\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n const responseClone = mockedResponse.clone()\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: true,\n request: interactiveRequest,\n requestId,\n })\n\n // Set the \"response.url\" property to equal the intercepted request URL.\n Object.defineProperty(mockedResponse, 'url', {\n writable: false,\n enumerable: true,\n configurable: false,\n value: request.url,\n })\n\n return mockedResponse\n }\n\n this.logger.info('no mocked response received!')\n\n return pureFetch(request).then((response) => {\n const responseClone = response.clone()\n this.logger.info('original fetch performed', responseClone)\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: false,\n request: interactiveRequest,\n requestId,\n })\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n\nfunction createNetworkError(cause: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/interceptors/fetch/index.ts","../../../../src/utils/canParseUrl.ts"],"names":["mockedResponse"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { toInteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\n\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch !== 'undefined'\n )\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n\n this.logger.info('[%s] %s', request.method, request.url)\n\n const { interactiveRequest, requestController } =\n toInteractiveRequest(request)\n\n this.logger.info(\n 'emitting the \"request\" event for %d listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n this.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== requestId) {\n return\n }\n\n if (requestController.responsePromise.state === 'pending') {\n requestController.responsePromise.resolve(undefined)\n }\n })\n\n this.logger.info('awaiting for the mocked response...')\n\n const signal = interactiveRequest.signal\n const requestAborted = new DeferredPromise()\n\n // Signal isn't always defined in react-native.\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n requestAborted.reject(signal.reason)\n },\n { once: true }\n )\n }\n\n const resolverResult = await until(async () => {\n const listenersFinished = emitAsync(this.emitter, 'request', {\n request: interactiveRequest,\n requestId,\n })\n\n await Promise.race([\n requestAborted,\n // Put the listeners invocation Promise in the same race condition\n // with the request abort Promise because otherwise awaiting the listeners\n // would always yield some response (or undefined).\n listenersFinished,\n requestController.responsePromise,\n ])\n\n this.logger.info('all request listeners have been resolved!')\n\n const mockedResponse = await requestController.responsePromise\n this.logger.info('event.respondWith called with:', mockedResponse)\n\n return mockedResponse\n })\n\n if (requestAborted.state === 'rejected') {\n return Promise.reject(requestAborted.rejectionReason)\n }\n\n if (resolverResult.error) {\n return Promise.reject(createNetworkError(resolverResult.error))\n }\n\n const mockedResponse = resolverResult.data\n\n if (mockedResponse && !request.signal?.aborted) {\n this.logger.info('received mocked response:', mockedResponse)\n\n // Reject the request Promise on mocked \"Response.error\" responses.\n if (\n isPropertyAccessible(mockedResponse, 'type') &&\n mockedResponse.type === 'error'\n ) {\n this.logger.info(\n 'received a network error response, rejecting the request promise...'\n )\n\n /**\n * Set the cause of the request promise rejection to the\n * network error Response instance. This different from Undici.\n * Undici will forward the \"response.error\" custom property\n * as the rejection reason but for \"Response.error()\" static method\n * \"response.error\" will equal to undefined, making \"cause\" an empty Error.\n * @see https://github.com/nodejs/undici/blob/83cb522ae0157a19d149d72c7d03d46e34510d0a/lib/fetch/response.js#L344\n */\n return Promise.reject(createNetworkError(mockedResponse))\n }\n\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n const responseClone = mockedResponse.clone()\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: true,\n request: interactiveRequest,\n requestId,\n })\n\n // Set the \"response.url\" property to equal the intercepted request URL.\n Object.defineProperty(mockedResponse, 'url', {\n writable: false,\n enumerable: true,\n configurable: false,\n value: request.url,\n })\n\n return mockedResponse\n }\n\n this.logger.info('no mocked response received!')\n\n return pureFetch(request).then((response) => {\n const responseClone = response.clone()\n this.logger.info('original fetch performed', responseClone)\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: false,\n request: interactiveRequest,\n requestId,\n })\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n\nfunction createNetworkError(cause: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n"]}
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  isPropertyAccessible
3
- } from "../../chunk-CDO7LUCB.mjs";
3
+ } from "../../chunk-DERTLGL3.mjs";
4
4
  import {
5
5
  IS_PATCHED_MODULE
6
- } from "../../chunk-YQUDKP67.mjs";
6
+ } from "../../chunk-HAGW22AN.mjs";
7
7
  import {
8
8
  emitAsync,
9
9
  toInteractiveRequest
10
- } from "../../chunk-7GOGV57P.mjs";
10
+ } from "../../chunk-OUWBQF3Z.mjs";
11
11
  import {
12
12
  Interceptor,
13
- crypto
14
- } from "../../chunk-TNNJTZLG.mjs";
13
+ createRequestId
14
+ } from "../../chunk-QED3Q6Z2.mjs";
15
15
 
16
16
  // src/interceptors/fetch/index.ts
17
17
  import { invariant } from "outvariant";
@@ -44,7 +44,7 @@ var _FetchInterceptor = class extends Interceptor {
44
44
  );
45
45
  globalThis.fetch = async (input, init) => {
46
46
  var _a;
47
- const requestId = crypto.randomUUID();
47
+ const requestId = createRequestId();
48
48
  const resolvedInput = typeof input === "string" && typeof location !== "undefined" && !canParseUrl(input) ? new URL(input, location.origin) : input;
49
49
  const request = new Request(resolvedInput, init);
50
50
  this.logger.info("[%s] %s", request.method, request.url);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/interceptors/fetch/index.ts","../../../../src/utils/canParseUrl.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { toInteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { canParseUrl } from '../../utils/canParseUrl'\n\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch !== 'undefined'\n )\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = crypto.randomUUID()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n\n this.logger.info('[%s] %s', request.method, request.url)\n\n const { interactiveRequest, requestController } =\n toInteractiveRequest(request)\n\n this.logger.info(\n 'emitting the \"request\" event for %d listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n this.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== requestId) {\n return\n }\n\n if (requestController.responsePromise.state === 'pending') {\n requestController.responsePromise.resolve(undefined)\n }\n })\n\n this.logger.info('awaiting for the mocked response...')\n\n const signal = interactiveRequest.signal\n const requestAborted = new DeferredPromise()\n\n // Signal isn't always defined in react-native.\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n requestAborted.reject(signal.reason)\n },\n { once: true }\n )\n }\n\n const resolverResult = await until(async () => {\n const listenersFinished = emitAsync(this.emitter, 'request', {\n request: interactiveRequest,\n requestId,\n })\n\n await Promise.race([\n requestAborted,\n // Put the listeners invocation Promise in the same race condition\n // with the request abort Promise because otherwise awaiting the listeners\n // would always yield some response (or undefined).\n listenersFinished,\n requestController.responsePromise,\n ])\n\n this.logger.info('all request listeners have been resolved!')\n\n const mockedResponse = await requestController.responsePromise\n this.logger.info('event.respondWith called with:', mockedResponse)\n\n return mockedResponse\n })\n\n if (requestAborted.state === 'rejected') {\n return Promise.reject(requestAborted.rejectionReason)\n }\n\n if (resolverResult.error) {\n return Promise.reject(createNetworkError(resolverResult.error))\n }\n\n const mockedResponse = resolverResult.data\n\n if (mockedResponse && !request.signal?.aborted) {\n this.logger.info('received mocked response:', mockedResponse)\n\n // Reject the request Promise on mocked \"Response.error\" responses.\n if (\n isPropertyAccessible(mockedResponse, 'type') &&\n mockedResponse.type === 'error'\n ) {\n this.logger.info(\n 'received a network error response, rejecting the request promise...'\n )\n\n /**\n * Set the cause of the request promise rejection to the\n * network error Response instance. This different from Undici.\n * Undici will forward the \"response.error\" custom property\n * as the rejection reason but for \"Response.error()\" static method\n * \"response.error\" will equal to undefined, making \"cause\" an empty Error.\n * @see https://github.com/nodejs/undici/blob/83cb522ae0157a19d149d72c7d03d46e34510d0a/lib/fetch/response.js#L344\n */\n return Promise.reject(createNetworkError(mockedResponse))\n }\n\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n const responseClone = mockedResponse.clone()\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: true,\n request: interactiveRequest,\n requestId,\n })\n\n // Set the \"response.url\" property to equal the intercepted request URL.\n Object.defineProperty(mockedResponse, 'url', {\n writable: false,\n enumerable: true,\n configurable: false,\n value: request.url,\n })\n\n return mockedResponse\n }\n\n this.logger.info('no mocked response received!')\n\n return pureFetch(request).then((response) => {\n const responseClone = response.clone()\n this.logger.info('original fetch performed', responseClone)\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: false,\n request: interactiveRequest,\n requestId,\n })\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n\nfunction createNetworkError(cause: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n"],"mappings":"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","names":["mockedResponse"]}
1
+ {"version":3,"sources":["../../../../src/interceptors/fetch/index.ts","../../../../src/utils/canParseUrl.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { toInteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\n\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch !== 'undefined'\n )\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n\n this.logger.info('[%s] %s', request.method, request.url)\n\n const { interactiveRequest, requestController } =\n toInteractiveRequest(request)\n\n this.logger.info(\n 'emitting the \"request\" event for %d listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n this.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== requestId) {\n return\n }\n\n if (requestController.responsePromise.state === 'pending') {\n requestController.responsePromise.resolve(undefined)\n }\n })\n\n this.logger.info('awaiting for the mocked response...')\n\n const signal = interactiveRequest.signal\n const requestAborted = new DeferredPromise()\n\n // Signal isn't always defined in react-native.\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n requestAborted.reject(signal.reason)\n },\n { once: true }\n )\n }\n\n const resolverResult = await until(async () => {\n const listenersFinished = emitAsync(this.emitter, 'request', {\n request: interactiveRequest,\n requestId,\n })\n\n await Promise.race([\n requestAborted,\n // Put the listeners invocation Promise in the same race condition\n // with the request abort Promise because otherwise awaiting the listeners\n // would always yield some response (or undefined).\n listenersFinished,\n requestController.responsePromise,\n ])\n\n this.logger.info('all request listeners have been resolved!')\n\n const mockedResponse = await requestController.responsePromise\n this.logger.info('event.respondWith called with:', mockedResponse)\n\n return mockedResponse\n })\n\n if (requestAborted.state === 'rejected') {\n return Promise.reject(requestAborted.rejectionReason)\n }\n\n if (resolverResult.error) {\n return Promise.reject(createNetworkError(resolverResult.error))\n }\n\n const mockedResponse = resolverResult.data\n\n if (mockedResponse && !request.signal?.aborted) {\n this.logger.info('received mocked response:', mockedResponse)\n\n // Reject the request Promise on mocked \"Response.error\" responses.\n if (\n isPropertyAccessible(mockedResponse, 'type') &&\n mockedResponse.type === 'error'\n ) {\n this.logger.info(\n 'received a network error response, rejecting the request promise...'\n )\n\n /**\n * Set the cause of the request promise rejection to the\n * network error Response instance. This different from Undici.\n * Undici will forward the \"response.error\" custom property\n * as the rejection reason but for \"Response.error()\" static method\n * \"response.error\" will equal to undefined, making \"cause\" an empty Error.\n * @see https://github.com/nodejs/undici/blob/83cb522ae0157a19d149d72c7d03d46e34510d0a/lib/fetch/response.js#L344\n */\n return Promise.reject(createNetworkError(mockedResponse))\n }\n\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n const responseClone = mockedResponse.clone()\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: true,\n request: interactiveRequest,\n requestId,\n })\n\n // Set the \"response.url\" property to equal the intercepted request URL.\n Object.defineProperty(mockedResponse, 'url', {\n writable: false,\n enumerable: true,\n configurable: false,\n value: request.url,\n })\n\n return mockedResponse\n }\n\n this.logger.info('no mocked response received!')\n\n return pureFetch(request).then((response) => {\n const responseClone = response.clone()\n this.logger.info('original fetch performed', responseClone)\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: false,\n request: interactiveRequest,\n requestId,\n })\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n\nfunction createNetworkError(cause: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n"],"mappings":"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","names":["mockedResponse"]}
@@ -1,20 +1,20 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkZOS6ZFFLjs = require('../chunk-ZOS6ZFFL.js');
3
+ var _chunk7I24Q7UYjs = require('../chunk-7I24Q7UY.js');
4
4
 
5
5
 
6
- var _chunkWJBJLZSKjs = require('../chunk-WJBJLZSK.js');
7
- require('../chunk-DWNXSX4R.js');
8
- require('../chunk-XRANZXDY.js');
9
- require('../chunk-OQFUVENL.js');
10
- require('../chunk-HOHLBCZO.js');
11
- require('../chunk-AQD7SRYT.js');
12
- require('../chunk-Q2ZAXW2V.js');
6
+ var _chunkK74ZLSG6js = require('../chunk-K74ZLSG6.js');
7
+ require('../chunk-LK6DILFK.js');
8
+ require('../chunk-JSSEHRRB.js');
9
+ require('../chunk-Y6GRL6UD.js');
10
+ require('../chunk-FZJKKO5H.js');
11
+ require('../chunk-MQJ3JOOK.js');
12
+ require('../chunk-TIPR373R.js');
13
13
 
14
14
  // src/presets/node.ts
15
15
  var node_default = [
16
- new (0, _chunkZOS6ZFFLjs.ClientRequestInterceptor)(),
17
- new (0, _chunkWJBJLZSKjs.XMLHttpRequestInterceptor)()
16
+ new (0, _chunk7I24Q7UYjs.ClientRequestInterceptor)(),
17
+ new (0, _chunkK74ZLSG6js.XMLHttpRequestInterceptor)()
18
18
  ];
19
19
 
20
20
 
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ClientRequestInterceptor
3
- } from "../chunk-OIJM4NGH.mjs";
3
+ } from "../chunk-CCASONWB.mjs";
4
4
  import {
5
5
  XMLHttpRequestInterceptor
6
- } from "../chunk-5JPIH6H2.mjs";
7
- import "../chunk-ORI3LFXR.mjs";
8
- import "../chunk-LVMKW3BV.mjs";
9
- import "../chunk-CDO7LUCB.mjs";
10
- import "../chunk-YQUDKP67.mjs";
11
- import "../chunk-7GOGV57P.mjs";
12
- import "../chunk-TNNJTZLG.mjs";
6
+ } from "../chunk-VUILOQBY.mjs";
7
+ import "../chunk-6HYIRFX2.mjs";
8
+ import "../chunk-IBYBTTYK.mjs";
9
+ import "../chunk-DERTLGL3.mjs";
10
+ import "../chunk-HAGW22AN.mjs";
11
+ import "../chunk-OUWBQF3Z.mjs";
12
+ import "../chunk-QED3Q6Z2.mjs";
13
13
 
14
14
  // src/presets/node.ts
15
15
  var node_default = [
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.26.13",
4
+ "version": "0.26.15",
5
5
  "main": "./lib/node/index.js",
6
6
  "module": "./lib/node/index.mjs",
7
7
  "types": "./lib/node/index.d.ts",
@@ -0,0 +1,7 @@
1
+ import { it, expect } from 'vitest'
2
+ import { createRequestId } from './createRequestId'
3
+ import { REQUEST_ID_REGEXP } from '../test/helpers'
4
+
5
+ it('returns a request ID', () => {
6
+ expect(createRequestId()).toMatch(REQUEST_ID_REGEXP)
7
+ })
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generate a random ID string to represent a request.
3
+ * @example
4
+ * createRequestId()
5
+ * // "f774b6c9c600f"
6
+ */
7
+ export function createRequestId(): string {
8
+ return Math.random().toString(16).slice(2)
9
+ }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export * from './Interceptor'
3
3
  export * from './BatchInterceptor'
4
4
 
5
5
  /* Utils */
6
+ export { createRequestId } from './createRequestId'
6
7
  export { getCleanUrl } from './utils/getCleanUrl'
7
8
  export { encodeBuffer, decodeBuffer } from './utils/bufferUtils'
8
9
  export { isResponseWithoutBody } from './utils/responseUtils'
@@ -21,6 +21,7 @@ import { emitAsync } from '../../utils/emitAsync'
21
21
  import { getRawFetchHeaders } from '../../utils/getRawFetchHeaders'
22
22
  import { isPropertyAccessible } from '../../utils/isPropertyAccessible'
23
23
  import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'
24
+ import { createRequestId } from '../../createRequestId'
24
25
 
25
26
  export type Protocol = 'http' | 'https'
26
27
 
@@ -151,7 +152,7 @@ export class NodeClientRequest extends ClientRequest {
151
152
  end(...args: any): this {
152
153
  this.logger.info('end', args)
153
154
 
154
- const requestId = crypto.randomUUID()
155
+ const requestId = createRequestId()
155
156
 
156
157
  const [chunk, encoding, callback] = normalizeClientRequestEndArgs(...args)
157
158
  this.logger.info('normalized arguments:', { chunk, encoding, callback })
@@ -9,6 +9,7 @@ import type { WebSocketData, WebSocketTransport } from './WebSocketTransport'
9
9
  import { WebSocketEventListener } from './WebSocketOverride'
10
10
  import { bindEvent } from './utils/bindEvent'
11
11
  import { CloseEvent } from './utils/events'
12
+ import { createRequestId } from '../../createRequestId'
12
13
 
13
14
  const kEmitter = Symbol('kEmitter')
14
15
 
@@ -41,7 +42,7 @@ export class WebSocketClientConnection
41
42
  public readonly socket: WebSocket,
42
43
  private readonly transport: WebSocketTransport
43
44
  ) {
44
- this.id = crypto.randomUUID()
45
+ this.id = createRequestId()
45
46
  this.url = new URL(socket.url)
46
47
  this[kEmitter] = new EventTarget()
47
48
 
@@ -108,6 +108,19 @@ export class WebSocketServerConnection {
108
108
  // Inherit the binary type from the mock WebSocket client.
109
109
  realWebSocket.binaryType = this.socket.binaryType
110
110
 
111
+ // Allow the interceptor to listen to when the server connection
112
+ // has been established. This isn't necessary to operate with the connection
113
+ // but may be beneficial in some cases (like conditionally adding logging).
114
+ realWebSocket.addEventListener(
115
+ 'open',
116
+ (event) => {
117
+ this[kEmitter].dispatchEvent(
118
+ bindEvent(this.realWebSocket!, new Event('open', event))
119
+ )
120
+ },
121
+ { once: true }
122
+ )
123
+
111
124
  realWebSocket.addEventListener('message', (event) => {
112
125
  this.transport.onIncoming(event)
113
126
  })
@@ -215,6 +228,9 @@ export class WebSocketServerConnection {
215
228
  this.socket.url
216
229
  )
217
230
 
231
+ // Remove the "close" event listener from the server
232
+ // so it doesn't close the underlying WebSocket client
233
+ // when you call "server.close()".
218
234
  realWebSocket.removeEventListener('close', this.handleRealClose)
219
235
 
220
236
  if (
@@ -225,6 +241,13 @@ export class WebSocketServerConnection {
225
241
  }
226
242
 
227
243
  realWebSocket.close()
244
+
245
+ // Dispatch the "close" event on the server connection.
246
+ queueMicrotask(() => {
247
+ this[kEmitter].dispatchEvent(
248
+ bindEvent(this.realWebSocket, new CloseEvent('close'))
249
+ )
250
+ })
228
251
  }
229
252
 
230
253
  private handleMockClose(_event: Event): void {
@@ -4,10 +4,18 @@ export function bindEvent<E extends Event, T>(
4
4
  target: T,
5
5
  event: E
6
6
  ): EventWithTarget<E, T> {
7
- Object.defineProperty(event, 'target', {
8
- enumerable: true,
9
- writable: true,
10
- value: target,
7
+ Object.defineProperties(event, {
8
+ target: {
9
+ value: target,
10
+ enumerable: true,
11
+ writable: true,
12
+ },
13
+ currentTarget: {
14
+ value: target,
15
+ enumerable: true,
16
+ writable: true,
17
+ },
11
18
  })
19
+
12
20
  return event as EventWithTarget<E, T>
13
21
  }
@@ -13,6 +13,7 @@ import { isDomParserSupportedType } from './utils/isDomParserSupportedType'
13
13
  import { parseJson } from '../../utils/parseJson'
14
14
  import { createResponse } from './utils/createResponse'
15
15
  import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'
16
+ import { createRequestId } from '../../createRequestId'
16
17
 
17
18
  const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
18
19
  const IS_NODE = isNodeProcess()
@@ -53,7 +54,7 @@ export class XMLHttpRequestController {
53
54
  public logger: Logger
54
55
  ) {
55
56
  this.events = new Map()
56
- this.requestId = crypto.randomUUID()
57
+ this.requestId = createRequestId()
57
58
  this.requestHeaders = new Headers()
58
59
  this.responseBuffer = new Uint8Array()
59
60
 
@@ -7,6 +7,7 @@ import { toInteractiveRequest } from '../../utils/toInteractiveRequest'
7
7
  import { emitAsync } from '../../utils/emitAsync'
8
8
  import { isPropertyAccessible } from '../../utils/isPropertyAccessible'
9
9
  import { canParseUrl } from '../../utils/canParseUrl'
10
+ import { createRequestId } from '../../createRequestId'
10
11
 
11
12
  export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
12
13
  static symbol = Symbol('fetch')
@@ -31,7 +32,7 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
31
32
  )
32
33
 
33
34
  globalThis.fetch = async (input, init) => {
34
- const requestId = crypto.randomUUID()
35
+ const requestId = createRequestId()
35
36
 
36
37
  /**
37
38
  * @note Resolve potentially relative request URL
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/Interceptor.ts"],"names":["InterceptorReadyState"],"mappings":"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","sourcesContent":["import { Logger } from '@open-draft/logger'\nimport { Emitter, Listener } from 'strict-event-emitter'\n\nexport type InterceptorEventMap = Record<string, any>\nexport type InterceptorSubscription = () => void\n\n/**\n * Request header name to detect when a single request\n * is being handled by nested interceptors (XHR -> ClientRequest).\n * Obscure by design to prevent collisions with user-defined headers.\n * Ideally, come up with the Interceptor-level mechanism for this.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\nexport const INTERNAL_REQUEST_ID_HEADER_NAME =\n 'x-interceptors-internal-request-id'\n\nexport function getGlobalSymbol<V>(symbol: Symbol): V | undefined {\n return (\n // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587\n globalThis[symbol] || undefined\n )\n}\n\nfunction setGlobalSymbol(symbol: Symbol, value: any): void {\n // @ts-ignore\n globalThis[symbol] = value\n}\n\nexport function deleteGlobalSymbol(symbol: Symbol): void {\n // @ts-ignore\n delete globalThis[symbol]\n}\n\nexport enum InterceptorReadyState {\n INACTIVE = 'INACTIVE',\n APPLYING = 'APPLYING',\n APPLIED = 'APPLIED',\n DISPOSING = 'DISPOSING',\n DISPOSED = 'DISPOSED',\n}\n\nexport type ExtractEventNames<Events extends Record<string, any>> =\n Events extends Record<infer EventName, any> ? EventName : never\n\nexport class Interceptor<Events extends InterceptorEventMap> {\n protected emitter: Emitter<Events>\n protected subscriptions: Array<InterceptorSubscription>\n protected logger: Logger\n\n public readyState: InterceptorReadyState\n\n constructor(private readonly symbol: symbol) {\n this.readyState = InterceptorReadyState.INACTIVE\n\n this.emitter = new Emitter()\n this.subscriptions = []\n this.logger = new Logger(symbol.description!)\n\n // Do not limit the maximum number of listeners\n // so not to limit the maximum amount of parallel events emitted.\n this.emitter.setMaxListeners(0)\n\n this.logger.info('constructing the interceptor...')\n }\n\n /**\n * Determine if this interceptor can be applied\n * in the current environment.\n */\n protected checkEnvironment(): boolean {\n return true\n }\n\n /**\n * Apply this interceptor to the current process.\n * Returns an already running interceptor instance if it's present.\n */\n public apply(): void {\n const logger = this.logger.extend('apply')\n logger.info('applying the interceptor...')\n\n if (this.readyState === InterceptorReadyState.APPLIED) {\n logger.info('intercepted already applied!')\n return\n }\n\n const shouldApply = this.checkEnvironment()\n\n if (!shouldApply) {\n logger.info('the interceptor cannot be applied in this environment!')\n return\n }\n\n this.readyState = InterceptorReadyState.APPLYING\n\n // Whenever applying a new interceptor, check if it hasn't been applied already.\n // This enables to apply the same interceptor multiple times, for example from a different\n // interceptor, only proxying events but keeping the stubs in a single place.\n const runningInstance = this.getInstance()\n\n if (runningInstance) {\n logger.info('found a running instance, reusing...')\n\n // Proxy any listeners you set on this instance to the running instance.\n this.on = (event, listener) => {\n logger.info('proxying the \"%s\" listener', event)\n\n // Add listeners to the running instance so they appear\n // at the top of the event listeners list and are executed first.\n runningInstance.emitter.addListener(event, listener)\n\n // Ensure that once this interceptor instance is disposed,\n // it removes all listeners it has appended to the running interceptor instance.\n this.subscriptions.push(() => {\n runningInstance.emitter.removeListener(event, listener)\n logger.info('removed proxied \"%s\" listener!', event)\n })\n\n return this\n }\n\n this.readyState = InterceptorReadyState.APPLIED\n\n return\n }\n\n logger.info('no running instance found, setting up a new instance...')\n\n // Setup the interceptor.\n this.setup()\n\n // Store the newly applied interceptor instance globally.\n this.setInstance()\n\n this.readyState = InterceptorReadyState.APPLIED\n }\n\n /**\n * Setup the module augments and stubs necessary for this interceptor.\n * This method is not run if there's a running interceptor instance\n * to prevent instantiating an interceptor multiple times.\n */\n protected setup(): void {}\n\n /**\n * Listen to the interceptor's public events.\n */\n public on<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n const logger = this.logger.extend('on')\n\n if (\n this.readyState === InterceptorReadyState.DISPOSING ||\n this.readyState === InterceptorReadyState.DISPOSED\n ) {\n logger.info('cannot listen to events, already disposed!')\n return this\n }\n\n logger.info('adding \"%s\" event listener:', event, listener)\n\n this.emitter.on(event, listener)\n return this\n }\n\n public once<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n this.emitter.once(event, listener)\n return this\n }\n\n public off<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n this.emitter.off(event, listener)\n return this\n }\n\n public removeAllListeners<EventName extends ExtractEventNames<Events>>(\n event?: EventName\n ): this {\n this.emitter.removeAllListeners(event)\n return this\n }\n\n /**\n * Disposes of any side-effects this interceptor has introduced.\n */\n public dispose(): void {\n const logger = this.logger.extend('dispose')\n\n if (this.readyState === InterceptorReadyState.DISPOSED) {\n logger.info('cannot dispose, already disposed!')\n return\n }\n\n logger.info('disposing the interceptor...')\n this.readyState = InterceptorReadyState.DISPOSING\n\n if (!this.getInstance()) {\n logger.info('no interceptors running, skipping dispose...')\n return\n }\n\n // Delete the global symbol as soon as possible,\n // indicating that the interceptor is no longer running.\n this.clearInstance()\n\n logger.info('global symbol deleted:', getGlobalSymbol(this.symbol))\n\n if (this.subscriptions.length > 0) {\n logger.info('disposing of %d subscriptions...', this.subscriptions.length)\n\n for (const dispose of this.subscriptions) {\n dispose()\n }\n\n this.subscriptions = []\n\n logger.info('disposed of all subscriptions!', this.subscriptions.length)\n }\n\n this.emitter.removeAllListeners()\n logger.info('destroyed the listener!')\n\n this.readyState = InterceptorReadyState.DISPOSED\n }\n\n private getInstance(): this | undefined {\n const instance = getGlobalSymbol<this>(this.symbol)\n this.logger.info('retrieved global instance:', instance?.constructor?.name)\n return instance\n }\n\n private setInstance(): void {\n setGlobalSymbol(this.symbol, this)\n this.logger.info('set global instance!', this.symbol.description)\n }\n\n private clearInstance(): void {\n deleteGlobalSymbol(this.symbol)\n this.logger.info('cleared global instance!', this.symbol.description)\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/interceptors/fetch/index.ts","../../src/utils/isPropertyAccessible.ts","../../src/utils/canParseUrl.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { toInteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { canParseUrl } from '../../utils/canParseUrl'\n\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch !== 'undefined'\n )\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = crypto.randomUUID()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n\n this.logger.info('[%s] %s', request.method, request.url)\n\n const { interactiveRequest, requestController } =\n toInteractiveRequest(request)\n\n this.logger.info(\n 'emitting the \"request\" event for %d listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n this.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== requestId) {\n return\n }\n\n if (requestController.responsePromise.state === 'pending') {\n requestController.responsePromise.resolve(undefined)\n }\n })\n\n this.logger.info('awaiting for the mocked response...')\n\n const signal = interactiveRequest.signal\n const requestAborted = new DeferredPromise()\n\n // Signal isn't always defined in react-native.\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n requestAborted.reject(signal.reason)\n },\n { once: true }\n )\n }\n\n const resolverResult = await until(async () => {\n const listenersFinished = emitAsync(this.emitter, 'request', {\n request: interactiveRequest,\n requestId,\n })\n\n await Promise.race([\n requestAborted,\n // Put the listeners invocation Promise in the same race condition\n // with the request abort Promise because otherwise awaiting the listeners\n // would always yield some response (or undefined).\n listenersFinished,\n requestController.responsePromise,\n ])\n\n this.logger.info('all request listeners have been resolved!')\n\n const mockedResponse = await requestController.responsePromise\n this.logger.info('event.respondWith called with:', mockedResponse)\n\n return mockedResponse\n })\n\n if (requestAborted.state === 'rejected') {\n return Promise.reject(requestAborted.rejectionReason)\n }\n\n if (resolverResult.error) {\n return Promise.reject(createNetworkError(resolverResult.error))\n }\n\n const mockedResponse = resolverResult.data\n\n if (mockedResponse && !request.signal?.aborted) {\n this.logger.info('received mocked response:', mockedResponse)\n\n // Reject the request Promise on mocked \"Response.error\" responses.\n if (\n isPropertyAccessible(mockedResponse, 'type') &&\n mockedResponse.type === 'error'\n ) {\n this.logger.info(\n 'received a network error response, rejecting the request promise...'\n )\n\n /**\n * Set the cause of the request promise rejection to the\n * network error Response instance. This different from Undici.\n * Undici will forward the \"response.error\" custom property\n * as the rejection reason but for \"Response.error()\" static method\n * \"response.error\" will equal to undefined, making \"cause\" an empty Error.\n * @see https://github.com/nodejs/undici/blob/83cb522ae0157a19d149d72c7d03d46e34510d0a/lib/fetch/response.js#L344\n */\n return Promise.reject(createNetworkError(mockedResponse))\n }\n\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n const responseClone = mockedResponse.clone()\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: true,\n request: interactiveRequest,\n requestId,\n })\n\n // Set the \"response.url\" property to equal the intercepted request URL.\n Object.defineProperty(mockedResponse, 'url', {\n writable: false,\n enumerable: true,\n configurable: false,\n value: request.url,\n })\n\n return mockedResponse\n }\n\n this.logger.info('no mocked response received!')\n\n return pureFetch(request).then((response) => {\n const responseClone = response.clone()\n this.logger.info('original fetch performed', responseClone)\n\n this.emitter.emit('response', {\n response: responseClone,\n isMockedResponse: false,\n request: interactiveRequest,\n requestId,\n })\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n\nfunction createNetworkError(cause: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible<Obj extends Record<string, any>>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n"],"mappings":"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","names":["mockedResponse"]}