@depup/mswjs__interceptors 0.41.3-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/ClientRequest/package.json +11 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +31 -0
  4. package/RemoteHttpInterceptor/package.json +11 -0
  5. package/WebSocket/package.json +12 -0
  6. package/XMLHttpRequest/package.json +12 -0
  7. package/changes.json +10 -0
  8. package/fetch/package.json +12 -0
  9. package/lib/browser/Interceptor-Deczogc8.d.cts +65 -0
  10. package/lib/browser/Interceptor-gqKgs-aF.d.mts +65 -0
  11. package/lib/browser/XMLHttpRequest-BACqefB-.cjs +761 -0
  12. package/lib/browser/XMLHttpRequest-BACqefB-.cjs.map +1 -0
  13. package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs +756 -0
  14. package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs.map +1 -0
  15. package/lib/browser/bufferUtils-BiiO6HZv.mjs +20 -0
  16. package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +1 -0
  17. package/lib/browser/bufferUtils-Uc0eRItL.cjs +38 -0
  18. package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +1 -0
  19. package/lib/browser/createRequestId-Cs4oXfa1.cjs +205 -0
  20. package/lib/browser/createRequestId-Cs4oXfa1.cjs.map +1 -0
  21. package/lib/browser/createRequestId-DQcIlohW.mjs +170 -0
  22. package/lib/browser/createRequestId-DQcIlohW.mjs.map +1 -0
  23. package/lib/browser/fetch-DdKEdDOR.mjs +248 -0
  24. package/lib/browser/fetch-DdKEdDOR.mjs.map +1 -0
  25. package/lib/browser/fetch-U3v3Y4ap.cjs +253 -0
  26. package/lib/browser/fetch-U3v3Y4ap.cjs.map +1 -0
  27. package/lib/browser/getRawRequest-BTaNLFr0.mjs +218 -0
  28. package/lib/browser/getRawRequest-BTaNLFr0.mjs.map +1 -0
  29. package/lib/browser/getRawRequest-zx8rUJL2.cjs +259 -0
  30. package/lib/browser/getRawRequest-zx8rUJL2.cjs.map +1 -0
  31. package/lib/browser/glossary-BdLS4k1H.d.cts +70 -0
  32. package/lib/browser/glossary-DYwOrogs.d.mts +70 -0
  33. package/lib/browser/handleRequest-CvX2G-Lz.cjs +189 -0
  34. package/lib/browser/handleRequest-CvX2G-Lz.cjs.map +1 -0
  35. package/lib/browser/handleRequest-D7kpTI5U.mjs +178 -0
  36. package/lib/browser/handleRequest-D7kpTI5U.mjs.map +1 -0
  37. package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs +45 -0
  38. package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs.map +1 -0
  39. package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs +33 -0
  40. package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs.map +1 -0
  41. package/lib/browser/index.cjs +70 -0
  42. package/lib/browser/index.cjs.map +1 -0
  43. package/lib/browser/index.d.cts +96 -0
  44. package/lib/browser/index.d.mts +96 -0
  45. package/lib/browser/index.mjs +56 -0
  46. package/lib/browser/index.mjs.map +1 -0
  47. package/lib/browser/interceptors/WebSocket/index.cjs +622 -0
  48. package/lib/browser/interceptors/WebSocket/index.cjs.map +1 -0
  49. package/lib/browser/interceptors/WebSocket/index.d.cts +277 -0
  50. package/lib/browser/interceptors/WebSocket/index.d.mts +277 -0
  51. package/lib/browser/interceptors/WebSocket/index.mjs +615 -0
  52. package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -0
  53. package/lib/browser/interceptors/XMLHttpRequest/index.cjs +7 -0
  54. package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +15 -0
  55. package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +15 -0
  56. package/lib/browser/interceptors/XMLHttpRequest/index.mjs +7 -0
  57. package/lib/browser/interceptors/fetch/index.cjs +6 -0
  58. package/lib/browser/interceptors/fetch/index.d.cts +13 -0
  59. package/lib/browser/interceptors/fetch/index.d.mts +13 -0
  60. package/lib/browser/interceptors/fetch/index.mjs +6 -0
  61. package/lib/browser/presets/browser.cjs +17 -0
  62. package/lib/browser/presets/browser.cjs.map +1 -0
  63. package/lib/browser/presets/browser.d.cts +12 -0
  64. package/lib/browser/presets/browser.d.mts +14 -0
  65. package/lib/browser/presets/browser.mjs +17 -0
  66. package/lib/browser/presets/browser.mjs.map +1 -0
  67. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs +31 -0
  68. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs.map +1 -0
  69. package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs +25 -0
  70. package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs.map +1 -0
  71. package/lib/node/BatchInterceptor-3LnAnLTx.cjs +49 -0
  72. package/lib/node/BatchInterceptor-3LnAnLTx.cjs.map +1 -0
  73. package/lib/node/BatchInterceptor-D7mXzHcQ.d.mts +26 -0
  74. package/lib/node/BatchInterceptor-DFaBPilf.mjs +44 -0
  75. package/lib/node/BatchInterceptor-DFaBPilf.mjs.map +1 -0
  76. package/lib/node/BatchInterceptor-D_YqR8qU.d.cts +26 -0
  77. package/lib/node/ClientRequest-2rDe54Ui.cjs +1043 -0
  78. package/lib/node/ClientRequest-2rDe54Ui.cjs.map +1 -0
  79. package/lib/node/ClientRequest-Ca8Qykuv.mjs +1034 -0
  80. package/lib/node/ClientRequest-Ca8Qykuv.mjs.map +1 -0
  81. package/lib/node/Interceptor-DEazpLJd.d.mts +133 -0
  82. package/lib/node/Interceptor-DJ2akVWI.d.cts +133 -0
  83. package/lib/node/RemoteHttpInterceptor.cjs +154 -0
  84. package/lib/node/RemoteHttpInterceptor.cjs.map +1 -0
  85. package/lib/node/RemoteHttpInterceptor.d.cts +39 -0
  86. package/lib/node/RemoteHttpInterceptor.d.mts +39 -0
  87. package/lib/node/RemoteHttpInterceptor.mjs +152 -0
  88. package/lib/node/RemoteHttpInterceptor.mjs.map +1 -0
  89. package/lib/node/XMLHttpRequest-B7kJdYYI.cjs +763 -0
  90. package/lib/node/XMLHttpRequest-B7kJdYYI.cjs.map +1 -0
  91. package/lib/node/XMLHttpRequest-C8dIZpds.mjs +757 -0
  92. package/lib/node/XMLHttpRequest-C8dIZpds.mjs.map +1 -0
  93. package/lib/node/bufferUtils-DiCTqG-7.cjs +38 -0
  94. package/lib/node/bufferUtils-DiCTqG-7.cjs.map +1 -0
  95. package/lib/node/bufferUtils-_8XfKIfX.mjs +20 -0
  96. package/lib/node/bufferUtils-_8XfKIfX.mjs.map +1 -0
  97. package/lib/node/chunk-CbDLau6x.cjs +34 -0
  98. package/lib/node/fetch-BmXpK10r.cjs +272 -0
  99. package/lib/node/fetch-BmXpK10r.cjs.map +1 -0
  100. package/lib/node/fetch-G1DVwDKG.mjs +265 -0
  101. package/lib/node/fetch-G1DVwDKG.mjs.map +1 -0
  102. package/lib/node/fetchUtils-BaY5iWXw.cjs +419 -0
  103. package/lib/node/fetchUtils-BaY5iWXw.cjs.map +1 -0
  104. package/lib/node/fetchUtils-CoU35g3M.mjs +359 -0
  105. package/lib/node/fetchUtils-CoU35g3M.mjs.map +1 -0
  106. package/lib/node/getRawRequest-BavnMWh_.cjs +36 -0
  107. package/lib/node/getRawRequest-BavnMWh_.cjs.map +1 -0
  108. package/lib/node/getRawRequest-DnwmXyOW.mjs +24 -0
  109. package/lib/node/getRawRequest-DnwmXyOW.mjs.map +1 -0
  110. package/lib/node/glossary-BLKRyLBd.cjs +12 -0
  111. package/lib/node/glossary-BLKRyLBd.cjs.map +1 -0
  112. package/lib/node/glossary-glQBRnVD.mjs +6 -0
  113. package/lib/node/glossary-glQBRnVD.mjs.map +1 -0
  114. package/lib/node/handleRequest-Bb7Y-XLw.cjs +220 -0
  115. package/lib/node/handleRequest-Bb7Y-XLw.cjs.map +1 -0
  116. package/lib/node/handleRequest-Y97UwBbF.mjs +190 -0
  117. package/lib/node/handleRequest-Y97UwBbF.mjs.map +1 -0
  118. package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs +26 -0
  119. package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs.map +1 -0
  120. package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs +20 -0
  121. package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs.map +1 -0
  122. package/lib/node/index-BMbJ8FXL.d.cts +113 -0
  123. package/lib/node/index-C0YAQ36w.d.mts +113 -0
  124. package/lib/node/index.cjs +54 -0
  125. package/lib/node/index.cjs.map +1 -0
  126. package/lib/node/index.d.cts +75 -0
  127. package/lib/node/index.d.mts +75 -0
  128. package/lib/node/index.mjs +40 -0
  129. package/lib/node/index.mjs.map +1 -0
  130. package/lib/node/interceptors/ClientRequest/index.cjs +6 -0
  131. package/lib/node/interceptors/ClientRequest/index.d.cts +2 -0
  132. package/lib/node/interceptors/ClientRequest/index.d.mts +3 -0
  133. package/lib/node/interceptors/ClientRequest/index.mjs +6 -0
  134. package/lib/node/interceptors/XMLHttpRequest/index.cjs +6 -0
  135. package/lib/node/interceptors/XMLHttpRequest/index.d.cts +14 -0
  136. package/lib/node/interceptors/XMLHttpRequest/index.d.mts +14 -0
  137. package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -0
  138. package/lib/node/interceptors/fetch/index.cjs +5 -0
  139. package/lib/node/interceptors/fetch/index.d.cts +12 -0
  140. package/lib/node/interceptors/fetch/index.d.mts +12 -0
  141. package/lib/node/interceptors/fetch/index.mjs +5 -0
  142. package/lib/node/node-DwCc6iuP.mjs +27 -0
  143. package/lib/node/node-DwCc6iuP.mjs.map +1 -0
  144. package/lib/node/node-dKdAf3tC.cjs +39 -0
  145. package/lib/node/node-dKdAf3tC.cjs.map +1 -0
  146. package/lib/node/presets/node.cjs +22 -0
  147. package/lib/node/presets/node.cjs.map +1 -0
  148. package/lib/node/presets/node.d.cts +13 -0
  149. package/lib/node/presets/node.d.mts +15 -0
  150. package/lib/node/presets/node.mjs +22 -0
  151. package/lib/node/presets/node.mjs.map +1 -0
  152. package/lib/node/utils/node/index.cjs +4 -0
  153. package/lib/node/utils/node/index.d.cts +16 -0
  154. package/lib/node/utils/node/index.d.mts +16 -0
  155. package/lib/node/utils/node/index.mjs +3 -0
  156. package/package.json +204 -0
  157. package/presets/browser/package.json +5 -0
  158. package/presets/node/package.json +11 -0
  159. package/src/BatchInterceptor.test.ts +255 -0
  160. package/src/BatchInterceptor.ts +95 -0
  161. package/src/Interceptor.test.ts +205 -0
  162. package/src/Interceptor.ts +249 -0
  163. package/src/InterceptorError.ts +7 -0
  164. package/src/RemoteHttpInterceptor.ts +251 -0
  165. package/src/RequestController.test.ts +104 -0
  166. package/src/RequestController.ts +109 -0
  167. package/src/createRequestId.test.ts +7 -0
  168. package/src/createRequestId.ts +9 -0
  169. package/src/getRawRequest.ts +21 -0
  170. package/src/glossary.ts +37 -0
  171. package/src/index.ts +15 -0
  172. package/src/interceptors/ClientRequest/MockHttpSocket.ts +724 -0
  173. package/src/interceptors/ClientRequest/agents.ts +110 -0
  174. package/src/interceptors/ClientRequest/index.test.ts +75 -0
  175. package/src/interceptors/ClientRequest/index.ts +193 -0
  176. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +54 -0
  177. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +45 -0
  178. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +427 -0
  179. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +268 -0
  180. package/src/interceptors/ClientRequest/utils/parserUtils.ts +48 -0
  181. package/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts +258 -0
  182. package/src/interceptors/ClientRequest/utils/recordRawHeaders.ts +262 -0
  183. package/src/interceptors/Socket/MockSocket.test.ts +264 -0
  184. package/src/interceptors/Socket/MockSocket.ts +58 -0
  185. package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +26 -0
  186. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +52 -0
  187. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +33 -0
  188. package/src/interceptors/WebSocket/WebSocketClassTransport.ts +116 -0
  189. package/src/interceptors/WebSocket/WebSocketClientConnection.ts +152 -0
  190. package/src/interceptors/WebSocket/WebSocketOverride.ts +252 -0
  191. package/src/interceptors/WebSocket/WebSocketServerConnection.ts +420 -0
  192. package/src/interceptors/WebSocket/WebSocketTransport.ts +39 -0
  193. package/src/interceptors/WebSocket/index.ts +191 -0
  194. package/src/interceptors/WebSocket/utils/bindEvent.test.ts +27 -0
  195. package/src/interceptors/WebSocket/utils/bindEvent.ts +21 -0
  196. package/src/interceptors/WebSocket/utils/events.test.ts +101 -0
  197. package/src/interceptors/WebSocket/utils/events.ts +94 -0
  198. package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +746 -0
  199. package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +121 -0
  200. package/src/interceptors/XMLHttpRequest/index.ts +61 -0
  201. package/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +51 -0
  202. package/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +17 -0
  203. package/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +12 -0
  204. package/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts +12 -0
  205. package/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts +26 -0
  206. package/src/interceptors/XMLHttpRequest/utils/createEvent.ts +41 -0
  207. package/src/interceptors/XMLHttpRequest/utils/createResponse.ts +49 -0
  208. package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts +164 -0
  209. package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +16 -0
  210. package/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +14 -0
  211. package/src/interceptors/fetch/index.ts +214 -0
  212. package/src/interceptors/fetch/utils/brotli-decompress.browser.ts +14 -0
  213. package/src/interceptors/fetch/utils/brotli-decompress.ts +31 -0
  214. package/src/interceptors/fetch/utils/createNetworkError.ts +5 -0
  215. package/src/interceptors/fetch/utils/decompression.ts +85 -0
  216. package/src/interceptors/fetch/utils/followRedirect.ts +114 -0
  217. package/src/presets/browser.ts +11 -0
  218. package/src/presets/node.ts +13 -0
  219. package/src/utils/bufferUtils.test.ts +21 -0
  220. package/src/utils/bufferUtils.ts +22 -0
  221. package/src/utils/canParseUrl.ts +13 -0
  222. package/src/utils/cloneObject.test.ts +94 -0
  223. package/src/utils/cloneObject.ts +36 -0
  224. package/src/utils/createProxy.test.ts +164 -0
  225. package/src/utils/createProxy.ts +104 -0
  226. package/src/utils/emitAsync.ts +25 -0
  227. package/src/utils/fetchUtils.ts +119 -0
  228. package/src/utils/findPropertySource.test.ts +27 -0
  229. package/src/utils/findPropertySource.ts +20 -0
  230. package/src/utils/getCleanUrl.test.ts +32 -0
  231. package/src/utils/getCleanUrl.ts +6 -0
  232. package/src/utils/getUrlByRequestOptions.test.ts +163 -0
  233. package/src/utils/getUrlByRequestOptions.ts +152 -0
  234. package/src/utils/getValueBySymbol.test.ts +14 -0
  235. package/src/utils/getValueBySymbol.ts +19 -0
  236. package/src/utils/handleRequest.ts +205 -0
  237. package/src/utils/hasConfigurableGlobal.test.ts +83 -0
  238. package/src/utils/hasConfigurableGlobal.ts +34 -0
  239. package/src/utils/isNodeLikeError.ts +13 -0
  240. package/src/utils/isObject.test.ts +21 -0
  241. package/src/utils/isObject.ts +8 -0
  242. package/src/utils/isPropertyAccessible.ts +19 -0
  243. package/src/utils/nextTick.ts +11 -0
  244. package/src/utils/node/index.ts +39 -0
  245. package/src/utils/parseJson.test.ts +10 -0
  246. package/src/utils/parseJson.ts +12 -0
  247. package/src/utils/resolveWebSocketUrl.ts +45 -0
  248. package/src/utils/responseUtils.ts +59 -0
@@ -0,0 +1,191 @@
1
+ import { Interceptor } from '../../Interceptor'
2
+ import {
3
+ WebSocketClientConnectionProtocol,
4
+ WebSocketClientConnection,
5
+ type WebSocketClientEventMap,
6
+ } from './WebSocketClientConnection'
7
+ import {
8
+ WebSocketServerConnectionProtocol,
9
+ WebSocketServerConnection,
10
+ type WebSocketServerEventMap,
11
+ } from './WebSocketServerConnection'
12
+ import { WebSocketClassTransport } from './WebSocketClassTransport'
13
+ import {
14
+ kClose,
15
+ kPassthroughPromise,
16
+ WebSocketOverride,
17
+ } from './WebSocketOverride'
18
+ import { bindEvent } from './utils/bindEvent'
19
+ import { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'
20
+ import { emitAsync } from '../../utils/emitAsync'
21
+
22
+ export {
23
+ type WebSocketData,
24
+ type WebSocketTransport,
25
+ } from './WebSocketTransport'
26
+ export {
27
+ WebSocketClientEventMap,
28
+ WebSocketClientConnectionProtocol,
29
+ WebSocketClientConnection,
30
+ WebSocketServerEventMap,
31
+ WebSocketServerConnectionProtocol,
32
+ WebSocketServerConnection,
33
+ }
34
+
35
+ export {
36
+ CloseEvent,
37
+ CancelableCloseEvent,
38
+ CancelableMessageEvent,
39
+ } from './utils/events'
40
+
41
+ export type WebSocketEventMap = {
42
+ connection: [args: WebSocketConnectionData]
43
+ }
44
+
45
+ export type WebSocketConnectionData = {
46
+ /**
47
+ * The incoming WebSocket client connection.
48
+ */
49
+ client: WebSocketClientConnection
50
+
51
+ /**
52
+ * The original WebSocket server connection.
53
+ */
54
+ server: WebSocketServerConnection
55
+
56
+ /**
57
+ * The connection information.
58
+ */
59
+ info: {
60
+ /**
61
+ * The protocols supported by the WebSocket client.
62
+ */
63
+ protocols: string | Array<string> | undefined
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Intercept the outgoing WebSocket connections created using
69
+ * the global `WebSocket` class.
70
+ */
71
+ export class WebSocketInterceptor extends Interceptor<WebSocketEventMap> {
72
+ static symbol = Symbol('websocket')
73
+
74
+ constructor() {
75
+ super(WebSocketInterceptor.symbol)
76
+ }
77
+
78
+ protected checkEnvironment(): boolean {
79
+ return hasConfigurableGlobal('WebSocket')
80
+ }
81
+
82
+ protected setup(): void {
83
+ const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor(
84
+ globalThis,
85
+ 'WebSocket'
86
+ )
87
+
88
+ const WebSocketProxy = new Proxy(globalThis.WebSocket, {
89
+ construct: (
90
+ target,
91
+ args: ConstructorParameters<typeof globalThis.WebSocket>,
92
+ newTarget
93
+ ) => {
94
+ const [url, protocols] = args
95
+
96
+ const createConnection = (): WebSocket => {
97
+ return Reflect.construct(target, args, newTarget)
98
+ }
99
+
100
+ // All WebSocket instances are mocked and don't forward
101
+ // any events to the original server (no connection established).
102
+ // To forward the events, the user must use the "server.send()" API.
103
+ const socket = new WebSocketOverride(url, protocols)
104
+ const transport = new WebSocketClassTransport(socket)
105
+
106
+ // Emit the "connection" event to the interceptor on the next tick
107
+ // so the client can modify WebSocket options, like "binaryType"
108
+ // while the connection is already pending.
109
+ queueMicrotask(async () => {
110
+ try {
111
+ const server = new WebSocketServerConnection(
112
+ socket,
113
+ transport,
114
+ createConnection
115
+ )
116
+
117
+ const hasConnectionListeners =
118
+ this.emitter.listenerCount('connection') > 0
119
+
120
+ // The "globalThis.WebSocket" class stands for
121
+ // the client-side connection. Assume it's established
122
+ // as soon as the WebSocket instance is constructed.
123
+ await emitAsync(this.emitter, 'connection', {
124
+ client: new WebSocketClientConnection(socket, transport),
125
+ server,
126
+ info: {
127
+ protocols,
128
+ },
129
+ })
130
+
131
+ if (hasConnectionListeners) {
132
+ socket[kPassthroughPromise].resolve(false)
133
+ } else {
134
+ socket[kPassthroughPromise].resolve(true)
135
+
136
+ server.connect()
137
+
138
+ // Forward the "open" event from the original server
139
+ // to the mock WebSocket client in the case of a passthrough connection.
140
+ server.addEventListener('open', () => {
141
+ socket.dispatchEvent(bindEvent(socket, new Event('open')))
142
+
143
+ // Forward the original connection protocol to the
144
+ // mock WebSocket client.
145
+ if (server['realWebSocket']) {
146
+ socket.protocol = server['realWebSocket'].protocol
147
+ }
148
+ })
149
+ }
150
+ } catch (error) {
151
+ /**
152
+ * @note Translate unhandled exceptions during the connection
153
+ * handling (i.e. interceptor exceptions) as WebSocket connection
154
+ * closures with error. This prevents from the exceptions occurring
155
+ * in `queueMicrotask` from being process-wide and uncatchable.
156
+ */
157
+ if (error instanceof Error) {
158
+ socket.dispatchEvent(new Event('error'))
159
+
160
+ // No need to close the connection if it's already being closed.
161
+ // E.g. the interceptor called `client.close()` and then threw an error.
162
+ if (
163
+ socket.readyState !== WebSocket.CLOSING &&
164
+ socket.readyState !== WebSocket.CLOSED
165
+ ) {
166
+ socket[kClose](1011, error.message, false)
167
+ }
168
+
169
+ console.error(error)
170
+ }
171
+ }
172
+ })
173
+
174
+ return socket
175
+ },
176
+ })
177
+
178
+ Object.defineProperty(globalThis, 'WebSocket', {
179
+ value: WebSocketProxy,
180
+ configurable: true,
181
+ })
182
+
183
+ this.subscriptions.push(() => {
184
+ Object.defineProperty(
185
+ globalThis,
186
+ 'WebSocket',
187
+ originalWebSocketDescriptor!
188
+ )
189
+ })
190
+ }
191
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @vitest-environment node
3
+ */
4
+ import { it, expect } from 'vitest'
5
+ import { bindEvent } from './bindEvent'
6
+
7
+ it('sets the "target" on the given event', () => {
8
+ class Target {}
9
+ const target = new Target()
10
+ const event = new Event('open')
11
+ bindEvent(target, event)
12
+
13
+ expect(event.type).toBe('open')
14
+ expect(event.target).toEqual(target)
15
+ })
16
+
17
+ it('overrides existing "target" on the given event', () => {
18
+ class Target {}
19
+ const oldTarget = new Target()
20
+ const newTarget = new Target()
21
+ const event = new Event('open')
22
+ bindEvent(oldTarget, event)
23
+ bindEvent(newTarget, event)
24
+
25
+ expect(event.type).toBe('open')
26
+ expect(event.target).toEqual(newTarget)
27
+ })
@@ -0,0 +1,21 @@
1
+ type EventWithTarget<E extends Event, T> = E & { target: T }
2
+
3
+ export function bindEvent<E extends Event, T>(
4
+ target: T,
5
+ event: E
6
+ ): EventWithTarget<E, T> {
7
+ Object.defineProperties(event, {
8
+ target: {
9
+ value: target,
10
+ enumerable: true,
11
+ writable: true,
12
+ },
13
+ currentTarget: {
14
+ value: target,
15
+ enumerable: true,
16
+ writable: true,
17
+ },
18
+ })
19
+
20
+ return event as EventWithTarget<E, T>
21
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @vitest-environment node
3
+ */
4
+ import { describe, it, expect } from 'vitest'
5
+ import { CancelableMessageEvent, CloseEvent } from './events'
6
+
7
+ describe(CancelableMessageEvent, () => {
8
+ it('initiates with the right defaults', () => {
9
+ const event = new CancelableMessageEvent('message', {
10
+ data: 'hello',
11
+ })
12
+
13
+ expect(event).toBeInstanceOf(MessageEvent)
14
+ expect(event.type).toBe('message')
15
+ expect(event.data).toBe('hello')
16
+ expect(event.cancelable).toBe(false)
17
+ expect(event.defaultPrevented).toBe(false)
18
+ })
19
+
20
+ it('initiates a cancelable event', () => {
21
+ const event = new CancelableMessageEvent('message', {
22
+ data: 'hello',
23
+ cancelable: true,
24
+ })
25
+
26
+ expect(event).toBeInstanceOf(MessageEvent)
27
+ expect(event.type).toBe('message')
28
+ expect(event.data).toBe('hello')
29
+ expect(event.cancelable).toBe(true)
30
+ expect(event.defaultPrevented).toBe(false)
31
+ })
32
+
33
+ it('cancels a cancelable event when calling "preventDefault()"', () => {
34
+ const event = new CancelableMessageEvent('message', {
35
+ data: 'hello',
36
+ cancelable: true,
37
+ })
38
+
39
+ expect(event.defaultPrevented).toBe(false)
40
+ event.preventDefault()
41
+ expect(event.defaultPrevented).toBe(true)
42
+ })
43
+
44
+ it('does nothing when calling "preventDefault()" on a non-cancelable event', () => {
45
+ const event = new CancelableMessageEvent('message', {
46
+ data: 'hello',
47
+ })
48
+
49
+ expect(event.defaultPrevented).toBe(false)
50
+ event.preventDefault()
51
+ expect(event.defaultPrevented).toBe(false)
52
+ })
53
+
54
+ it('supports setting the "cancelable" value directly', () => {
55
+ const event = new CancelableMessageEvent('message', {})
56
+ /**
57
+ * @note HappyDOM sets the "cancelable" and "preventDefault"
58
+ * event properties directly. That's no-op as far as I know
59
+ * but they do it and we have to account for that.
60
+ */
61
+ event.cancelable = true
62
+ expect(event.cancelable).toBe(true)
63
+ })
64
+
65
+ it('supports setting the "defaultPrevented" value directly', () => {
66
+ const event = new CancelableMessageEvent('message', {})
67
+ /**
68
+ * @note HappyDOM sets the "cancelable" and "preventDefault"
69
+ * event properties directly. That's no-op as far as I know
70
+ * but they do it and we have to account for that.
71
+ */
72
+ event.defaultPrevented = true
73
+ expect(event.defaultPrevented).toBe(true)
74
+ })
75
+ })
76
+
77
+ describe(CloseEvent, () => {
78
+ it('initiates with the right defaults', () => {
79
+ const event = new CloseEvent('close')
80
+
81
+ expect(event).toBeInstanceOf(Event)
82
+ expect(event.type).toBe('close')
83
+ expect(event.code).toBe(0)
84
+ expect(event.reason).toBe('')
85
+ expect(event.wasClean).toBe(false)
86
+ })
87
+
88
+ it('initiates with custom values', () => {
89
+ const event = new CloseEvent('close', {
90
+ code: 1003,
91
+ reason: 'close reason',
92
+ wasClean: true,
93
+ })
94
+
95
+ expect(event).toBeInstanceOf(Event)
96
+ expect(event.type).toBe('close')
97
+ expect(event.code).toBe(1003)
98
+ expect(event.reason).toBe('close reason')
99
+ expect(event.wasClean).toBe(true)
100
+ })
101
+ })
@@ -0,0 +1,94 @@
1
+ const kCancelable = Symbol('kCancelable')
2
+ const kDefaultPrevented = Symbol('kDefaultPrevented')
3
+
4
+ /**
5
+ * A `MessageEvent` superset that supports event cancellation
6
+ * in Node.js. It's rather non-intrusive so it can be safely
7
+ * used in the browser as well.
8
+ *
9
+ * @see https://github.com/nodejs/node/issues/51767
10
+ */
11
+ export class CancelableMessageEvent<T = any> extends MessageEvent<T> {
12
+ [kCancelable]: boolean;
13
+ [kDefaultPrevented]: boolean
14
+
15
+ constructor(type: string, init: MessageEventInit<T>) {
16
+ super(type, init)
17
+ this[kCancelable] = !!init.cancelable
18
+ this[kDefaultPrevented] = false
19
+ }
20
+
21
+ get cancelable() {
22
+ return this[kCancelable]
23
+ }
24
+
25
+ set cancelable(nextCancelable) {
26
+ this[kCancelable] = nextCancelable
27
+ }
28
+
29
+ get defaultPrevented() {
30
+ return this[kDefaultPrevented]
31
+ }
32
+
33
+ set defaultPrevented(nextDefaultPrevented) {
34
+ this[kDefaultPrevented] = nextDefaultPrevented
35
+ }
36
+
37
+ public preventDefault(): void {
38
+ if (this.cancelable && !this[kDefaultPrevented]) {
39
+ this[kDefaultPrevented] = true
40
+ }
41
+ }
42
+ }
43
+
44
+ interface CloseEventInit extends EventInit {
45
+ code?: number
46
+ reason?: string
47
+ wasClean?: boolean
48
+ }
49
+
50
+ export class CloseEvent extends Event {
51
+ public code: number
52
+ public reason: string
53
+ public wasClean: boolean
54
+
55
+ constructor(type: string, init: CloseEventInit = {}) {
56
+ super(type, init)
57
+ this.code = init.code === undefined ? 0 : init.code
58
+ this.reason = init.reason === undefined ? '' : init.reason
59
+ this.wasClean = init.wasClean === undefined ? false : init.wasClean
60
+ }
61
+ }
62
+
63
+ export class CancelableCloseEvent extends CloseEvent {
64
+ [kCancelable]: boolean;
65
+ [kDefaultPrevented]: boolean
66
+
67
+ constructor(type: string, init: CloseEventInit = {}) {
68
+ super(type, init)
69
+ this[kCancelable] = !!init.cancelable
70
+ this[kDefaultPrevented] = false
71
+ }
72
+
73
+ get cancelable() {
74
+ return this[kCancelable]
75
+ }
76
+
77
+ set cancelable(nextCancelable) {
78
+ this[kCancelable] = nextCancelable
79
+ }
80
+
81
+ get defaultPrevented() {
82
+ return this[kDefaultPrevented]
83
+ }
84
+
85
+ set defaultPrevented(nextDefaultPrevented) {
86
+ this[kDefaultPrevented] = nextDefaultPrevented
87
+ }
88
+
89
+ public preventDefault(): void {
90
+ if (this.cancelable && !this[kDefaultPrevented]) {
91
+ this[kDefaultPrevented] = true
92
+ }
93
+ }
94
+ }