@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.
- package/ClientRequest/package.json +11 -0
- package/LICENSE.md +9 -0
- package/README.md +31 -0
- package/RemoteHttpInterceptor/package.json +11 -0
- package/WebSocket/package.json +12 -0
- package/XMLHttpRequest/package.json +12 -0
- package/changes.json +10 -0
- package/fetch/package.json +12 -0
- package/lib/browser/Interceptor-Deczogc8.d.cts +65 -0
- package/lib/browser/Interceptor-gqKgs-aF.d.mts +65 -0
- package/lib/browser/XMLHttpRequest-BACqefB-.cjs +761 -0
- package/lib/browser/XMLHttpRequest-BACqefB-.cjs.map +1 -0
- package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs +756 -0
- package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs.map +1 -0
- package/lib/browser/bufferUtils-BiiO6HZv.mjs +20 -0
- package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +1 -0
- package/lib/browser/bufferUtils-Uc0eRItL.cjs +38 -0
- package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +1 -0
- package/lib/browser/createRequestId-Cs4oXfa1.cjs +205 -0
- package/lib/browser/createRequestId-Cs4oXfa1.cjs.map +1 -0
- package/lib/browser/createRequestId-DQcIlohW.mjs +170 -0
- package/lib/browser/createRequestId-DQcIlohW.mjs.map +1 -0
- package/lib/browser/fetch-DdKEdDOR.mjs +248 -0
- package/lib/browser/fetch-DdKEdDOR.mjs.map +1 -0
- package/lib/browser/fetch-U3v3Y4ap.cjs +253 -0
- package/lib/browser/fetch-U3v3Y4ap.cjs.map +1 -0
- package/lib/browser/getRawRequest-BTaNLFr0.mjs +218 -0
- package/lib/browser/getRawRequest-BTaNLFr0.mjs.map +1 -0
- package/lib/browser/getRawRequest-zx8rUJL2.cjs +259 -0
- package/lib/browser/getRawRequest-zx8rUJL2.cjs.map +1 -0
- package/lib/browser/glossary-BdLS4k1H.d.cts +70 -0
- package/lib/browser/glossary-DYwOrogs.d.mts +70 -0
- package/lib/browser/handleRequest-CvX2G-Lz.cjs +189 -0
- package/lib/browser/handleRequest-CvX2G-Lz.cjs.map +1 -0
- package/lib/browser/handleRequest-D7kpTI5U.mjs +178 -0
- package/lib/browser/handleRequest-D7kpTI5U.mjs.map +1 -0
- package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs +45 -0
- package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs.map +1 -0
- package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs +33 -0
- package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs.map +1 -0
- package/lib/browser/index.cjs +70 -0
- package/lib/browser/index.cjs.map +1 -0
- package/lib/browser/index.d.cts +96 -0
- package/lib/browser/index.d.mts +96 -0
- package/lib/browser/index.mjs +56 -0
- package/lib/browser/index.mjs.map +1 -0
- package/lib/browser/interceptors/WebSocket/index.cjs +622 -0
- package/lib/browser/interceptors/WebSocket/index.cjs.map +1 -0
- package/lib/browser/interceptors/WebSocket/index.d.cts +277 -0
- package/lib/browser/interceptors/WebSocket/index.d.mts +277 -0
- package/lib/browser/interceptors/WebSocket/index.mjs +615 -0
- package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.cjs +7 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +15 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +15 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs +7 -0
- package/lib/browser/interceptors/fetch/index.cjs +6 -0
- package/lib/browser/interceptors/fetch/index.d.cts +13 -0
- package/lib/browser/interceptors/fetch/index.d.mts +13 -0
- package/lib/browser/interceptors/fetch/index.mjs +6 -0
- package/lib/browser/presets/browser.cjs +17 -0
- package/lib/browser/presets/browser.cjs.map +1 -0
- package/lib/browser/presets/browser.d.cts +12 -0
- package/lib/browser/presets/browser.d.mts +14 -0
- package/lib/browser/presets/browser.mjs +17 -0
- package/lib/browser/presets/browser.mjs.map +1 -0
- package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs +31 -0
- package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs.map +1 -0
- package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs +25 -0
- package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs.map +1 -0
- package/lib/node/BatchInterceptor-3LnAnLTx.cjs +49 -0
- package/lib/node/BatchInterceptor-3LnAnLTx.cjs.map +1 -0
- package/lib/node/BatchInterceptor-D7mXzHcQ.d.mts +26 -0
- package/lib/node/BatchInterceptor-DFaBPilf.mjs +44 -0
- package/lib/node/BatchInterceptor-DFaBPilf.mjs.map +1 -0
- package/lib/node/BatchInterceptor-D_YqR8qU.d.cts +26 -0
- package/lib/node/ClientRequest-2rDe54Ui.cjs +1043 -0
- package/lib/node/ClientRequest-2rDe54Ui.cjs.map +1 -0
- package/lib/node/ClientRequest-Ca8Qykuv.mjs +1034 -0
- package/lib/node/ClientRequest-Ca8Qykuv.mjs.map +1 -0
- package/lib/node/Interceptor-DEazpLJd.d.mts +133 -0
- package/lib/node/Interceptor-DJ2akVWI.d.cts +133 -0
- package/lib/node/RemoteHttpInterceptor.cjs +154 -0
- package/lib/node/RemoteHttpInterceptor.cjs.map +1 -0
- package/lib/node/RemoteHttpInterceptor.d.cts +39 -0
- package/lib/node/RemoteHttpInterceptor.d.mts +39 -0
- package/lib/node/RemoteHttpInterceptor.mjs +152 -0
- package/lib/node/RemoteHttpInterceptor.mjs.map +1 -0
- package/lib/node/XMLHttpRequest-B7kJdYYI.cjs +763 -0
- package/lib/node/XMLHttpRequest-B7kJdYYI.cjs.map +1 -0
- package/lib/node/XMLHttpRequest-C8dIZpds.mjs +757 -0
- package/lib/node/XMLHttpRequest-C8dIZpds.mjs.map +1 -0
- package/lib/node/bufferUtils-DiCTqG-7.cjs +38 -0
- package/lib/node/bufferUtils-DiCTqG-7.cjs.map +1 -0
- package/lib/node/bufferUtils-_8XfKIfX.mjs +20 -0
- package/lib/node/bufferUtils-_8XfKIfX.mjs.map +1 -0
- package/lib/node/chunk-CbDLau6x.cjs +34 -0
- package/lib/node/fetch-BmXpK10r.cjs +272 -0
- package/lib/node/fetch-BmXpK10r.cjs.map +1 -0
- package/lib/node/fetch-G1DVwDKG.mjs +265 -0
- package/lib/node/fetch-G1DVwDKG.mjs.map +1 -0
- package/lib/node/fetchUtils-BaY5iWXw.cjs +419 -0
- package/lib/node/fetchUtils-BaY5iWXw.cjs.map +1 -0
- package/lib/node/fetchUtils-CoU35g3M.mjs +359 -0
- package/lib/node/fetchUtils-CoU35g3M.mjs.map +1 -0
- package/lib/node/getRawRequest-BavnMWh_.cjs +36 -0
- package/lib/node/getRawRequest-BavnMWh_.cjs.map +1 -0
- package/lib/node/getRawRequest-DnwmXyOW.mjs +24 -0
- package/lib/node/getRawRequest-DnwmXyOW.mjs.map +1 -0
- package/lib/node/glossary-BLKRyLBd.cjs +12 -0
- package/lib/node/glossary-BLKRyLBd.cjs.map +1 -0
- package/lib/node/glossary-glQBRnVD.mjs +6 -0
- package/lib/node/glossary-glQBRnVD.mjs.map +1 -0
- package/lib/node/handleRequest-Bb7Y-XLw.cjs +220 -0
- package/lib/node/handleRequest-Bb7Y-XLw.cjs.map +1 -0
- package/lib/node/handleRequest-Y97UwBbF.mjs +190 -0
- package/lib/node/handleRequest-Y97UwBbF.mjs.map +1 -0
- package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs +26 -0
- package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs.map +1 -0
- package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs +20 -0
- package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs.map +1 -0
- package/lib/node/index-BMbJ8FXL.d.cts +113 -0
- package/lib/node/index-C0YAQ36w.d.mts +113 -0
- package/lib/node/index.cjs +54 -0
- package/lib/node/index.cjs.map +1 -0
- package/lib/node/index.d.cts +75 -0
- package/lib/node/index.d.mts +75 -0
- package/lib/node/index.mjs +40 -0
- package/lib/node/index.mjs.map +1 -0
- package/lib/node/interceptors/ClientRequest/index.cjs +6 -0
- package/lib/node/interceptors/ClientRequest/index.d.cts +2 -0
- package/lib/node/interceptors/ClientRequest/index.d.mts +3 -0
- package/lib/node/interceptors/ClientRequest/index.mjs +6 -0
- package/lib/node/interceptors/XMLHttpRequest/index.cjs +6 -0
- package/lib/node/interceptors/XMLHttpRequest/index.d.cts +14 -0
- package/lib/node/interceptors/XMLHttpRequest/index.d.mts +14 -0
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -0
- package/lib/node/interceptors/fetch/index.cjs +5 -0
- package/lib/node/interceptors/fetch/index.d.cts +12 -0
- package/lib/node/interceptors/fetch/index.d.mts +12 -0
- package/lib/node/interceptors/fetch/index.mjs +5 -0
- package/lib/node/node-DwCc6iuP.mjs +27 -0
- package/lib/node/node-DwCc6iuP.mjs.map +1 -0
- package/lib/node/node-dKdAf3tC.cjs +39 -0
- package/lib/node/node-dKdAf3tC.cjs.map +1 -0
- package/lib/node/presets/node.cjs +22 -0
- package/lib/node/presets/node.cjs.map +1 -0
- package/lib/node/presets/node.d.cts +13 -0
- package/lib/node/presets/node.d.mts +15 -0
- package/lib/node/presets/node.mjs +22 -0
- package/lib/node/presets/node.mjs.map +1 -0
- package/lib/node/utils/node/index.cjs +4 -0
- package/lib/node/utils/node/index.d.cts +16 -0
- package/lib/node/utils/node/index.d.mts +16 -0
- package/lib/node/utils/node/index.mjs +3 -0
- package/package.json +204 -0
- package/presets/browser/package.json +5 -0
- package/presets/node/package.json +11 -0
- package/src/BatchInterceptor.test.ts +255 -0
- package/src/BatchInterceptor.ts +95 -0
- package/src/Interceptor.test.ts +205 -0
- package/src/Interceptor.ts +249 -0
- package/src/InterceptorError.ts +7 -0
- package/src/RemoteHttpInterceptor.ts +251 -0
- package/src/RequestController.test.ts +104 -0
- package/src/RequestController.ts +109 -0
- package/src/createRequestId.test.ts +7 -0
- package/src/createRequestId.ts +9 -0
- package/src/getRawRequest.ts +21 -0
- package/src/glossary.ts +37 -0
- package/src/index.ts +15 -0
- package/src/interceptors/ClientRequest/MockHttpSocket.ts +724 -0
- package/src/interceptors/ClientRequest/agents.ts +110 -0
- package/src/interceptors/ClientRequest/index.test.ts +75 -0
- package/src/interceptors/ClientRequest/index.ts +193 -0
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +54 -0
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +45 -0
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +427 -0
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +268 -0
- package/src/interceptors/ClientRequest/utils/parserUtils.ts +48 -0
- package/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts +258 -0
- package/src/interceptors/ClientRequest/utils/recordRawHeaders.ts +262 -0
- package/src/interceptors/Socket/MockSocket.test.ts +264 -0
- package/src/interceptors/Socket/MockSocket.ts +58 -0
- package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +26 -0
- package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +52 -0
- package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +33 -0
- package/src/interceptors/WebSocket/WebSocketClassTransport.ts +116 -0
- package/src/interceptors/WebSocket/WebSocketClientConnection.ts +152 -0
- package/src/interceptors/WebSocket/WebSocketOverride.ts +252 -0
- package/src/interceptors/WebSocket/WebSocketServerConnection.ts +420 -0
- package/src/interceptors/WebSocket/WebSocketTransport.ts +39 -0
- package/src/interceptors/WebSocket/index.ts +191 -0
- package/src/interceptors/WebSocket/utils/bindEvent.test.ts +27 -0
- package/src/interceptors/WebSocket/utils/bindEvent.ts +21 -0
- package/src/interceptors/WebSocket/utils/events.test.ts +101 -0
- package/src/interceptors/WebSocket/utils/events.ts +94 -0
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +746 -0
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +121 -0
- package/src/interceptors/XMLHttpRequest/index.ts +61 -0
- package/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +51 -0
- package/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +17 -0
- package/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +12 -0
- package/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts +12 -0
- package/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts +26 -0
- package/src/interceptors/XMLHttpRequest/utils/createEvent.ts +41 -0
- package/src/interceptors/XMLHttpRequest/utils/createResponse.ts +49 -0
- package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts +164 -0
- package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +16 -0
- package/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +14 -0
- package/src/interceptors/fetch/index.ts +214 -0
- package/src/interceptors/fetch/utils/brotli-decompress.browser.ts +14 -0
- package/src/interceptors/fetch/utils/brotli-decompress.ts +31 -0
- package/src/interceptors/fetch/utils/createNetworkError.ts +5 -0
- package/src/interceptors/fetch/utils/decompression.ts +85 -0
- package/src/interceptors/fetch/utils/followRedirect.ts +114 -0
- package/src/presets/browser.ts +11 -0
- package/src/presets/node.ts +13 -0
- package/src/utils/bufferUtils.test.ts +21 -0
- package/src/utils/bufferUtils.ts +22 -0
- package/src/utils/canParseUrl.ts +13 -0
- package/src/utils/cloneObject.test.ts +94 -0
- package/src/utils/cloneObject.ts +36 -0
- package/src/utils/createProxy.test.ts +164 -0
- package/src/utils/createProxy.ts +104 -0
- package/src/utils/emitAsync.ts +25 -0
- package/src/utils/fetchUtils.ts +119 -0
- package/src/utils/findPropertySource.test.ts +27 -0
- package/src/utils/findPropertySource.ts +20 -0
- package/src/utils/getCleanUrl.test.ts +32 -0
- package/src/utils/getCleanUrl.ts +6 -0
- package/src/utils/getUrlByRequestOptions.test.ts +163 -0
- package/src/utils/getUrlByRequestOptions.ts +152 -0
- package/src/utils/getValueBySymbol.test.ts +14 -0
- package/src/utils/getValueBySymbol.ts +19 -0
- package/src/utils/handleRequest.ts +205 -0
- package/src/utils/hasConfigurableGlobal.test.ts +83 -0
- package/src/utils/hasConfigurableGlobal.ts +34 -0
- package/src/utils/isNodeLikeError.ts +13 -0
- package/src/utils/isObject.test.ts +21 -0
- package/src/utils/isObject.ts +8 -0
- package/src/utils/isPropertyAccessible.ts +19 -0
- package/src/utils/nextTick.ts +11 -0
- package/src/utils/node/index.ts +39 -0
- package/src/utils/parseJson.test.ts +10 -0
- package/src/utils/parseJson.ts +12 -0
- package/src/utils/resolveWebSocketUrl.ts +45 -0
- 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
|
+
}
|