@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/interceptors/XMLHttpRequest/index.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts","../../src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts","../../src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts","../../src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts","../../src/interceptors/XMLHttpRequest/utils/createEvent.ts","../../src/utils/findPropertySource.ts","../../src/utils/createProxy.ts","../../src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts","../../src/utils/parseJson.ts","../../src/interceptors/XMLHttpRequest/utils/createResponse.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { InteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { Interceptor } from '../../Interceptor'\nimport { createXMLHttpRequestProxy } from './XMLHttpRequestProxy'\n\nexport type XMLHttpRequestEventListener = (args: {\n request: InteractiveRequest\n requestId: string\n}) => Promise<void> | void\n\nexport type XMLHttpRequestEmitter = Emitter<HttpRequestEventMap>\n\nexport class XMLHttpRequestInterceptor extends Interceptor<HttpRequestEventMap> {\n static interceptorSymbol = Symbol('xhr')\n\n constructor() {\n super(XMLHttpRequestInterceptor.interceptorSymbol)\n }\n\n protected checkEnvironment() {\n return typeof globalThis.XMLHttpRequest !== 'undefined'\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('patching \"XMLHttpRequest\" module...')\n\n const PureXMLHttpRequest = globalThis.XMLHttpRequest\n\n invariant(\n !(PureXMLHttpRequest as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"XMLHttpRequest\" module: already patched.'\n )\n\n globalThis.XMLHttpRequest = createXMLHttpRequestProxy({\n emitter: this.emitter,\n logger: this.logger,\n })\n\n logger.info(\n 'native \"XMLHttpRequest\" module patched!',\n globalThis.XMLHttpRequest.name\n )\n\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.XMLHttpRequest = PureXMLHttpRequest\n logger.info(\n 'native \"XMLHttpRequest\" module restored!',\n globalThis.XMLHttpRequest.name\n )\n })\n }\n}\n","import { until } from '@open-draft/until'\nimport type { Logger } from '@open-draft/logger'\nimport { XMLHttpRequestEmitter } from '.'\nimport { toInteractiveRequest } from '../../utils/toInteractiveRequest'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { XMLHttpRequestController } from './XMLHttpRequestController'\n\nexport interface XMLHttpRequestProxyOptions {\n emitter: XMLHttpRequestEmitter\n logger: Logger\n}\n\n/**\n * Create a proxied `XMLHttpRequest` class.\n * The proxied class establishes spies on certain methods,\n * allowing us to intercept requests and respond to them.\n */\nexport function createXMLHttpRequestProxy({\n emitter,\n logger,\n}: XMLHttpRequestProxyOptions) {\n const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {\n construct(target, args, newTarget) {\n logger.info('constructed new XMLHttpRequest')\n\n const originalRequest = Reflect.construct(\n target,\n args,\n newTarget\n ) as XMLHttpRequest\n\n /**\n * @note Forward prototype descriptors onto the proxied object.\n * XMLHttpRequest is implemented in JSDOM in a way that assigns\n * a bunch of descriptors, like \"set responseType()\" on the prototype.\n * With this propagation, we make sure that those descriptors trigger\n * when the user operates with the proxied request instance.\n */\n const prototypeDescriptors = Object.getOwnPropertyDescriptors(\n target.prototype\n )\n for (const propertyName in prototypeDescriptors) {\n Reflect.defineProperty(\n originalRequest,\n propertyName,\n prototypeDescriptors[propertyName]\n )\n }\n\n const xhrRequestController = new XMLHttpRequestController(\n originalRequest,\n logger\n )\n\n xhrRequestController.onRequest = async function ({ request, requestId }) {\n const { interactiveRequest, requestController } =\n toInteractiveRequest(request)\n\n this.logger.info('awaiting mocked response...')\n\n emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== requestId) {\n return\n }\n\n if (requestController.responsePromise.state === 'pending') {\n requestController.respondWith(undefined)\n }\n })\n\n const resolverResult = await until(async () => {\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n emitter.listenerCount('request')\n )\n\n await emitAsync(emitter, 'request', {\n request: interactiveRequest,\n requestId,\n })\n\n this.logger.info('all \"request\" listeners settled!')\n\n const mockedResponse = await requestController.responsePromise\n\n this.logger.info('event.respondWith called with:', mockedResponse)\n\n return mockedResponse\n })\n\n if (resolverResult.error) {\n this.logger.info(\n 'request listener threw an exception, aborting request...',\n resolverResult.error\n )\n\n /**\n * @todo Consider forwarding this error to the stderr as well\n * since not all consumers are expecting to handle errors.\n * If they don't, this error will be swallowed.\n */\n xhrRequestController.errorWith(resolverResult.error)\n return\n }\n\n const mockedResponse = resolverResult.data\n\n if (typeof mockedResponse !== 'undefined') {\n this.logger.info(\n 'received mocked response: %d %s',\n mockedResponse.status,\n mockedResponse.statusText\n )\n\n if (mockedResponse.type === 'error') {\n this.logger.info(\n 'received a network error response, rejecting the request promise...'\n )\n\n xhrRequestController.errorWith(new TypeError('Network error'))\n return\n }\n\n return xhrRequestController.respondWith(mockedResponse)\n }\n\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n }\n\n xhrRequestController.onResponse = async function ({\n response,\n isMockedResponse,\n request,\n requestId,\n }) {\n this.logger.info(\n 'emitting the \"response\" event for %s listener(s)...',\n emitter.listenerCount('response')\n )\n\n emitter.emit('response', {\n response,\n isMockedResponse,\n request,\n requestId,\n })\n }\n\n // Return the proxied request from the controller\n // so that the controller can react to the consumer's interactions\n // with this request (opening/sending/etc).\n return xhrRequestController.request\n },\n })\n\n return XMLHttpRequestProxy\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport type { Logger } from '@open-draft/logger'\nimport { concatArrayBuffer } from './utils/concatArrayBuffer'\nimport { createEvent } from './utils/createEvent'\nimport {\n decodeBuffer,\n encodeBuffer,\n toArrayBuffer,\n} from '../../utils/bufferUtils'\nimport { createProxy } from '../../utils/createProxy'\nimport { isDomParserSupportedType } from './utils/isDomParserSupportedType'\nimport { parseJson } from '../../utils/parseJson'\nimport { createResponse } from './utils/createResponse'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { createRequestId } from '../../createRequestId'\n\nconst IS_MOCKED_RESPONSE = Symbol('isMockedResponse')\nconst IS_NODE = isNodeProcess()\n\n/**\n * An `XMLHttpRequest` instance controller that allows us\n * to handle any given request instance (e.g. responding to it).\n */\nexport class XMLHttpRequestController {\n public request: XMLHttpRequest\n public requestId: string\n public onRequest?: (\n this: XMLHttpRequestController,\n args: {\n request: Request\n requestId: string\n }\n ) => Promise<void>\n public onResponse?: (\n this: XMLHttpRequestController,\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ) => void\n\n private method: string = 'GET'\n private url: URL = null as any\n private requestHeaders: Headers\n private requestBody?: XMLHttpRequestBodyInit | Document | null\n private responseBuffer: Uint8Array\n private events: Map<keyof XMLHttpRequestEventTargetEventMap, Array<Function>>\n\n constructor(\n readonly initialRequest: XMLHttpRequest,\n public logger: Logger\n ) {\n this.events = new Map()\n this.requestId = createRequestId()\n this.requestHeaders = new Headers()\n this.responseBuffer = new Uint8Array()\n\n this.request = createProxy(initialRequest, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'ontimeout': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n /**\n * @note Proxy callbacks to event listeners because JSDOM has trouble\n * translating these properties to callbacks. It seemed to be operating\n * on events exclusively.\n */\n this.request.addEventListener(eventName, nextValue as any)\n\n return invoke()\n }\n\n default: {\n return invoke()\n }\n }\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'open': {\n const [method, url] = args as [string, string | undefined]\n\n if (typeof url === 'undefined') {\n this.method = 'GET'\n this.url = toAbsoluteUrl(method)\n } else {\n this.method = method\n this.url = toAbsoluteUrl(url)\n }\n\n this.logger = this.logger.extend(`${this.method} ${this.url.href}`)\n this.logger.info('open', this.method, this.url.href)\n\n return invoke()\n }\n\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function,\n ]\n\n this.registerEvent(eventName, listener)\n this.logger.info('addEventListener', eventName, listener)\n\n return invoke()\n }\n\n case 'setRequestHeader': {\n const [name, value] = args as [string, string]\n this.requestHeaders.set(name, value)\n\n this.logger.info('setRequestHeader', name, value)\n\n return invoke()\n }\n\n case 'send': {\n const [body] = args as [\n body?: XMLHttpRequestBodyInit | Document | null,\n ]\n\n if (body != null) {\n this.requestBody =\n typeof body === 'string' ? encodeBuffer(body) : body\n }\n\n this.request.addEventListener('load', () => {\n if (typeof this.onResponse !== 'undefined') {\n // Create a Fetch API Response representation of whichever\n // response this XMLHttpRequest received. Note those may\n // be either a mocked and the original response.\n const fetchResponse = createResponse(\n this.request,\n /**\n * The `response` property is the right way to read\n * the ambiguous response body, as the request's \"responseType\" may differ.\n * @see https://xhr.spec.whatwg.org/#the-response-attribute\n */\n this.request.response\n )\n\n // Notify the consumer about the response.\n this.onResponse.call(this, {\n response: fetchResponse,\n isMockedResponse: IS_MOCKED_RESPONSE in this.request,\n request: fetchRequest,\n requestId: this.requestId!,\n })\n }\n })\n\n // Delegate request handling to the consumer.\n const fetchRequest = this.toFetchApiRequest()\n const onceRequestSettled =\n this.onRequest?.call(this, {\n request: fetchRequest,\n requestId: this.requestId!,\n }) || Promise.resolve()\n\n onceRequestSettled.finally(() => {\n // If the consumer didn't handle the request perform it as-is.\n // Note that the request may not yet be DONE and may, in fact,\n // be LOADING while the \"respondWith\" method does its magic.\n if (this.request.readyState < this.request.LOADING) {\n this.logger.info(\n 'request callback settled but request has not been handled (readystate %d), performing as-is...',\n this.request.readyState\n )\n\n /**\n * @note Set the intercepted request ID on the original request in Node.js\n * so that if it triggers any other interceptors, they don't attempt\n * to process it once again.\n *\n * For instance, XMLHttpRequest is often implemented via \"http.ClientRequest\"\n * and we don't want for both XHR and ClientRequest interceptors to\n * handle the same request at the same time (e.g. emit the \"response\" event twice).\n */\n if (IS_NODE) {\n this.request.setRequestHeader(\n INTERNAL_REQUEST_ID_HEADER_NAME,\n this.requestId!\n )\n }\n\n return invoke()\n }\n })\n\n break\n }\n\n default: {\n return invoke()\n }\n }\n },\n })\n }\n\n private registerEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.events.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.events.set(eventName, nextEvents)\n\n this.logger.info('registered event \"%s\"', eventName, listener)\n }\n\n /**\n * Responds to the current request with the given\n * Fetch API `Response` instance.\n */\n public respondWith(response: Response): void {\n this.logger.info(\n 'responding with a mocked response: %d %s',\n response.status,\n response.statusText\n )\n\n /**\n * @note Since `XMLHttpRequestController` delegates the handling of the responses\n * to the \"load\" event listener that doesn't distinguish between the mocked and original\n * responses, mark the request that had a mocked response with a corresponding symbol.\n */\n define(this.request, IS_MOCKED_RESPONSE, true)\n\n define(this.request, 'status', response.status)\n define(this.request, 'statusText', response.statusText)\n define(this.request, 'responseURL', this.url.href)\n\n this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {\n apply: (_, __, args: [name: string]) => {\n this.logger.info('getResponseHeader', args[0])\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning null')\n\n // Headers not received yet, nothing to return.\n return null\n }\n\n const headerValue = response.headers.get(args[0])\n this.logger.info(\n 'resolved response header \"%s\" to',\n args[0],\n headerValue\n )\n\n return headerValue\n },\n })\n\n this.request.getAllResponseHeaders = new Proxy(\n this.request.getAllResponseHeaders,\n {\n apply: () => {\n this.logger.info('getAllResponseHeaders')\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning empty string')\n\n // Headers not received yet, nothing to return.\n return ''\n }\n\n const headersList = Array.from(response.headers.entries())\n const allHeaders = headersList\n .map(([headerName, headerValue]) => {\n return `${headerName}: ${headerValue}`\n })\n .join('\\r\\n')\n\n this.logger.info('resolved all response headers to', allHeaders)\n\n return allHeaders\n },\n }\n )\n\n // Update the response getters to resolve against the mocked response.\n Object.defineProperties(this.request, {\n response: {\n enumerable: true,\n configurable: false,\n get: () => this.response,\n },\n responseText: {\n enumerable: true,\n configurable: false,\n get: () => this.responseText,\n },\n responseXML: {\n enumerable: true,\n configurable: false,\n get: () => this.responseXML,\n },\n })\n\n const totalResponseBodyLength = response.headers.has('Content-Length')\n ? Number(response.headers.get('Content-Length'))\n : /**\n * @todo Infer the response body length from the response body.\n */\n undefined\n\n this.logger.info('calculated response body length', totalResponseBodyLength)\n\n this.trigger('loadstart', {\n loaded: 0,\n total: totalResponseBodyLength,\n })\n\n this.setReadyState(this.request.HEADERS_RECEIVED)\n this.setReadyState(this.request.LOADING)\n\n const finalizeResponse = () => {\n this.logger.info('finalizing the mocked response...')\n\n this.setReadyState(this.request.DONE)\n\n this.trigger('load', {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n\n this.trigger('loadend', {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n if (response.body) {\n this.logger.info('mocked response has body, streaming...')\n\n const reader = response.body.getReader()\n\n const readNextResponseBodyChunk = async () => {\n const { value, done } = await reader.read()\n\n if (done) {\n this.logger.info('response body stream done!')\n finalizeResponse()\n return\n }\n\n if (value) {\n this.logger.info('read response body chunk:', value)\n this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)\n\n this.trigger('progress', {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n readNextResponseBodyChunk()\n }\n\n readNextResponseBodyChunk()\n } else {\n finalizeResponse()\n }\n }\n\n private responseBufferToText(): string {\n return decodeBuffer(this.responseBuffer)\n }\n\n get response(): unknown {\n this.logger.info(\n 'getResponse (responseType: %s)',\n this.request.responseType\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n switch (this.request.responseType) {\n case 'json': {\n const responseJson = parseJson(this.responseBufferToText())\n this.logger.info('resolved response JSON', responseJson)\n\n return responseJson\n }\n\n case 'arraybuffer': {\n const arrayBuffer = toArrayBuffer(this.responseBuffer)\n this.logger.info('resolved response ArrayBuffer', arrayBuffer)\n\n return arrayBuffer\n }\n\n case 'blob': {\n const mimeType =\n this.request.getResponseHeader('Content-Type') || 'text/plain'\n const responseBlob = new Blob([this.responseBufferToText()], {\n type: mimeType,\n })\n\n this.logger.info(\n 'resolved response Blob (mime type: %s)',\n responseBlob,\n mimeType\n )\n\n return responseBlob\n }\n\n default: {\n const responseText = this.responseBufferToText()\n this.logger.info(\n 'resolving \"%s\" response type as text',\n this.request.responseType,\n responseText\n )\n\n return responseText\n }\n }\n }\n\n get responseText(): string {\n /**\n * Throw when trying to read the response body as text when the\n * \"responseType\" doesn't expect text. This just respects the spec better.\n * @see https://xhr.spec.whatwg.org/#the-responsetext-attribute\n */\n invariant(\n this.request.responseType === '' || this.request.responseType === 'text',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (\n this.request.readyState !== this.request.LOADING &&\n this.request.readyState !== this.request.DONE\n ) {\n return ''\n }\n\n const responseText = this.responseBufferToText()\n this.logger.info('getResponseText: \"%s\"', responseText)\n\n return responseText\n }\n\n get responseXML(): Document | null {\n invariant(\n this.request.responseType === '' ||\n this.request.responseType === 'document',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n const contentType = this.request.getResponseHeader('Content-Type') || ''\n\n if (typeof DOMParser === 'undefined') {\n console.warn(\n 'Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.'\n )\n return null\n }\n\n if (isDomParserSupportedType(contentType)) {\n return new DOMParser().parseFromString(\n this.responseBufferToText(),\n contentType\n )\n }\n\n return null\n }\n\n public errorWith(error: Error): void {\n this.logger.info('responding with an error')\n\n this.setReadyState(this.request.DONE)\n this.trigger('error')\n this.trigger('loadend')\n }\n\n /**\n * Transitions this request's `readyState` to the given one.\n */\n private setReadyState(nextReadyState: number): void {\n this.logger.info(\n 'setReadyState: %d -> %d',\n this.request.readyState,\n nextReadyState\n )\n\n if (this.request.readyState === nextReadyState) {\n this.logger.info('ready state identical, skipping transition...')\n return\n }\n\n define(this.request, 'readyState', nextReadyState)\n\n this.logger.info('set readyState to: %d', nextReadyState)\n\n if (nextReadyState !== this.request.UNSENT) {\n this.logger.info('triggerring \"readystatechange\" event...')\n\n this.trigger('readystatechange')\n }\n }\n\n /**\n * Triggers given event on the `XMLHttpRequest` instance.\n */\n private trigger<\n EventName extends keyof (XMLHttpRequestEventTargetEventMap & {\n readystatechange: ProgressEvent<XMLHttpRequestEventTarget>\n }),\n >(eventName: EventName, options?: ProgressEventInit): void {\n const callback = this.request[`on${eventName}`]\n const event = createEvent(this.request, eventName, options)\n\n this.logger.info('trigger \"%s\"', eventName, options || '')\n\n // Invoke direct callbacks.\n if (typeof callback === 'function') {\n this.logger.info('found a direct \"%s\" callback, calling...', eventName)\n callback.call(this.request, event)\n }\n\n // Invoke event listeners.\n for (const [registeredEventName, listeners] of this.events) {\n if (registeredEventName === eventName) {\n this.logger.info(\n 'found %d listener(s) for \"%s\" event, calling...',\n listeners.length,\n eventName\n )\n\n listeners.forEach((listener) => listener.call(this.request, event))\n }\n }\n }\n\n /**\n * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance.\n */\n public toFetchApiRequest(): Request {\n this.logger.info('converting request to a Fetch API Request...')\n\n const fetchRequest = new Request(this.url.href, {\n method: this.method,\n headers: this.requestHeaders,\n /**\n * @see https://xhr.spec.whatwg.org/#cross-origin-credentials\n */\n credentials: this.request.withCredentials ? 'include' : 'same-origin',\n body: ['GET', 'HEAD'].includes(this.method)\n ? null\n : (this.requestBody as BodyInit),\n })\n\n const proxyHeaders = createProxy(fetchRequest.headers, {\n methodCall: ([methodName, args], invoke) => {\n // Forward the latest state of the internal request headers\n // because the interceptor might have modified them\n // without responding to the request.\n switch (methodName) {\n case 'append':\n case 'set': {\n const [headerName, headerValue] = args as [string, string]\n this.request.setRequestHeader(headerName, headerValue)\n break\n }\n\n case 'delete': {\n const [headerName] = args as [string]\n console.warn(\n `XMLHttpRequest: Cannot remove a \"${headerName}\" header from the Fetch API representation of the \"${fetchRequest.method} ${fetchRequest.url}\" request. XMLHttpRequest headers cannot be removed.`\n )\n break\n }\n }\n\n return invoke()\n },\n })\n define(fetchRequest, 'headers', proxyHeaders)\n\n this.logger.info('converted request to a Fetch API Request!', fetchRequest)\n\n return fetchRequest\n }\n}\n\nfunction toAbsoluteUrl(url: string | URL): URL {\n /**\n * @note XMLHttpRequest interceptor may run in environments\n * that implement XMLHttpRequest but don't implement \"location\"\n * (for example, React Native). If that's the case, return the\n * input URL as-is (nothing to be relative to).\n * @see https://github.com/mswjs/msw/issues/1777\n */\n if (typeof location === 'undefined') {\n return new URL(url)\n }\n\n return new URL(url.toString(), location.href)\n}\n\nfunction define(\n target: object,\n property: string | symbol,\n value: unknown\n): void {\n Reflect.defineProperty(target, property, {\n // Ensure writable properties to allow redefining readonly properties.\n writable: true,\n enumerable: true,\n value,\n })\n}\n","/**\n * Concatenate two `Uint8Array` buffers.\n */\nexport function concatArrayBuffer(\n left: Uint8Array,\n right: Uint8Array\n): Uint8Array {\n const result = new Uint8Array(left.byteLength + right.byteLength)\n result.set(left, 0)\n result.set(right, left.byteLength)\n return result\n}\n","export class EventPolyfill implements Event {\n readonly AT_TARGET: number = 0\n readonly BUBBLING_PHASE: number = 0\n readonly CAPTURING_PHASE: number = 0\n readonly NONE: number = 0\n\n public type: string = ''\n public srcElement: EventTarget | null = null\n public target: EventTarget | null\n public currentTarget: EventTarget | null = null\n public eventPhase: number = 0\n public timeStamp: number\n public isTrusted: boolean = true\n public composed: boolean = false\n public cancelable: boolean = true\n public defaultPrevented: boolean = false\n public bubbles: boolean = true\n public lengthComputable: boolean = true\n public loaded: number = 0\n public total: number = 0\n\n cancelBubble: boolean = false\n returnValue: boolean = true\n\n constructor(\n type: string,\n options?: { target: EventTarget; currentTarget: EventTarget }\n ) {\n this.type = type\n this.target = options?.target || null\n this.currentTarget = options?.currentTarget || null\n this.timeStamp = Date.now()\n }\n\n public composedPath(): EventTarget[] {\n return []\n }\n\n public initEvent(type: string, bubbles?: boolean, cancelable?: boolean) {\n this.type = type\n this.bubbles = !!bubbles\n this.cancelable = !!cancelable\n }\n\n public preventDefault() {\n this.defaultPrevented = true\n }\n\n public stopPropagation() {}\n public stopImmediatePropagation() {}\n}\n","import { EventPolyfill } from './EventPolyfill'\n\nexport class ProgressEventPolyfill extends EventPolyfill {\n readonly lengthComputable: boolean\n readonly composed: boolean\n readonly loaded: number\n readonly total: number\n\n constructor(type: string, init?: ProgressEventInit) {\n super(type)\n\n this.lengthComputable = init?.lengthComputable || false\n this.composed = init?.composed || false\n this.loaded = init?.loaded || 0\n this.total = init?.total || 0\n }\n}\n","import { EventPolyfill } from '../polyfills/EventPolyfill'\nimport { ProgressEventPolyfill } from '../polyfills/ProgressEventPolyfill'\n\nconst SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== 'undefined'\n\nexport function createEvent(\n target: XMLHttpRequest,\n type: string,\n init?: ProgressEventInit\n): EventPolyfill {\n const progressEvents = [\n 'error',\n 'progress',\n 'loadstart',\n 'loadend',\n 'load',\n 'timeout',\n 'abort',\n ]\n\n /**\n * `ProgressEvent` is not supported in React Native.\n * @see https://github.com/mswjs/interceptors/issues/40\n */\n const ProgressEventClass = SUPPORTS_PROGRESS_EVENT\n ? ProgressEvent\n : ProgressEventPolyfill\n\n const event = progressEvents.includes(type)\n ? new ProgressEventClass(type, {\n lengthComputable: true,\n loaded: init?.loaded || 0,\n total: init?.total || 0,\n })\n : new EventPolyfill(type, {\n target,\n currentTarget: target,\n })\n\n return event\n}\n","/**\n * Returns the source object of the given property on the target object\n * (the target itself, any parent in its prototype, or null).\n */\nexport function findPropertySource(\n target: object,\n propertyName: string | symbol\n): object | null {\n if (!(propertyName in target)) {\n return null\n }\n\n const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)\n if (hasProperty) {\n return target\n }\n\n const prototype = Reflect.getPrototypeOf(target)\n return prototype ? findPropertySource(prototype, propertyName) : null\n}\n","import { findPropertySource } from './findPropertySource'\n\nexport interface ProxyOptions<Target extends Record<string, any>> {\n constructorCall?(args: Array<unknown>, next: NextFunction<Target>): Target\n\n methodCall?<F extends keyof Target>(\n this: Target,\n data: [methodName: F, args: Array<unknown>],\n next: NextFunction<void>\n ): void\n\n setProperty?(\n data: [propertyName: string | symbol, nextValue: unknown],\n next: NextFunction<boolean>\n ): boolean\n\n getProperty?(\n data: [propertyName: string | symbol, receiver: Target],\n next: NextFunction<void>\n ): void\n}\n\nexport type NextFunction<ReturnType> = () => ReturnType\n\nexport function createProxy<Target extends object>(\n target: Target,\n options: ProxyOptions<Target>\n): Target {\n const proxy = new Proxy(target, optionsToProxyHandler(options))\n\n return proxy\n}\n\nfunction optionsToProxyHandler<T extends Record<string, any>>(\n options: ProxyOptions<T>\n): ProxyHandler<T> {\n const { constructorCall, methodCall, getProperty, setProperty } = options\n const handler: ProxyHandler<T> = {}\n\n if (typeof constructorCall !== 'undefined') {\n handler.construct = function (target, args, newTarget) {\n const next = Reflect.construct.bind(null, target as any, args, newTarget)\n return constructorCall.call(newTarget, args, next)\n }\n }\n\n handler.set = function (target, propertyName, nextValue) {\n const next = () => {\n const propertySource = findPropertySource(target, propertyName) || target\n const ownDescriptors = Reflect.getOwnPropertyDescriptor(\n propertySource,\n propertyName\n )\n\n // Respect any custom setters present for this property.\n if (typeof ownDescriptors?.set !== 'undefined') {\n ownDescriptors.set.apply(target, [nextValue])\n return true\n }\n\n // Otherwise, set the property on the source.\n return Reflect.defineProperty(propertySource, propertyName, {\n writable: true,\n enumerable: true,\n configurable: true,\n value: nextValue,\n })\n }\n\n if (typeof setProperty !== 'undefined') {\n return setProperty.call(target, [propertyName, nextValue], next)\n }\n\n return next()\n }\n\n handler.get = function (target, propertyName, receiver) {\n /**\n * @note Using `Reflect.get()` here causes \"TypeError: Illegal invocation\".\n */\n const next = () => target[propertyName as any]\n\n const value =\n typeof getProperty !== 'undefined'\n ? getProperty.call(target, [propertyName, receiver], next)\n : next()\n\n if (typeof value === 'function') {\n return (...args: Array<any>) => {\n const next = value.bind(target, ...args)\n\n if (typeof methodCall !== 'undefined') {\n return methodCall.call(target, [propertyName as any, args], next)\n }\n\n return next()\n }\n }\n\n return value\n }\n\n return handler\n}\n","export function isDomParserSupportedType(\n type: string\n): type is DOMParserSupportedType {\n const supportedTypes: Array<DOMParserSupportedType> = [\n 'application/xhtml+xml',\n 'application/xml',\n 'image/svg+xml',\n 'text/html',\n 'text/xml',\n ]\n return supportedTypes.some((supportedType) => {\n return type.startsWith(supportedType)\n })\n}\n","/**\n * Parses a given string into JSON.\n * Gracefully handles invalid JSON by returning `null`.\n */\nexport function parseJson(data: string): Record<string, unknown> | null {\n try {\n const json = JSON.parse(data)\n return json\n } catch (_) {\n return null\n }\n}\n","import { isResponseWithoutBody } from '../../../utils/responseUtils'\n\n/**\n * Creates a Fetch API `Response` instance from the given\n * `XMLHttpRequest` instance and a response body.\n */\nexport function createResponse(\n request: XMLHttpRequest,\n body: BodyInit | null\n): Response {\n /**\n * Handle XMLHttpRequest responses that must have null as the\n * response body when represented using Fetch API Response.\n * XMLHttpRequest response will always have an empty string\n * as the \"request.response\" in those cases, resulting in an error\n * when constructing a Response instance.\n * @see https://github.com/mswjs/interceptors/issues/379\n */\n const responseBodyOrNull = isResponseWithoutBody(request.status) ? null : body\n\n return new Response(responseBodyOrNull, {\n status: request.status,\n statusText: request.statusText,\n headers: createHeadersFromXMLHttpReqestHeaders(\n request.getAllResponseHeaders()\n ),\n })\n}\n\nfunction createHeadersFromXMLHttpReqestHeaders(headersString: string): Headers {\n const headers = new Headers()\n\n const lines = headersString.split(/[\\r\\n]+/)\n for (const line of lines) {\n if (line.trim() === '') {\n continue\n }\n\n const [name, ...parts] = line.split(': ')\n const value = parts.join(': ')\n\n headers.append(name, value)\n }\n\n return headers\n}\n"],"mappings":"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","names":["invariant","next","mockedResponse","invariant"]}
@@ -25,6 +25,14 @@ declare class BatchInterceptor<InterceptorList extends ReadonlyArray<Interceptor
25
25
  removeAllListeners<EventName extends ExtractEventNames<Events>>(event?: EventName | undefined): this;
26
26
  }
27
27
 
28
+ /**
29
+ * Generate a random ID string to represent a request.
30
+ * @example
31
+ * createRequestId()
32
+ * // "f774b6c9c600f"
33
+ */
34
+ declare function createRequestId(): string;
35
+
28
36
  /**
29
37
  * Removes query parameters and hashes from a given URL.
30
38
  */
@@ -39,4 +47,4 @@ declare function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string;
39
47
  */
40
48
  declare function isResponseWithoutBody(status: number): boolean;
41
49
 
42
- export { BatchInterceptor, BatchInterceptorOptions, ExtractEventMapType, ExtractEventNames, Interceptor, decodeBuffer, encodeBuffer, getCleanUrl, isResponseWithoutBody };
50
+ export { BatchInterceptor, BatchInterceptorOptions, ExtractEventMapType, ExtractEventNames, Interceptor, createRequestId, decodeBuffer, encodeBuffer, getCleanUrl, isResponseWithoutBody };
@@ -12,10 +12,11 @@ var _chunkFZJKKO5Hjs = require('./chunk-FZJKKO5H.js');
12
12
 
13
13
 
14
14
 
15
- var _chunk3PGRU2BRjs = require('./chunk-3PGRU2BR.js');
15
+
16
+ var _chunkTIPR373Rjs = require('./chunk-TIPR373R.js');
16
17
 
17
18
  // src/BatchInterceptor.ts
18
- var BatchInterceptor = class extends _chunk3PGRU2BRjs.Interceptor {
19
+ var BatchInterceptor = class extends _chunkTIPR373Rjs.Interceptor {
19
20
  constructor(options) {
20
21
  BatchInterceptor.symbol = Symbol(options.name);
21
22
  super(BatchInterceptor.symbol);
@@ -73,5 +74,6 @@ function getCleanUrl(url, isAbsolute = true) {
73
74
 
74
75
 
75
76
 
76
- exports.BatchInterceptor = BatchInterceptor; exports.INTERNAL_REQUEST_ID_HEADER_NAME = _chunk3PGRU2BRjs.INTERNAL_REQUEST_ID_HEADER_NAME; exports.IS_PATCHED_MODULE = _chunkFZJKKO5Hjs.IS_PATCHED_MODULE; exports.Interceptor = _chunk3PGRU2BRjs.Interceptor; exports.InterceptorReadyState = _chunk3PGRU2BRjs.InterceptorReadyState; exports.decodeBuffer = _chunkOJ2CN4LSjs.decodeBuffer; exports.deleteGlobalSymbol = _chunk3PGRU2BRjs.deleteGlobalSymbol; exports.encodeBuffer = _chunkOJ2CN4LSjs.encodeBuffer; exports.getCleanUrl = getCleanUrl; exports.getGlobalSymbol = _chunk3PGRU2BRjs.getGlobalSymbol; exports.isResponseWithoutBody = _chunkOJ2CN4LSjs.isResponseWithoutBody;
77
+
78
+ exports.BatchInterceptor = BatchInterceptor; exports.INTERNAL_REQUEST_ID_HEADER_NAME = _chunkTIPR373Rjs.INTERNAL_REQUEST_ID_HEADER_NAME; exports.IS_PATCHED_MODULE = _chunkFZJKKO5Hjs.IS_PATCHED_MODULE; exports.Interceptor = _chunkTIPR373Rjs.Interceptor; exports.InterceptorReadyState = _chunkTIPR373Rjs.InterceptorReadyState; exports.createRequestId = _chunkTIPR373Rjs.createRequestId; exports.decodeBuffer = _chunkOJ2CN4LSjs.decodeBuffer; exports.deleteGlobalSymbol = _chunkTIPR373Rjs.deleteGlobalSymbol; exports.encodeBuffer = _chunkOJ2CN4LSjs.encodeBuffer; exports.getCleanUrl = getCleanUrl; exports.getGlobalSymbol = _chunkTIPR373Rjs.getGlobalSymbol; exports.isResponseWithoutBody = _chunkOJ2CN4LSjs.isResponseWithoutBody;
77
79
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/BatchInterceptor.ts","../../src/utils/getCleanUrl.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE","sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> = InterceptorList extends ReadonlyArray<infer InterceptorType>\n ? InterceptorType extends Interceptor<infer EventMap>\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray<Interceptor<any>>,\n Events extends EventMap = ExtractEventMapType<InterceptorList>\n> extends Interceptor<Events> {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions<InterceptorList>) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners<EventName extends ExtractEventNames<Events>>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n","/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"]}
1
+ {"version":3,"sources":["../../src/BatchInterceptor.ts","../../src/utils/getCleanUrl.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE","sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> = InterceptorList extends ReadonlyArray<infer InterceptorType>\n ? InterceptorType extends Interceptor<infer EventMap>\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray<Interceptor<any>>,\n Events extends EventMap = ExtractEventMapType<InterceptorList>\n> extends Interceptor<Events> {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions<InterceptorList>) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners<EventName extends ExtractEventNames<Events>>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n","/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"]}
@@ -10,9 +10,10 @@ import {
10
10
  INTERNAL_REQUEST_ID_HEADER_NAME,
11
11
  Interceptor,
12
12
  InterceptorReadyState,
13
+ createRequestId,
13
14
  deleteGlobalSymbol,
14
15
  getGlobalSymbol
15
- } from "./chunk-KHZ3VYHS.mjs";
16
+ } from "./chunk-QED3Q6Z2.mjs";
16
17
 
17
18
  // src/BatchInterceptor.ts
18
19
  var BatchInterceptor = class extends Interceptor {
@@ -67,6 +68,7 @@ export {
67
68
  IS_PATCHED_MODULE,
68
69
  Interceptor,
69
70
  InterceptorReadyState,
71
+ createRequestId,
70
72
  decodeBuffer,
71
73
  deleteGlobalSymbol,
72
74
  encodeBuffer,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/BatchInterceptor.ts","../../src/utils/getCleanUrl.ts"],"sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> = InterceptorList extends ReadonlyArray<infer InterceptorType>\n ? InterceptorType extends Interceptor<infer EventMap>\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray<Interceptor<any>>,\n Events extends EventMap = ExtractEventMapType<InterceptorList>\n> extends Interceptor<Events> {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions<InterceptorList>) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners<EventName extends ExtractEventNames<Events>>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n","/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE;","names":[]}
1
+ {"version":3,"sources":["../../src/BatchInterceptor.ts","../../src/utils/getCleanUrl.ts"],"sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray<Interceptor<any>>\n> = InterceptorList extends ReadonlyArray<infer InterceptorType>\n ? InterceptorType extends Interceptor<infer EventMap>\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray<Interceptor<any>>,\n Events extends EventMap = ExtractEventMapType<InterceptorList>\n> extends Interceptor<Events> {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions<InterceptorList>) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off<EventName extends ExtractEventNames<Events>>(\n event: EventName,\n listener: Listener<Events[EventName]>\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners<EventName extends ExtractEventNames<Events>>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n","/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE;","names":[]}
@@ -1,13 +1,21 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunk3PGRU2BRjs = require('../../chunk-3PGRU2BR.js');
3
+
4
+ var _chunkTIPR373Rjs = require('../../chunk-TIPR373R.js');
4
5
 
5
6
  // src/interceptors/WebSocket/utils/bindEvent.ts
6
7
  function bindEvent(target, event) {
7
- Object.defineProperty(event, "target", {
8
- enumerable: true,
9
- writable: true,
10
- value: target
8
+ Object.defineProperties(event, {
9
+ target: {
10
+ value: target,
11
+ enumerable: true,
12
+ writable: true
13
+ },
14
+ currentTarget: {
15
+ value: target,
16
+ enumerable: true,
17
+ writable: true
18
+ }
11
19
  });
12
20
  return event;
13
21
  }
@@ -49,7 +57,7 @@ var WebSocketClientConnection = class {
49
57
  constructor(socket, transport) {
50
58
  this.socket = socket;
51
59
  this.transport = transport;
52
- this.id = crypto.randomUUID();
60
+ this.id = _chunkTIPR373Rjs.createRequestId.call(void 0, );
53
61
  this.url = new URL(socket.url);
54
62
  this[kEmitter] = new EventTarget();
55
63
  this.transport.onOutgoing = (data) => {
@@ -309,6 +317,15 @@ var WebSocketServerConnection = class {
309
317
  );
310
318
  const realWebSocket = this.createConnection();
311
319
  realWebSocket.binaryType = this.socket.binaryType;
320
+ realWebSocket.addEventListener(
321
+ "open",
322
+ (event) => {
323
+ this[kEmitter2].dispatchEvent(
324
+ bindEvent(this.realWebSocket, new Event("open", event))
325
+ );
326
+ },
327
+ { once: true }
328
+ );
312
329
  realWebSocket.addEventListener("message", (event) => {
313
330
  this.transport.onIncoming(event);
314
331
  });
@@ -385,6 +402,11 @@ var WebSocketServerConnection = class {
385
402
  return;
386
403
  }
387
404
  realWebSocket.close();
405
+ queueMicrotask(() => {
406
+ this[kEmitter2].dispatchEvent(
407
+ bindEvent(this.realWebSocket, new CloseEvent("close"))
408
+ );
409
+ });
388
410
  }
389
411
  handleMockClose(_event) {
390
412
  if (this.realWebSocket) {
@@ -451,7 +473,7 @@ var WebSocketClassTransport = class extends WebSocketTransport {
451
473
  };
452
474
 
453
475
  // src/interceptors/WebSocket/index.ts
454
- var _WebSocketInterceptor = class extends _chunk3PGRU2BRjs.Interceptor {
476
+ var _WebSocketInterceptor = class extends _chunkTIPR373Rjs.Interceptor {
455
477
  constructor() {
456
478
  super(_WebSocketInterceptor.symbol);
457
479
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/interceptors/WebSocket/utils/bindEvent.ts","../../../../src/interceptors/WebSocket/utils/events.ts","../../../../src/interceptors/WebSocket/WebSocketClientConnection.ts","../../../../src/interceptors/WebSocket/WebSocketServerConnection.ts","../../../../src/interceptors/WebSocket/WebSocketOverride.ts","../../../../src/interceptors/WebSocket/WebSocketTransport.ts","../../../../src/interceptors/WebSocket/WebSocketClassTransport.ts","../../../../src/interceptors/WebSocket/index.ts"],"names":["invariant","kEmitter"],"mappings":"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","sourcesContent":["type EventWithTarget<E extends Event, T> = E & { target: T }\n\nexport function bindEvent<E extends Event, T>(\n target: T,\n event: E\n): EventWithTarget<E, T> {\n Object.defineProperty(event, 'target', {\n enumerable: true,\n writable: true,\n value: target,\n })\n return event as EventWithTarget<E, T>\n}\n","const kCancelable = Symbol('kCancelable')\nconst kDefaultPrevented = Symbol('kDefaultPrevented')\n\n/**\n * A `MessageEvent` superset that supports event cancellation\n * in Node.js. It's rather non-intrusive so it can be safely\n * used in the browser as well.\n *\n * @see https://github.com/nodejs/node/issues/51767\n */\nexport class CancelableMessageEvent<T = any> extends MessageEvent<T> {\n [kCancelable]: boolean;\n [kDefaultPrevented]: boolean\n\n constructor(type: string, init: MessageEventInit<T>) {\n super(type, init)\n this[kCancelable] = !!init.cancelable\n this[kDefaultPrevented] = false\n }\n\n get cancelable() {\n return this[kCancelable]\n }\n\n get defaultPrevented() {\n return this[kDefaultPrevented]\n }\n\n public preventDefault(): void {\n if (this.cancelable && !this[kDefaultPrevented]) {\n this[kDefaultPrevented] = true\n }\n }\n}\n\ninterface CloseEventInit extends EventInit {\n code?: number\n reason?: string\n wasClean?: boolean\n}\n\nexport class CloseEvent extends Event {\n public code: number\n public reason: string\n public wasClean: boolean\n\n constructor(type: string, init: CloseEventInit = {}) {\n super(type, init)\n this.code = init.code === undefined ? 0 : init.code\n this.reason = init.reason === undefined ? '' : init.reason\n this.wasClean = init.wasClean === undefined ? false : init.wasClean\n }\n}\n","/**\n * WebSocket client class.\n * This represents an incoming WebSocket client connection.\n * @note Keep this class implementation-agnostic because it's\n * meant to be used over any WebSocket implementation\n * (not all of them follow the one from WHATWG).\n */\nimport type { WebSocketData, WebSocketTransport } from './WebSocketTransport'\nimport { WebSocketEventListener } from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\n\nconst kEmitter = Symbol('kEmitter')\n\ninterface WebSocketClientEventMap {\n message: MessageEvent<WebSocketData>\n close: CloseEvent\n}\n\nexport interface WebSocketClientConnectionProtocol {\n id: string\n url: URL\n send(data: WebSocketData): void\n close(code?: number, reason?: string): void\n}\n\n/**\n * The WebSocket client instance represents an incoming\n * client connection. The user can control the connection,\n * send and receive events.\n */\nexport class WebSocketClientConnection\n implements WebSocketClientConnectionProtocol\n{\n public readonly id: string\n public readonly url: URL\n\n private [kEmitter]: EventTarget\n\n constructor(\n public readonly socket: WebSocket,\n private readonly transport: WebSocketTransport\n ) {\n this.id = crypto.randomUUID()\n this.url = new URL(socket.url)\n this[kEmitter] = new EventTarget()\n\n // Emit outgoing client data (\"ws.send()\") as \"message\"\n // events on the client connection.\n this.transport.onOutgoing = (data) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.socket, new MessageEvent('message', { data }))\n )\n }\n\n this.transport.onClose = (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.socket, new CloseEvent('close', event))\n )\n }\n }\n\n /**\n * Listen for the outgoing events from the connected WebSocket client.\n */\n public addEventListener<EventType extends keyof WebSocketClientEventMap>(\n type: EventType,\n listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,\n options?: AddEventListenerOptions | boolean\n ): void {\n this[kEmitter].addEventListener(type, listener as EventListener, options)\n }\n\n /**\n * Removes the listener for the given event.\n */\n public removeEventListener<EventType extends keyof WebSocketClientEventMap>(\n event: EventType,\n listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n listener as EventListener,\n options\n )\n }\n\n /**\n * Send data to the connected client.\n */\n public send(data: WebSocketData): void {\n this.transport.send(data)\n }\n\n /**\n * Close the WebSocket connection.\n * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1).\n * @param {string} reason A custom connection close reason.\n */\n public close(code?: number, reason?: string): void {\n this.transport.close(code, reason)\n }\n}\n","import { invariant } from 'outvariant'\nimport { kClose, WebSocketOverride } from './WebSocketOverride'\nimport type { WebSocketData } from './WebSocketTransport'\nimport type { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\n\nconst kEmitter = Symbol('kEmitter')\n\n/**\n * The WebSocket server instance represents the actual production\n * WebSocket server connection. It's idle by default but you can\n * establish it by calling `server.connect()`.\n */\nexport class WebSocketServerConnection {\n /**\n * A WebSocket instance connected to the original server.\n */\n private realWebSocket?: WebSocket\n private mockCloseController: AbortController\n private [kEmitter]: EventTarget\n\n constructor(\n private readonly socket: WebSocketOverride,\n private readonly transport: WebSocketClassTransport,\n private readonly createConnection: () => WebSocket\n ) {\n this[kEmitter] = new EventTarget()\n this.mockCloseController = new AbortController()\n\n // Handle incoming events from the actual server.\n // The (mock) WebSocket instance will call this\n // whenever a \"message\" event from the actual server\n // is dispatched on it (the dispatch will be skipped).\n this.transport.onIncoming = (event) => {\n // Clone the event to dispatch it on this class\n // once again and prevent the \"already being dispatched\"\n // exception. Clone it here so we can observe this event\n // being prevented in the \"server.on()\" listeners.\n const messageEvent = bindEvent(\n this.realWebSocket!,\n new CancelableMessageEvent('message', {\n data: event.data,\n origin: event.origin,\n cancelable: true,\n })\n )\n\n /**\n * @note Emit \"message\" event on the WebSocketClassServer\n * instance to let the interceptor know about these\n * incoming events from the original server. In that listener,\n * the interceptor can modify or skip the event forwarding\n * to the mock WebSocket instance.\n */\n this[kEmitter].dispatchEvent(messageEvent)\n\n /**\n * @note Forward the incoming server events to the client.\n * Preventing the default on the message event stops this.\n */\n if (!messageEvent.defaultPrevented) {\n this.socket.dispatchEvent(\n bindEvent(\n /**\n * @note Bind the forwarded original server events\n * to the mock WebSocket instance so it would\n * dispatch them straight away.\n */\n this.socket,\n // Clone the message event again to prevent\n // the \"already being dispatched\" exception.\n new MessageEvent('message', {\n data: event.data,\n origin: event.origin,\n })\n )\n )\n }\n }\n }\n\n /**\n * Server ready state.\n * Proxies the ready state of the original WebSocket instance,\n * if set. If the original connection hasn't been established,\n * defaults to `-1`.\n */\n public get readyState(): number {\n if (this.realWebSocket) {\n return this.realWebSocket.readyState\n }\n\n return -1\n }\n\n /**\n * Open connection to the original WebSocket server.\n */\n public connect(): void {\n invariant(\n !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN,\n 'Failed to call \"connect()\" on the original WebSocket instance: the connection already open'\n )\n\n const realWebSocket = this.createConnection()\n\n // Inherit the binary type from the mock WebSocket client.\n realWebSocket.binaryType = this.socket.binaryType\n\n realWebSocket.addEventListener('message', (event) => {\n this.transport.onIncoming(event)\n })\n\n // Close the original connection when the mock client closes.\n // E.g. \"client.close()\" was called.\n this.socket.addEventListener('close', this.handleMockClose.bind(this), {\n signal: this.mockCloseController.signal,\n })\n\n // Forward the \"close\" event to let the interceptor handle\n // closures initiated by the original server.\n realWebSocket.addEventListener('close', this.handleRealClose.bind(this))\n\n // Forward server errors to the WebSocket client as-is.\n // We may consider exposing them to the interceptor in the future.\n realWebSocket.addEventListener('error', () => {\n this.socket.dispatchEvent(bindEvent(this.socket, new Event('error')))\n })\n\n this.realWebSocket = realWebSocket\n }\n\n /**\n * Listen for the incoming events from the original WebSocket server.\n */\n public addEventListener<K extends keyof WebSocketEventMap>(\n event: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: AddEventListenerOptions | boolean\n ): void {\n this[kEmitter].addEventListener(\n event,\n listener.bind(this.realWebSocket!) as EventListener,\n options\n )\n }\n\n /**\n * Remove the listener for the given event.\n */\n public removeEventListener<K extends keyof WebSocketEventMap>(\n event: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n listener as EventListener,\n options\n )\n }\n\n /**\n * Send data to the original WebSocket server.\n * @example\n * server.send('hello')\n * server.send(new Blob(['hello']))\n * server.send(new TextEncoder().encode('hello'))\n */\n public send(data: WebSocketData): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to call \"server.send()\" for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.socket.url\n )\n\n // Silently ignore writes on the closed original WebSocket.\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n // Delegate the send to when the original connection is open.\n // Unlike the mock, connecting to the original server may take time\n // so we cannot call this on the next tick.\n if (realWebSocket.readyState === WebSocket.CONNECTING) {\n realWebSocket.addEventListener(\n 'open',\n () => {\n realWebSocket.send(data)\n },\n { once: true }\n )\n return\n }\n\n // Send the data to the original WebSocket server.\n realWebSocket.send(data)\n }\n\n /**\n * Close the actual server connection.\n */\n public close(): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to close server connection for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.socket.url\n )\n\n realWebSocket.removeEventListener('close', this.handleRealClose)\n\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n realWebSocket.close()\n }\n\n private handleMockClose(_event: Event): void {\n // Close the original connection if the mock client closes.\n if (this.realWebSocket) {\n this.realWebSocket.close()\n }\n }\n\n private handleRealClose(event: CloseEvent): void {\n // For closures originating from the original server,\n // remove the \"close\" listener from the mock client.\n // original close -> (?) client[kClose]() --X-> \"close\" (again).\n this.mockCloseController.abort()\n\n const closeEvent = bindEvent(\n this.realWebSocket,\n new CloseEvent('close', event)\n )\n\n this[kEmitter].dispatchEvent(closeEvent)\n\n // If the close event from the server hasn't been prevented,\n // forward the closure to the mock client.\n if (!closeEvent.defaultPrevented) {\n // Close the intercepted client forcefully to\n // allow non-configurable status codes from the server.\n // If the socket has been closed by now, no harm calling\n // this again—it will have no effect.\n this.socket[kClose](event.code, event.reason)\n }\n }\n}\n","import { invariant } from 'outvariant'\nimport type { WebSocketData } from './WebSocketTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\n\nexport type WebSocketEventListener<\n T extends WebSocketEventMap[keyof WebSocketEventMap] = Event,\n> = (this: WebSocket, event: T) => void\n\nconst WEBSOCKET_CLOSE_CODE_RANGE_ERROR =\n 'InvalidAccessError: close code out of user configurable range'\n\nexport const kOnSend = Symbol('kOnSend')\nexport const kClose = Symbol('kClose')\n\nexport class WebSocketOverride extends EventTarget implements WebSocket {\n static readonly CONNECTING = 0\n static readonly OPEN = 1\n static readonly CLOSING = 2\n static readonly CLOSED = 3\n readonly CONNECTING = 0\n readonly OPEN = 1\n readonly CLOSING = 2\n readonly CLOSED = 3\n\n public url: string\n public protocol: string\n public extensions: string\n public binaryType: BinaryType\n public readyState: number\n public bufferedAmount: number\n\n private _onopen: WebSocketEventListener | null = null\n private _onmessage: WebSocketEventListener<\n MessageEvent<WebSocketData>\n > | null = null\n private _onerror: WebSocketEventListener | null = null\n private _onclose: WebSocketEventListener<CloseEvent> | null = null\n\n private [kOnSend]?: (data: WebSocketData) => void\n\n constructor(url: string | URL, protocols?: string | Array<string>) {\n super()\n this.url = url.toString()\n this.protocol = ''\n this.extensions = ''\n this.binaryType = 'blob'\n this.readyState = this.CONNECTING\n this.bufferedAmount = 0\n\n Reflect.set(this, 'readyState', this.CONNECTING)\n queueMicrotask(() => {\n Reflect.set(this, 'readyState', this.OPEN)\n this.protocol = protocols ? protocols[0] : 'ws'\n\n this.dispatchEvent(bindEvent(this, new Event('open')))\n })\n }\n\n set onopen(listener: WebSocketEventListener | null) {\n this.removeEventListener('open', this._onopen)\n this._onopen = listener\n if (listener !== null) {\n this.addEventListener('open', listener)\n }\n }\n get onopen(): WebSocketEventListener | null {\n return this._onopen\n }\n\n set onmessage(\n listener: WebSocketEventListener<MessageEvent<WebSocketData>> | null\n ) {\n this.removeEventListener(\n 'message',\n this._onmessage as WebSocketEventListener\n )\n this._onmessage = listener\n if (listener !== null) {\n this.addEventListener('message', listener)\n }\n }\n get onmessage(): WebSocketEventListener<MessageEvent<WebSocketData>> | null {\n return this._onmessage\n }\n\n set onerror(listener: WebSocketEventListener | null) {\n this.removeEventListener('error', this._onerror)\n this._onerror = listener\n if (listener !== null) {\n this.addEventListener('error', listener)\n }\n }\n get onerror(): WebSocketEventListener | null {\n return this._onerror\n }\n\n set onclose(listener: WebSocketEventListener<CloseEvent> | null) {\n this.removeEventListener('close', this._onclose as WebSocketEventListener)\n this._onclose = listener\n if (listener !== null) {\n this.addEventListener('close', listener)\n }\n }\n get onclose(): WebSocketEventListener<CloseEvent> | null {\n return this._onclose\n }\n\n /**\n * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0\n */\n public send(data: WebSocketData): void {\n if (this.readyState === this.CONNECTING) {\n this.close()\n throw new DOMException('InvalidStateError')\n }\n\n // Sending when the socket is about to close\n // discards the sent data.\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n // Buffer the data to send in this even loop\n // but send it in the next.\n this.bufferedAmount += getDataSize(data)\n\n queueMicrotask(() => {\n // This is a bit optimistic but since no actual data transfer\n // is involved, all the data will be \"sent\" on the next tick.\n this.bufferedAmount = 0\n\n /**\n * @note Notify the parent about outgoing data.\n * This notifies the transport and the connection\n * listens to the outgoing data to emit the \"message\" event.\n */\n this[kOnSend]?.(data)\n })\n }\n\n public close(code: number = 1000, reason?: string): void {\n invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR)\n invariant(\n code === 1000 || (code >= 3000 && code <= 4999),\n WEBSOCKET_CLOSE_CODE_RANGE_ERROR\n )\n\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n this[kClose](code, reason)\n }\n\n private [kClose](code: number = 1000, reason?: string): void {\n this.readyState = this.CLOSING\n\n queueMicrotask(() => {\n this.readyState = this.CLOSED\n\n // Non-user-configurable close status codes\n // represent connection termination and must\n // emit the \"error\" event before closing.\n if (code > 1000 && code <= 1015) {\n this.dispatchEvent(bindEvent(this, new Event('error')))\n }\n\n this.dispatchEvent(\n bindEvent(\n this,\n new CloseEvent('close', {\n code,\n reason,\n wasClean: code === 1000,\n })\n )\n )\n\n // Remove all event listeners once the socket is closed.\n this._onopen = null\n this._onmessage = null\n this._onerror = null\n this._onclose = null\n })\n }\n\n public addEventListener<K extends keyof WebSocketEventMap>(\n type: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: unknown,\n listener: unknown,\n options?: unknown\n ): void {\n return super.addEventListener(\n type as string,\n listener as EventListener,\n options as AddEventListenerOptions\n )\n }\n\n removeEventListener<K extends keyof WebSocketEventMap>(\n type: K,\n callback: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void {\n return super.removeEventListener(type, callback, options)\n }\n}\n\nfunction getDataSize(data: WebSocketData): number {\n if (typeof data === 'string') {\n return data.length\n }\n\n if (data instanceof Blob) {\n return data.size\n }\n\n return data.byteLength\n}\n","export type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView\n\nexport type WebSocketTransportOnIncomingCallback = (\n event: MessageEvent<WebSocketData>\n) => void\n\nexport type WebSocketTransportOnOutgoingCallback = (data: WebSocketData) => void\n\nexport type WebSocketTransportOnCloseCallback = (event: CloseEvent) => void\n\nexport abstract class WebSocketTransport {\n /**\n * A callback for the incoming server events.\n * This is called when the WebSocket client receives\n * a message from the server.\n */\n abstract onIncoming: WebSocketTransportOnIncomingCallback\n\n /**\n * A callback for outgoing client events.\n * This is called when the WebSocket client sends data.\n */\n abstract onOutgoing: WebSocketTransportOnOutgoingCallback\n\n /**\n * A callback for the close client event.\n * This is called when the WebSocket client is closed.\n */\n abstract onClose: WebSocketTransportOnCloseCallback\n\n /**\n * Send the data from the server to this client.\n */\n abstract send(data: WebSocketData): void\n\n /**\n * Close the client connection.\n */\n abstract close(code?: number, reason?: string): void\n}\n","import { bindEvent } from './utils/bindEvent'\nimport {\n WebSocketData,\n WebSocketTransport,\n WebSocketTransportOnCloseCallback,\n WebSocketTransportOnIncomingCallback,\n WebSocketTransportOnOutgoingCallback,\n} from './WebSocketTransport'\nimport { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride'\n\n/**\n * Abstraction over the given mock `WebSocket` instance that allows\n * for controlling that instance (e.g. sending and receiving messages).\n */\nexport class WebSocketClassTransport extends WebSocketTransport {\n public onOutgoing: WebSocketTransportOnOutgoingCallback = () => {}\n public onIncoming: WebSocketTransportOnIncomingCallback = () => {}\n public onClose: WebSocketTransportOnCloseCallback = () => {}\n\n constructor(protected readonly socket: WebSocketOverride) {\n super()\n\n this.socket.addEventListener('close', (event) => this.onClose(event), {\n once: true,\n })\n this.socket[kOnSend] = (...args) => this.onOutgoing(...args)\n }\n\n public send(data: WebSocketData): void {\n queueMicrotask(() => {\n const message = bindEvent(\n /**\n * @note Setting this event's \"target\" to the\n * WebSocket override instance is important.\n * This way it can tell apart original incoming events\n * (must be forwarded to the transport) from the\n * mocked message events like the one below\n * (must be dispatched on the client instance).\n */\n this.socket,\n new MessageEvent('message', {\n data,\n origin: this.socket.url,\n })\n )\n\n this.socket.dispatchEvent(message)\n })\n }\n\n public close(code: number, reason?: string): void {\n /**\n * @note Call the internal close method directly\n * to allow closing the connection with the status codes\n * that are non-configurable by the user (> 1000 <= 1015).\n */\n this.socket[kClose](code, reason)\n }\n}\n","import { Interceptor } from '../../Interceptor'\nimport {\n type WebSocketClientConnectionProtocol,\n WebSocketClientConnection,\n} from './WebSocketClientConnection'\nimport { WebSocketServerConnection } from './WebSocketServerConnection'\nimport { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { WebSocketOverride } from './WebSocketOverride'\n\nexport { type WebSocketData, WebSocketTransport } from './WebSocketTransport'\nexport {\n WebSocketClientConnection,\n WebSocketClientConnectionProtocol,\n WebSocketServerConnection,\n}\n\nexport type WebSocketEventMap = {\n connection: [args: WebSocketConnectionData]\n}\n\nexport type WebSocketConnectionData = {\n /**\n * The incoming WebSocket client connection.\n */\n client: WebSocketClientConnection\n\n /**\n * The original WebSocket server connection.\n */\n server: WebSocketServerConnection\n}\n\n/**\n * Intercept the outgoing WebSocket connections created using\n * the global `WebSocket` class.\n */\nexport class WebSocketInterceptor extends Interceptor<WebSocketEventMap> {\n static symbol = Symbol('websocket')\n\n constructor() {\n super(WebSocketInterceptor.symbol)\n }\n\n protected checkEnvironment(): boolean {\n // Enable this interceptor in any environment\n // that has a global WebSocket API.\n return typeof globalThis.WebSocket !== 'undefined'\n }\n\n protected setup(): void {\n const originalWebSocket = globalThis.WebSocket\n\n const webSocketProxy = new Proxy(globalThis.WebSocket, {\n construct: (\n target,\n args: ConstructorParameters<typeof globalThis.WebSocket>,\n newTarget\n ) => {\n const [url, protocols] = args\n\n const createConnection = (): WebSocket => {\n return Reflect.construct(target, args, newTarget)\n }\n\n // All WebSocket instances are mocked and don't forward\n // any events to the original server (no connection established).\n // To forward the events, the user must use the \"server.send()\" API.\n const socket = new WebSocketOverride(url, protocols)\n const transport = new WebSocketClassTransport(socket)\n\n // Emit the \"connection\" event to the interceptor on the next tick\n // so the client can modify WebSocket options, like \"binaryType\"\n // while the connection is already pending.\n queueMicrotask(() => {\n // The \"globalThis.WebSocket\" class stands for\n // the client-side connection. Assume it's established\n // as soon as the WebSocket instance is constructed.\n this.emitter.emit('connection', {\n client: new WebSocketClientConnection(socket, transport),\n server: new WebSocketServerConnection(\n socket,\n transport,\n createConnection\n ),\n })\n })\n\n return socket\n },\n })\n\n globalThis.WebSocket = webSocketProxy\n\n this.subscriptions.push(() => {\n globalThis.WebSocket = originalWebSocket\n })\n }\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/interceptors/WebSocket/utils/bindEvent.ts","../../../../src/interceptors/WebSocket/utils/events.ts","../../../../src/interceptors/WebSocket/WebSocketClientConnection.ts","../../../../src/interceptors/WebSocket/WebSocketServerConnection.ts","../../../../src/interceptors/WebSocket/WebSocketOverride.ts","../../../../src/interceptors/WebSocket/WebSocketTransport.ts","../../../../src/interceptors/WebSocket/WebSocketClassTransport.ts","../../../../src/interceptors/WebSocket/index.ts"],"names":["invariant","kEmitter"],"mappings":"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","sourcesContent":["type EventWithTarget<E extends Event, T> = E & { target: T }\n\nexport function bindEvent<E extends Event, T>(\n target: T,\n event: E\n): EventWithTarget<E, T> {\n Object.defineProperties(event, {\n target: {\n value: target,\n enumerable: true,\n writable: true,\n },\n currentTarget: {\n value: target,\n enumerable: true,\n writable: true,\n },\n })\n\n return event as EventWithTarget<E, T>\n}\n","const kCancelable = Symbol('kCancelable')\nconst kDefaultPrevented = Symbol('kDefaultPrevented')\n\n/**\n * A `MessageEvent` superset that supports event cancellation\n * in Node.js. It's rather non-intrusive so it can be safely\n * used in the browser as well.\n *\n * @see https://github.com/nodejs/node/issues/51767\n */\nexport class CancelableMessageEvent<T = any> extends MessageEvent<T> {\n [kCancelable]: boolean;\n [kDefaultPrevented]: boolean\n\n constructor(type: string, init: MessageEventInit<T>) {\n super(type, init)\n this[kCancelable] = !!init.cancelable\n this[kDefaultPrevented] = false\n }\n\n get cancelable() {\n return this[kCancelable]\n }\n\n get defaultPrevented() {\n return this[kDefaultPrevented]\n }\n\n public preventDefault(): void {\n if (this.cancelable && !this[kDefaultPrevented]) {\n this[kDefaultPrevented] = true\n }\n }\n}\n\ninterface CloseEventInit extends EventInit {\n code?: number\n reason?: string\n wasClean?: boolean\n}\n\nexport class CloseEvent extends Event {\n public code: number\n public reason: string\n public wasClean: boolean\n\n constructor(type: string, init: CloseEventInit = {}) {\n super(type, init)\n this.code = init.code === undefined ? 0 : init.code\n this.reason = init.reason === undefined ? '' : init.reason\n this.wasClean = init.wasClean === undefined ? false : init.wasClean\n }\n}\n","/**\n * WebSocket client class.\n * This represents an incoming WebSocket client connection.\n * @note Keep this class implementation-agnostic because it's\n * meant to be used over any WebSocket implementation\n * (not all of them follow the one from WHATWG).\n */\nimport type { WebSocketData, WebSocketTransport } from './WebSocketTransport'\nimport { WebSocketEventListener } from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\nimport { createRequestId } from '../../createRequestId'\n\nconst kEmitter = Symbol('kEmitter')\n\ninterface WebSocketClientEventMap {\n message: MessageEvent<WebSocketData>\n close: CloseEvent\n}\n\nexport interface WebSocketClientConnectionProtocol {\n id: string\n url: URL\n send(data: WebSocketData): void\n close(code?: number, reason?: string): void\n}\n\n/**\n * The WebSocket client instance represents an incoming\n * client connection. The user can control the connection,\n * send and receive events.\n */\nexport class WebSocketClientConnection\n implements WebSocketClientConnectionProtocol\n{\n public readonly id: string\n public readonly url: URL\n\n private [kEmitter]: EventTarget\n\n constructor(\n public readonly socket: WebSocket,\n private readonly transport: WebSocketTransport\n ) {\n this.id = createRequestId()\n this.url = new URL(socket.url)\n this[kEmitter] = new EventTarget()\n\n // Emit outgoing client data (\"ws.send()\") as \"message\"\n // events on the client connection.\n this.transport.onOutgoing = (data) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.socket, new MessageEvent('message', { data }))\n )\n }\n\n this.transport.onClose = (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.socket, new CloseEvent('close', event))\n )\n }\n }\n\n /**\n * Listen for the outgoing events from the connected WebSocket client.\n */\n public addEventListener<EventType extends keyof WebSocketClientEventMap>(\n type: EventType,\n listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,\n options?: AddEventListenerOptions | boolean\n ): void {\n this[kEmitter].addEventListener(type, listener as EventListener, options)\n }\n\n /**\n * Removes the listener for the given event.\n */\n public removeEventListener<EventType extends keyof WebSocketClientEventMap>(\n event: EventType,\n listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n listener as EventListener,\n options\n )\n }\n\n /**\n * Send data to the connected client.\n */\n public send(data: WebSocketData): void {\n this.transport.send(data)\n }\n\n /**\n * Close the WebSocket connection.\n * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1).\n * @param {string} reason A custom connection close reason.\n */\n public close(code?: number, reason?: string): void {\n this.transport.close(code, reason)\n }\n}\n","import { invariant } from 'outvariant'\nimport { kClose, WebSocketOverride } from './WebSocketOverride'\nimport type { WebSocketData } from './WebSocketTransport'\nimport type { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\n\nconst kEmitter = Symbol('kEmitter')\n\n/**\n * The WebSocket server instance represents the actual production\n * WebSocket server connection. It's idle by default but you can\n * establish it by calling `server.connect()`.\n */\nexport class WebSocketServerConnection {\n /**\n * A WebSocket instance connected to the original server.\n */\n private realWebSocket?: WebSocket\n private mockCloseController: AbortController\n private [kEmitter]: EventTarget\n\n constructor(\n private readonly socket: WebSocketOverride,\n private readonly transport: WebSocketClassTransport,\n private readonly createConnection: () => WebSocket\n ) {\n this[kEmitter] = new EventTarget()\n this.mockCloseController = new AbortController()\n\n // Handle incoming events from the actual server.\n // The (mock) WebSocket instance will call this\n // whenever a \"message\" event from the actual server\n // is dispatched on it (the dispatch will be skipped).\n this.transport.onIncoming = (event) => {\n // Clone the event to dispatch it on this class\n // once again and prevent the \"already being dispatched\"\n // exception. Clone it here so we can observe this event\n // being prevented in the \"server.on()\" listeners.\n const messageEvent = bindEvent(\n this.realWebSocket!,\n new CancelableMessageEvent('message', {\n data: event.data,\n origin: event.origin,\n cancelable: true,\n })\n )\n\n /**\n * @note Emit \"message\" event on the WebSocketClassServer\n * instance to let the interceptor know about these\n * incoming events from the original server. In that listener,\n * the interceptor can modify or skip the event forwarding\n * to the mock WebSocket instance.\n */\n this[kEmitter].dispatchEvent(messageEvent)\n\n /**\n * @note Forward the incoming server events to the client.\n * Preventing the default on the message event stops this.\n */\n if (!messageEvent.defaultPrevented) {\n this.socket.dispatchEvent(\n bindEvent(\n /**\n * @note Bind the forwarded original server events\n * to the mock WebSocket instance so it would\n * dispatch them straight away.\n */\n this.socket,\n // Clone the message event again to prevent\n // the \"already being dispatched\" exception.\n new MessageEvent('message', {\n data: event.data,\n origin: event.origin,\n })\n )\n )\n }\n }\n }\n\n /**\n * Server ready state.\n * Proxies the ready state of the original WebSocket instance,\n * if set. If the original connection hasn't been established,\n * defaults to `-1`.\n */\n public get readyState(): number {\n if (this.realWebSocket) {\n return this.realWebSocket.readyState\n }\n\n return -1\n }\n\n /**\n * Open connection to the original WebSocket server.\n */\n public connect(): void {\n invariant(\n !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN,\n 'Failed to call \"connect()\" on the original WebSocket instance: the connection already open'\n )\n\n const realWebSocket = this.createConnection()\n\n // Inherit the binary type from the mock WebSocket client.\n realWebSocket.binaryType = this.socket.binaryType\n\n // Allow the interceptor to listen to when the server connection\n // has been established. This isn't necessary to operate with the connection\n // but may be beneficial in some cases (like conditionally adding logging).\n realWebSocket.addEventListener(\n 'open',\n (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.realWebSocket!, new Event('open', event))\n )\n },\n { once: true }\n )\n\n realWebSocket.addEventListener('message', (event) => {\n this.transport.onIncoming(event)\n })\n\n // Close the original connection when the mock client closes.\n // E.g. \"client.close()\" was called.\n this.socket.addEventListener('close', this.handleMockClose.bind(this), {\n signal: this.mockCloseController.signal,\n })\n\n // Forward the \"close\" event to let the interceptor handle\n // closures initiated by the original server.\n realWebSocket.addEventListener('close', this.handleRealClose.bind(this))\n\n // Forward server errors to the WebSocket client as-is.\n // We may consider exposing them to the interceptor in the future.\n realWebSocket.addEventListener('error', () => {\n this.socket.dispatchEvent(bindEvent(this.socket, new Event('error')))\n })\n\n this.realWebSocket = realWebSocket\n }\n\n /**\n * Listen for the incoming events from the original WebSocket server.\n */\n public addEventListener<K extends keyof WebSocketEventMap>(\n event: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: AddEventListenerOptions | boolean\n ): void {\n this[kEmitter].addEventListener(\n event,\n listener.bind(this.realWebSocket!) as EventListener,\n options\n )\n }\n\n /**\n * Remove the listener for the given event.\n */\n public removeEventListener<K extends keyof WebSocketEventMap>(\n event: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n listener as EventListener,\n options\n )\n }\n\n /**\n * Send data to the original WebSocket server.\n * @example\n * server.send('hello')\n * server.send(new Blob(['hello']))\n * server.send(new TextEncoder().encode('hello'))\n */\n public send(data: WebSocketData): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to call \"server.send()\" for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.socket.url\n )\n\n // Silently ignore writes on the closed original WebSocket.\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n // Delegate the send to when the original connection is open.\n // Unlike the mock, connecting to the original server may take time\n // so we cannot call this on the next tick.\n if (realWebSocket.readyState === WebSocket.CONNECTING) {\n realWebSocket.addEventListener(\n 'open',\n () => {\n realWebSocket.send(data)\n },\n { once: true }\n )\n return\n }\n\n // Send the data to the original WebSocket server.\n realWebSocket.send(data)\n }\n\n /**\n * Close the actual server connection.\n */\n public close(): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to close server connection for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.socket.url\n )\n\n // Remove the \"close\" event listener from the server\n // so it doesn't close the underlying WebSocket client\n // when you call \"server.close()\".\n realWebSocket.removeEventListener('close', this.handleRealClose)\n\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n realWebSocket.close()\n\n // Dispatch the \"close\" event on the server connection.\n queueMicrotask(() => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.realWebSocket, new CloseEvent('close'))\n )\n })\n }\n\n private handleMockClose(_event: Event): void {\n // Close the original connection if the mock client closes.\n if (this.realWebSocket) {\n this.realWebSocket.close()\n }\n }\n\n private handleRealClose(event: CloseEvent): void {\n // For closures originating from the original server,\n // remove the \"close\" listener from the mock client.\n // original close -> (?) client[kClose]() --X-> \"close\" (again).\n this.mockCloseController.abort()\n\n const closeEvent = bindEvent(\n this.realWebSocket,\n new CloseEvent('close', event)\n )\n\n this[kEmitter].dispatchEvent(closeEvent)\n\n // If the close event from the server hasn't been prevented,\n // forward the closure to the mock client.\n if (!closeEvent.defaultPrevented) {\n // Close the intercepted client forcefully to\n // allow non-configurable status codes from the server.\n // If the socket has been closed by now, no harm calling\n // this again—it will have no effect.\n this.socket[kClose](event.code, event.reason)\n }\n }\n}\n","import { invariant } from 'outvariant'\nimport type { WebSocketData } from './WebSocketTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\n\nexport type WebSocketEventListener<\n T extends WebSocketEventMap[keyof WebSocketEventMap] = Event,\n> = (this: WebSocket, event: T) => void\n\nconst WEBSOCKET_CLOSE_CODE_RANGE_ERROR =\n 'InvalidAccessError: close code out of user configurable range'\n\nexport const kOnSend = Symbol('kOnSend')\nexport const kClose = Symbol('kClose')\n\nexport class WebSocketOverride extends EventTarget implements WebSocket {\n static readonly CONNECTING = 0\n static readonly OPEN = 1\n static readonly CLOSING = 2\n static readonly CLOSED = 3\n readonly CONNECTING = 0\n readonly OPEN = 1\n readonly CLOSING = 2\n readonly CLOSED = 3\n\n public url: string\n public protocol: string\n public extensions: string\n public binaryType: BinaryType\n public readyState: number\n public bufferedAmount: number\n\n private _onopen: WebSocketEventListener | null = null\n private _onmessage: WebSocketEventListener<\n MessageEvent<WebSocketData>\n > | null = null\n private _onerror: WebSocketEventListener | null = null\n private _onclose: WebSocketEventListener<CloseEvent> | null = null\n\n private [kOnSend]?: (data: WebSocketData) => void\n\n constructor(url: string | URL, protocols?: string | Array<string>) {\n super()\n this.url = url.toString()\n this.protocol = ''\n this.extensions = ''\n this.binaryType = 'blob'\n this.readyState = this.CONNECTING\n this.bufferedAmount = 0\n\n Reflect.set(this, 'readyState', this.CONNECTING)\n queueMicrotask(() => {\n Reflect.set(this, 'readyState', this.OPEN)\n this.protocol = protocols ? protocols[0] : 'ws'\n\n this.dispatchEvent(bindEvent(this, new Event('open')))\n })\n }\n\n set onopen(listener: WebSocketEventListener | null) {\n this.removeEventListener('open', this._onopen)\n this._onopen = listener\n if (listener !== null) {\n this.addEventListener('open', listener)\n }\n }\n get onopen(): WebSocketEventListener | null {\n return this._onopen\n }\n\n set onmessage(\n listener: WebSocketEventListener<MessageEvent<WebSocketData>> | null\n ) {\n this.removeEventListener(\n 'message',\n this._onmessage as WebSocketEventListener\n )\n this._onmessage = listener\n if (listener !== null) {\n this.addEventListener('message', listener)\n }\n }\n get onmessage(): WebSocketEventListener<MessageEvent<WebSocketData>> | null {\n return this._onmessage\n }\n\n set onerror(listener: WebSocketEventListener | null) {\n this.removeEventListener('error', this._onerror)\n this._onerror = listener\n if (listener !== null) {\n this.addEventListener('error', listener)\n }\n }\n get onerror(): WebSocketEventListener | null {\n return this._onerror\n }\n\n set onclose(listener: WebSocketEventListener<CloseEvent> | null) {\n this.removeEventListener('close', this._onclose as WebSocketEventListener)\n this._onclose = listener\n if (listener !== null) {\n this.addEventListener('close', listener)\n }\n }\n get onclose(): WebSocketEventListener<CloseEvent> | null {\n return this._onclose\n }\n\n /**\n * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0\n */\n public send(data: WebSocketData): void {\n if (this.readyState === this.CONNECTING) {\n this.close()\n throw new DOMException('InvalidStateError')\n }\n\n // Sending when the socket is about to close\n // discards the sent data.\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n // Buffer the data to send in this even loop\n // but send it in the next.\n this.bufferedAmount += getDataSize(data)\n\n queueMicrotask(() => {\n // This is a bit optimistic but since no actual data transfer\n // is involved, all the data will be \"sent\" on the next tick.\n this.bufferedAmount = 0\n\n /**\n * @note Notify the parent about outgoing data.\n * This notifies the transport and the connection\n * listens to the outgoing data to emit the \"message\" event.\n */\n this[kOnSend]?.(data)\n })\n }\n\n public close(code: number = 1000, reason?: string): void {\n invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR)\n invariant(\n code === 1000 || (code >= 3000 && code <= 4999),\n WEBSOCKET_CLOSE_CODE_RANGE_ERROR\n )\n\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n this[kClose](code, reason)\n }\n\n private [kClose](code: number = 1000, reason?: string): void {\n this.readyState = this.CLOSING\n\n queueMicrotask(() => {\n this.readyState = this.CLOSED\n\n // Non-user-configurable close status codes\n // represent connection termination and must\n // emit the \"error\" event before closing.\n if (code > 1000 && code <= 1015) {\n this.dispatchEvent(bindEvent(this, new Event('error')))\n }\n\n this.dispatchEvent(\n bindEvent(\n this,\n new CloseEvent('close', {\n code,\n reason,\n wasClean: code === 1000,\n })\n )\n )\n\n // Remove all event listeners once the socket is closed.\n this._onopen = null\n this._onmessage = null\n this._onerror = null\n this._onclose = null\n })\n }\n\n public addEventListener<K extends keyof WebSocketEventMap>(\n type: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: unknown,\n listener: unknown,\n options?: unknown\n ): void {\n return super.addEventListener(\n type as string,\n listener as EventListener,\n options as AddEventListenerOptions\n )\n }\n\n removeEventListener<K extends keyof WebSocketEventMap>(\n type: K,\n callback: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void {\n return super.removeEventListener(type, callback, options)\n }\n}\n\nfunction getDataSize(data: WebSocketData): number {\n if (typeof data === 'string') {\n return data.length\n }\n\n if (data instanceof Blob) {\n return data.size\n }\n\n return data.byteLength\n}\n","export type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView\n\nexport type WebSocketTransportOnIncomingCallback = (\n event: MessageEvent<WebSocketData>\n) => void\n\nexport type WebSocketTransportOnOutgoingCallback = (data: WebSocketData) => void\n\nexport type WebSocketTransportOnCloseCallback = (event: CloseEvent) => void\n\nexport abstract class WebSocketTransport {\n /**\n * A callback for the incoming server events.\n * This is called when the WebSocket client receives\n * a message from the server.\n */\n abstract onIncoming: WebSocketTransportOnIncomingCallback\n\n /**\n * A callback for outgoing client events.\n * This is called when the WebSocket client sends data.\n */\n abstract onOutgoing: WebSocketTransportOnOutgoingCallback\n\n /**\n * A callback for the close client event.\n * This is called when the WebSocket client is closed.\n */\n abstract onClose: WebSocketTransportOnCloseCallback\n\n /**\n * Send the data from the server to this client.\n */\n abstract send(data: WebSocketData): void\n\n /**\n * Close the client connection.\n */\n abstract close(code?: number, reason?: string): void\n}\n","import { bindEvent } from './utils/bindEvent'\nimport {\n WebSocketData,\n WebSocketTransport,\n WebSocketTransportOnCloseCallback,\n WebSocketTransportOnIncomingCallback,\n WebSocketTransportOnOutgoingCallback,\n} from './WebSocketTransport'\nimport { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride'\n\n/**\n * Abstraction over the given mock `WebSocket` instance that allows\n * for controlling that instance (e.g. sending and receiving messages).\n */\nexport class WebSocketClassTransport extends WebSocketTransport {\n public onOutgoing: WebSocketTransportOnOutgoingCallback = () => {}\n public onIncoming: WebSocketTransportOnIncomingCallback = () => {}\n public onClose: WebSocketTransportOnCloseCallback = () => {}\n\n constructor(protected readonly socket: WebSocketOverride) {\n super()\n\n this.socket.addEventListener('close', (event) => this.onClose(event), {\n once: true,\n })\n this.socket[kOnSend] = (...args) => this.onOutgoing(...args)\n }\n\n public send(data: WebSocketData): void {\n queueMicrotask(() => {\n const message = bindEvent(\n /**\n * @note Setting this event's \"target\" to the\n * WebSocket override instance is important.\n * This way it can tell apart original incoming events\n * (must be forwarded to the transport) from the\n * mocked message events like the one below\n * (must be dispatched on the client instance).\n */\n this.socket,\n new MessageEvent('message', {\n data,\n origin: this.socket.url,\n })\n )\n\n this.socket.dispatchEvent(message)\n })\n }\n\n public close(code: number, reason?: string): void {\n /**\n * @note Call the internal close method directly\n * to allow closing the connection with the status codes\n * that are non-configurable by the user (> 1000 <= 1015).\n */\n this.socket[kClose](code, reason)\n }\n}\n","import { Interceptor } from '../../Interceptor'\nimport {\n type WebSocketClientConnectionProtocol,\n WebSocketClientConnection,\n} from './WebSocketClientConnection'\nimport { WebSocketServerConnection } from './WebSocketServerConnection'\nimport { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { WebSocketOverride } from './WebSocketOverride'\n\nexport { type WebSocketData, WebSocketTransport } from './WebSocketTransport'\nexport {\n WebSocketClientConnection,\n WebSocketClientConnectionProtocol,\n WebSocketServerConnection,\n}\n\nexport type WebSocketEventMap = {\n connection: [args: WebSocketConnectionData]\n}\n\nexport type WebSocketConnectionData = {\n /**\n * The incoming WebSocket client connection.\n */\n client: WebSocketClientConnection\n\n /**\n * The original WebSocket server connection.\n */\n server: WebSocketServerConnection\n}\n\n/**\n * Intercept the outgoing WebSocket connections created using\n * the global `WebSocket` class.\n */\nexport class WebSocketInterceptor extends Interceptor<WebSocketEventMap> {\n static symbol = Symbol('websocket')\n\n constructor() {\n super(WebSocketInterceptor.symbol)\n }\n\n protected checkEnvironment(): boolean {\n // Enable this interceptor in any environment\n // that has a global WebSocket API.\n return typeof globalThis.WebSocket !== 'undefined'\n }\n\n protected setup(): void {\n const originalWebSocket = globalThis.WebSocket\n\n const webSocketProxy = new Proxy(globalThis.WebSocket, {\n construct: (\n target,\n args: ConstructorParameters<typeof globalThis.WebSocket>,\n newTarget\n ) => {\n const [url, protocols] = args\n\n const createConnection = (): WebSocket => {\n return Reflect.construct(target, args, newTarget)\n }\n\n // All WebSocket instances are mocked and don't forward\n // any events to the original server (no connection established).\n // To forward the events, the user must use the \"server.send()\" API.\n const socket = new WebSocketOverride(url, protocols)\n const transport = new WebSocketClassTransport(socket)\n\n // Emit the \"connection\" event to the interceptor on the next tick\n // so the client can modify WebSocket options, like \"binaryType\"\n // while the connection is already pending.\n queueMicrotask(() => {\n // The \"globalThis.WebSocket\" class stands for\n // the client-side connection. Assume it's established\n // as soon as the WebSocket instance is constructed.\n this.emitter.emit('connection', {\n client: new WebSocketClientConnection(socket, transport),\n server: new WebSocketServerConnection(\n socket,\n transport,\n createConnection\n ),\n })\n })\n\n return socket\n },\n })\n\n globalThis.WebSocket = webSocketProxy\n\n this.subscriptions.push(() => {\n globalThis.WebSocket = originalWebSocket\n })\n }\n}\n"]}
@@ -1,13 +1,21 @@
1
1
  import {
2
- Interceptor
3
- } from "../../chunk-KHZ3VYHS.mjs";
2
+ Interceptor,
3
+ createRequestId
4
+ } from "../../chunk-QED3Q6Z2.mjs";
4
5
 
5
6
  // src/interceptors/WebSocket/utils/bindEvent.ts
6
7
  function bindEvent(target, event) {
7
- Object.defineProperty(event, "target", {
8
- enumerable: true,
9
- writable: true,
10
- value: target
8
+ Object.defineProperties(event, {
9
+ target: {
10
+ value: target,
11
+ enumerable: true,
12
+ writable: true
13
+ },
14
+ currentTarget: {
15
+ value: target,
16
+ enumerable: true,
17
+ writable: true
18
+ }
11
19
  });
12
20
  return event;
13
21
  }
@@ -49,7 +57,7 @@ var WebSocketClientConnection = class {
49
57
  constructor(socket, transport) {
50
58
  this.socket = socket;
51
59
  this.transport = transport;
52
- this.id = crypto.randomUUID();
60
+ this.id = createRequestId();
53
61
  this.url = new URL(socket.url);
54
62
  this[kEmitter] = new EventTarget();
55
63
  this.transport.onOutgoing = (data) => {
@@ -309,6 +317,15 @@ var WebSocketServerConnection = class {
309
317
  );
310
318
  const realWebSocket = this.createConnection();
311
319
  realWebSocket.binaryType = this.socket.binaryType;
320
+ realWebSocket.addEventListener(
321
+ "open",
322
+ (event) => {
323
+ this[kEmitter2].dispatchEvent(
324
+ bindEvent(this.realWebSocket, new Event("open", event))
325
+ );
326
+ },
327
+ { once: true }
328
+ );
312
329
  realWebSocket.addEventListener("message", (event) => {
313
330
  this.transport.onIncoming(event);
314
331
  });
@@ -385,6 +402,11 @@ var WebSocketServerConnection = class {
385
402
  return;
386
403
  }
387
404
  realWebSocket.close();
405
+ queueMicrotask(() => {
406
+ this[kEmitter2].dispatchEvent(
407
+ bindEvent(this.realWebSocket, new CloseEvent("close"))
408
+ );
409
+ });
388
410
  }
389
411
  handleMockClose(_event) {
390
412
  if (this.realWebSocket) {