@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,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment node
|
|
3
|
+
*/
|
|
4
|
+
import { Socket } from 'node:net'
|
|
5
|
+
import { vi, it, expect } from 'vitest'
|
|
6
|
+
import { MockSocket } from './MockSocket'
|
|
7
|
+
|
|
8
|
+
it(`keeps the socket connecting until it's destroyed`, () => {
|
|
9
|
+
const socket = new MockSocket({
|
|
10
|
+
write: vi.fn(),
|
|
11
|
+
read: vi.fn(),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
expect(socket.connecting).toBe(true)
|
|
15
|
+
|
|
16
|
+
socket.destroy()
|
|
17
|
+
expect(socket.connecting).toBe(false)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('calls the "write" on "socket.write()"', () => {
|
|
21
|
+
const writeCallback = vi.fn()
|
|
22
|
+
const socket = new MockSocket({
|
|
23
|
+
write: writeCallback,
|
|
24
|
+
read: vi.fn(),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
socket.write()
|
|
28
|
+
expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('calls the "write" on "socket.write(chunk)"', () => {
|
|
32
|
+
const writeCallback = vi.fn()
|
|
33
|
+
const socket = new MockSocket({
|
|
34
|
+
write: writeCallback,
|
|
35
|
+
read: vi.fn(),
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
socket.write('hello')
|
|
39
|
+
expect(writeCallback).toHaveBeenCalledWith('hello', undefined, undefined)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('calls the "write" on "socket.write(chunk, encoding)"', () => {
|
|
43
|
+
const writeCallback = vi.fn()
|
|
44
|
+
const socket = new MockSocket({
|
|
45
|
+
write: writeCallback,
|
|
46
|
+
read: vi.fn(),
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
socket.write('hello', 'utf8')
|
|
50
|
+
expect(writeCallback).toHaveBeenCalledWith('hello', 'utf8', undefined)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('calls the "write" on "socket.write(chunk, encoding, callback)"', () => {
|
|
54
|
+
const writeCallback = vi.fn()
|
|
55
|
+
const socket = new MockSocket({
|
|
56
|
+
write: writeCallback,
|
|
57
|
+
read: vi.fn(),
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const callback = vi.fn()
|
|
61
|
+
socket.write('hello', 'utf8', callback)
|
|
62
|
+
expect(writeCallback).toHaveBeenCalledWith('hello', 'utf8', callback)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('calls the "write" on "socket.end()"', () => {
|
|
66
|
+
const writeCallback = vi.fn()
|
|
67
|
+
const socket = new MockSocket({
|
|
68
|
+
write: writeCallback,
|
|
69
|
+
read: vi.fn(),
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
socket.end()
|
|
73
|
+
expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('calls the "write" on "socket.end(chunk)"', () => {
|
|
77
|
+
const writeCallback = vi.fn()
|
|
78
|
+
const socket = new MockSocket({
|
|
79
|
+
write: writeCallback,
|
|
80
|
+
read: vi.fn(),
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
socket.end('final')
|
|
84
|
+
expect(writeCallback).toHaveBeenCalledWith('final', undefined, undefined)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('calls the "write" on "socket.end(chunk, encoding)"', () => {
|
|
88
|
+
const writeCallback = vi.fn()
|
|
89
|
+
const socket = new MockSocket({
|
|
90
|
+
write: writeCallback,
|
|
91
|
+
read: vi.fn(),
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
socket.end('final', 'utf8')
|
|
95
|
+
expect(writeCallback).toHaveBeenCalledWith('final', 'utf8', undefined)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('calls the "write" on "socket.end(chunk, encoding, callback)"', () => {
|
|
99
|
+
const writeCallback = vi.fn()
|
|
100
|
+
const socket = new MockSocket({
|
|
101
|
+
write: writeCallback,
|
|
102
|
+
read: vi.fn(),
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const callback = vi.fn()
|
|
106
|
+
socket.end('final', 'utf8', callback)
|
|
107
|
+
expect(writeCallback).toHaveBeenCalledWith('final', 'utf8', callback)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('calls the "write" on "socket.end()" without any arguments', () => {
|
|
111
|
+
const writeCallback = vi.fn()
|
|
112
|
+
const socket = new MockSocket({
|
|
113
|
+
write: writeCallback,
|
|
114
|
+
read: vi.fn(),
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
socket.end()
|
|
118
|
+
expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('emits "finished" on .end() without any arguments', async () => {
|
|
122
|
+
const finishListener = vi.fn()
|
|
123
|
+
const socket = new MockSocket({
|
|
124
|
+
write: vi.fn(),
|
|
125
|
+
read: vi.fn(),
|
|
126
|
+
})
|
|
127
|
+
socket.on('finish', finishListener)
|
|
128
|
+
socket.end()
|
|
129
|
+
|
|
130
|
+
await vi.waitFor(() => {
|
|
131
|
+
expect(finishListener).toHaveBeenCalledTimes(1)
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('calls the "read" on "socket.read(chunk)"', () => {
|
|
136
|
+
const readCallback = vi.fn()
|
|
137
|
+
const socket = new MockSocket({
|
|
138
|
+
write: vi.fn(),
|
|
139
|
+
read: readCallback,
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
socket.push('hello')
|
|
143
|
+
expect(readCallback).toHaveBeenCalledWith('hello', undefined)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('calls the "read" on "socket.read(chunk, encoding)"', () => {
|
|
147
|
+
const readCallback = vi.fn()
|
|
148
|
+
const socket = new MockSocket({
|
|
149
|
+
write: vi.fn(),
|
|
150
|
+
read: readCallback,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
socket.push('world', 'utf8')
|
|
154
|
+
expect(readCallback).toHaveBeenCalledWith('world', 'utf8')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('calls the "read" on "socket.read(null)"', () => {
|
|
158
|
+
const readCallback = vi.fn()
|
|
159
|
+
const socket = new MockSocket({
|
|
160
|
+
write: vi.fn(),
|
|
161
|
+
read: readCallback,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
socket.push(null)
|
|
165
|
+
expect(readCallback).toHaveBeenCalledWith(null, undefined)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it('updates the writable state on "socket.end()"', async () => {
|
|
169
|
+
const finishListener = vi.fn()
|
|
170
|
+
const endListener = vi.fn()
|
|
171
|
+
const socket = new MockSocket({
|
|
172
|
+
write: vi.fn(),
|
|
173
|
+
read: vi.fn(),
|
|
174
|
+
})
|
|
175
|
+
socket.on('finish', finishListener)
|
|
176
|
+
socket.on('end', endListener)
|
|
177
|
+
|
|
178
|
+
expect(socket.writable).toBe(true)
|
|
179
|
+
expect(socket.writableEnded).toBe(false)
|
|
180
|
+
expect(socket.writableFinished).toBe(false)
|
|
181
|
+
|
|
182
|
+
socket.write('hello')
|
|
183
|
+
// Finish the writable stream.
|
|
184
|
+
socket.end()
|
|
185
|
+
|
|
186
|
+
expect(socket.writable).toBe(false)
|
|
187
|
+
expect(socket.writableEnded).toBe(true)
|
|
188
|
+
|
|
189
|
+
// The "finish" event is emitted when writable is done.
|
|
190
|
+
// I.e. "socket.end()" is called.
|
|
191
|
+
await vi.waitFor(() => {
|
|
192
|
+
expect(finishListener).toHaveBeenCalledTimes(1)
|
|
193
|
+
})
|
|
194
|
+
expect(socket.writableFinished).toBe(true)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('updates the readable state on "socket.push(null)"', async () => {
|
|
198
|
+
const endListener = vi.fn()
|
|
199
|
+
const socket = new MockSocket({
|
|
200
|
+
write: vi.fn(),
|
|
201
|
+
read: vi.fn(),
|
|
202
|
+
})
|
|
203
|
+
socket.on('end', endListener)
|
|
204
|
+
|
|
205
|
+
expect(socket.readable).toBe(true)
|
|
206
|
+
expect(socket.readableEnded).toBe(false)
|
|
207
|
+
|
|
208
|
+
socket.push('hello')
|
|
209
|
+
socket.push(null)
|
|
210
|
+
|
|
211
|
+
expect(socket.readable).toBe(true)
|
|
212
|
+
expect(socket.readableEnded).toBe(false)
|
|
213
|
+
|
|
214
|
+
// Read the data to free the buffer and
|
|
215
|
+
// make Socket emit "end".
|
|
216
|
+
socket.read()
|
|
217
|
+
|
|
218
|
+
await vi.waitFor(() => {
|
|
219
|
+
expect(endListener).toHaveBeenCalledTimes(1)
|
|
220
|
+
})
|
|
221
|
+
expect(socket.readable).toBe(false)
|
|
222
|
+
expect(socket.readableEnded).toBe(true)
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
it('updates the readable/writable state on "socket.destroy()"', async () => {
|
|
226
|
+
const finishListener = vi.fn()
|
|
227
|
+
const endListener = vi.fn()
|
|
228
|
+
const closeListener = vi.fn()
|
|
229
|
+
const socket = new MockSocket({
|
|
230
|
+
write: vi.fn(),
|
|
231
|
+
read: vi.fn(),
|
|
232
|
+
})
|
|
233
|
+
socket.on('finish', finishListener)
|
|
234
|
+
socket.on('end', endListener)
|
|
235
|
+
socket.on('close', closeListener)
|
|
236
|
+
|
|
237
|
+
expect(socket.writable).toBe(true)
|
|
238
|
+
expect(socket.writableEnded).toBe(false)
|
|
239
|
+
expect(socket.writableFinished).toBe(false)
|
|
240
|
+
expect(socket.readable).toBe(true)
|
|
241
|
+
|
|
242
|
+
socket.destroy()
|
|
243
|
+
|
|
244
|
+
expect(socket.writable).toBe(false)
|
|
245
|
+
// The ".end()" wasn't called.
|
|
246
|
+
expect(socket.writableEnded).toBe(false)
|
|
247
|
+
expect(socket.writableFinished).toBe(false)
|
|
248
|
+
expect(socket.readable).toBe(false)
|
|
249
|
+
|
|
250
|
+
await vi.waitFor(() => {
|
|
251
|
+
expect(closeListener).toHaveBeenCalledTimes(1)
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
// Neither "finish" nor "end" events are emitted
|
|
255
|
+
// when you destroy the stream. If you want those,
|
|
256
|
+
// call ".end()", then destroy the stream.
|
|
257
|
+
expect(finishListener).not.toHaveBeenCalled()
|
|
258
|
+
expect(endListener).not.toHaveBeenCalled()
|
|
259
|
+
expect(socket.writableFinished).toBe(false)
|
|
260
|
+
|
|
261
|
+
// The "end" event was never emitted so "readableEnded"
|
|
262
|
+
// remains false.
|
|
263
|
+
expect(socket.readableEnded).toBe(false)
|
|
264
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import net from 'node:net'
|
|
2
|
+
import {
|
|
3
|
+
normalizeSocketWriteArgs,
|
|
4
|
+
type WriteArgs,
|
|
5
|
+
type WriteCallback,
|
|
6
|
+
} from './utils/normalizeSocketWriteArgs'
|
|
7
|
+
|
|
8
|
+
export interface MockSocketOptions {
|
|
9
|
+
write: (
|
|
10
|
+
chunk: Buffer | string,
|
|
11
|
+
encoding: BufferEncoding | undefined,
|
|
12
|
+
callback?: WriteCallback
|
|
13
|
+
) => void
|
|
14
|
+
|
|
15
|
+
read: (chunk: Buffer, encoding: BufferEncoding | undefined) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class MockSocket extends net.Socket {
|
|
19
|
+
public connecting: boolean
|
|
20
|
+
|
|
21
|
+
constructor(protected readonly options: MockSocketOptions) {
|
|
22
|
+
super()
|
|
23
|
+
this.connecting = false
|
|
24
|
+
this.connect()
|
|
25
|
+
|
|
26
|
+
this._final = (callback) => {
|
|
27
|
+
callback(null)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public connect() {
|
|
32
|
+
// The connection will remain pending until
|
|
33
|
+
// the consumer decides to handle it.
|
|
34
|
+
this.connecting = true
|
|
35
|
+
return this
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public write(...args: Array<unknown>): boolean {
|
|
39
|
+
const [chunk, encoding, callback] = normalizeSocketWriteArgs(
|
|
40
|
+
args as WriteArgs
|
|
41
|
+
)
|
|
42
|
+
this.options.write(chunk, encoding, callback)
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public end(...args: Array<unknown>) {
|
|
47
|
+
const [chunk, encoding, callback] = normalizeSocketWriteArgs(
|
|
48
|
+
args as WriteArgs
|
|
49
|
+
)
|
|
50
|
+
this.options.write(chunk, encoding, callback)
|
|
51
|
+
return super.end.apply(this, args as any)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public push(chunk: any, encoding?: BufferEncoding): boolean {
|
|
55
|
+
this.options.read(chunk, encoding)
|
|
56
|
+
return super.push(chunk, encoding)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function baseUrlFromConnectionOptions(options: any): URL {
|
|
2
|
+
if ('href' in options) {
|
|
3
|
+
return new URL(options.href)
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const protocol = options.port === 443 ? 'https:' : 'http:'
|
|
7
|
+
const host = options.host
|
|
8
|
+
|
|
9
|
+
const url = new URL(`${protocol}//${host}`)
|
|
10
|
+
|
|
11
|
+
if (options.port) {
|
|
12
|
+
url.port = options.port.toString()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (options.path) {
|
|
16
|
+
url.pathname = options.path
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (options.auth) {
|
|
20
|
+
const [username, password] = options.auth.split(':')
|
|
21
|
+
url.username = username
|
|
22
|
+
url.password = password
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return url
|
|
26
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment node
|
|
3
|
+
*/
|
|
4
|
+
import { it, expect } from 'vitest'
|
|
5
|
+
import { normalizeSocketWriteArgs } from './normalizeSocketWriteArgs'
|
|
6
|
+
|
|
7
|
+
it('normalizes .write()', () => {
|
|
8
|
+
expect(normalizeSocketWriteArgs([undefined])).toEqual([
|
|
9
|
+
undefined,
|
|
10
|
+
undefined,
|
|
11
|
+
undefined,
|
|
12
|
+
])
|
|
13
|
+
expect(normalizeSocketWriteArgs([null])).toEqual([null, undefined, undefined])
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('normalizes .write(chunk)', () => {
|
|
17
|
+
expect(normalizeSocketWriteArgs([Buffer.from('hello')])).toEqual([
|
|
18
|
+
Buffer.from('hello'),
|
|
19
|
+
undefined,
|
|
20
|
+
undefined,
|
|
21
|
+
])
|
|
22
|
+
expect(normalizeSocketWriteArgs(['hello'])).toEqual([
|
|
23
|
+
'hello',
|
|
24
|
+
undefined,
|
|
25
|
+
undefined,
|
|
26
|
+
])
|
|
27
|
+
expect(normalizeSocketWriteArgs([null])).toEqual([null, undefined, undefined])
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('normalizes .write(chunk, encoding)', () => {
|
|
31
|
+
expect(normalizeSocketWriteArgs([Buffer.from('hello'), 'utf8'])).toEqual([
|
|
32
|
+
Buffer.from('hello'),
|
|
33
|
+
'utf8',
|
|
34
|
+
undefined,
|
|
35
|
+
])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('normalizes .write(chunk, callback)', () => {
|
|
39
|
+
const callback = () => {}
|
|
40
|
+
expect(normalizeSocketWriteArgs([Buffer.from('hello'), callback])).toEqual([
|
|
41
|
+
Buffer.from('hello'),
|
|
42
|
+
undefined,
|
|
43
|
+
callback,
|
|
44
|
+
])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('normalizes .write(chunk, encoding, callback)', () => {
|
|
48
|
+
const callback = () => {}
|
|
49
|
+
expect(
|
|
50
|
+
normalizeSocketWriteArgs([Buffer.from('hello'), 'utf8', callback])
|
|
51
|
+
).toEqual([Buffer.from('hello'), 'utf8', callback])
|
|
52
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type WriteCallback = (error?: Error | null) => void
|
|
2
|
+
|
|
3
|
+
export type WriteArgs =
|
|
4
|
+
| [chunk: unknown, callback?: WriteCallback]
|
|
5
|
+
| [chunk: unknown, encoding: BufferEncoding, callback?: WriteCallback]
|
|
6
|
+
|
|
7
|
+
export type NormalizedSocketWriteArgs = [
|
|
8
|
+
chunk: any,
|
|
9
|
+
encoding?: BufferEncoding,
|
|
10
|
+
callback?: WriteCallback,
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Normalizes the arguments provided to the `Writable.prototype.write()`
|
|
15
|
+
* and `Writable.prototype.end()`.
|
|
16
|
+
*/
|
|
17
|
+
export function normalizeSocketWriteArgs(
|
|
18
|
+
args: WriteArgs
|
|
19
|
+
): NormalizedSocketWriteArgs {
|
|
20
|
+
const normalized: NormalizedSocketWriteArgs = [args[0], undefined, undefined]
|
|
21
|
+
|
|
22
|
+
if (typeof args[1] === 'string') {
|
|
23
|
+
normalized[1] = args[1]
|
|
24
|
+
} else if (typeof args[1] === 'function') {
|
|
25
|
+
normalized[2] = args[1]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof args[2] === 'function') {
|
|
29
|
+
normalized[2] = args[2]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return normalized
|
|
33
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { bindEvent } from './utils/bindEvent'
|
|
2
|
+
import {
|
|
3
|
+
StrictEventListenerOrEventListenerObject,
|
|
4
|
+
WebSocketData,
|
|
5
|
+
WebSocketTransport,
|
|
6
|
+
WebSocketTransportEventMap,
|
|
7
|
+
} from './WebSocketTransport'
|
|
8
|
+
import { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride'
|
|
9
|
+
import { CancelableMessageEvent, CloseEvent } from './utils/events'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Abstraction over the given mock `WebSocket` instance that allows
|
|
13
|
+
* for controlling that instance (e.g. sending and receiving messages).
|
|
14
|
+
*/
|
|
15
|
+
export class WebSocketClassTransport
|
|
16
|
+
extends EventTarget
|
|
17
|
+
implements WebSocketTransport
|
|
18
|
+
{
|
|
19
|
+
constructor(protected readonly socket: WebSocketOverride) {
|
|
20
|
+
super()
|
|
21
|
+
|
|
22
|
+
// Emit the "close" event on the transport if the close
|
|
23
|
+
// originates from the WebSocket client. E.g. the application
|
|
24
|
+
// calls "ws.close()", not the interceptor.
|
|
25
|
+
this.socket.addEventListener('close', (event) => {
|
|
26
|
+
this.dispatchEvent(bindEvent(this.socket, new CloseEvent('close', event)))
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Emit the "outgoing" event on the transport
|
|
31
|
+
* whenever the WebSocket client sends data ("ws.send()").
|
|
32
|
+
*/
|
|
33
|
+
this.socket[kOnSend] = (data) => {
|
|
34
|
+
this.dispatchEvent(
|
|
35
|
+
bindEvent(
|
|
36
|
+
this.socket,
|
|
37
|
+
// Dispatch this as cancelable because "client" connection
|
|
38
|
+
// re-creates this message event (cannot dispatch the same event).
|
|
39
|
+
new CancelableMessageEvent('outgoing', {
|
|
40
|
+
data,
|
|
41
|
+
origin: this.socket.url,
|
|
42
|
+
cancelable: true,
|
|
43
|
+
})
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public addEventListener<EventType extends keyof WebSocketTransportEventMap>(
|
|
50
|
+
type: EventType,
|
|
51
|
+
callback: StrictEventListenerOrEventListenerObject<
|
|
52
|
+
WebSocketTransportEventMap[EventType]
|
|
53
|
+
> | null,
|
|
54
|
+
options?: boolean | AddEventListenerOptions
|
|
55
|
+
): void {
|
|
56
|
+
return super.addEventListener(type, callback as EventListener, options)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public dispatchEvent<EventType extends keyof WebSocketTransportEventMap>(
|
|
60
|
+
event: WebSocketTransportEventMap[EventType]
|
|
61
|
+
): boolean {
|
|
62
|
+
return super.dispatchEvent(event)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public send(data: WebSocketData): void {
|
|
66
|
+
queueMicrotask(() => {
|
|
67
|
+
if (
|
|
68
|
+
this.socket.readyState === this.socket.CLOSING ||
|
|
69
|
+
this.socket.readyState === this.socket.CLOSED
|
|
70
|
+
) {
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const dispatchEvent = () => {
|
|
75
|
+
this.socket.dispatchEvent(
|
|
76
|
+
bindEvent(
|
|
77
|
+
/**
|
|
78
|
+
* @note Setting this event's "target" to the
|
|
79
|
+
* WebSocket override instance is important.
|
|
80
|
+
* This way it can tell apart original incoming events
|
|
81
|
+
* (must be forwarded to the transport) from the
|
|
82
|
+
* mocked message events like the one below
|
|
83
|
+
* (must be dispatched on the client instance).
|
|
84
|
+
*/
|
|
85
|
+
this.socket,
|
|
86
|
+
new MessageEvent('message', {
|
|
87
|
+
data,
|
|
88
|
+
origin: this.socket.url,
|
|
89
|
+
})
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.socket.readyState === this.socket.CONNECTING) {
|
|
95
|
+
this.socket.addEventListener(
|
|
96
|
+
'open',
|
|
97
|
+
() => {
|
|
98
|
+
dispatchEvent()
|
|
99
|
+
},
|
|
100
|
+
{ once: true }
|
|
101
|
+
)
|
|
102
|
+
} else {
|
|
103
|
+
dispatchEvent()
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public close(code: number, reason?: string): void {
|
|
109
|
+
/**
|
|
110
|
+
* @note Call the internal close method directly
|
|
111
|
+
* to allow closing the connection with the status codes
|
|
112
|
+
* that are non-configurable by the user (> 1000 <= 1015).
|
|
113
|
+
*/
|
|
114
|
+
this.socket[kClose](code, reason)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { WebSocketData, WebSocketTransport } from './WebSocketTransport'
|
|
2
|
+
import type { WebSocketEventListener } from './WebSocketOverride'
|
|
3
|
+
import { bindEvent } from './utils/bindEvent'
|
|
4
|
+
import { CancelableMessageEvent, CloseEvent } from './utils/events'
|
|
5
|
+
import { createRequestId } from '../../createRequestId'
|
|
6
|
+
|
|
7
|
+
const kEmitter = Symbol('kEmitter')
|
|
8
|
+
const kBoundListener = Symbol('kBoundListener')
|
|
9
|
+
|
|
10
|
+
export interface WebSocketClientEventMap {
|
|
11
|
+
message: MessageEvent<WebSocketData>
|
|
12
|
+
close: CloseEvent
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export abstract class WebSocketClientConnectionProtocol {
|
|
16
|
+
abstract id: string
|
|
17
|
+
abstract url: URL
|
|
18
|
+
public abstract send(data: WebSocketData): void
|
|
19
|
+
public abstract close(code?: number, reason?: string): void
|
|
20
|
+
|
|
21
|
+
public abstract addEventListener<
|
|
22
|
+
EventType extends keyof WebSocketClientEventMap,
|
|
23
|
+
>(
|
|
24
|
+
type: EventType,
|
|
25
|
+
listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,
|
|
26
|
+
options?: AddEventListenerOptions | boolean
|
|
27
|
+
): void
|
|
28
|
+
|
|
29
|
+
public abstract removeEventListener<
|
|
30
|
+
EventType extends keyof WebSocketClientEventMap,
|
|
31
|
+
>(
|
|
32
|
+
event: EventType,
|
|
33
|
+
listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,
|
|
34
|
+
options?: EventListenerOptions | boolean
|
|
35
|
+
): void
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The WebSocket client instance represents an incoming
|
|
40
|
+
* client connection. The user can control the connection,
|
|
41
|
+
* send and receive events.
|
|
42
|
+
*/
|
|
43
|
+
export class WebSocketClientConnection implements WebSocketClientConnectionProtocol {
|
|
44
|
+
public readonly id: string
|
|
45
|
+
public readonly url: URL
|
|
46
|
+
|
|
47
|
+
private [kEmitter]: EventTarget
|
|
48
|
+
|
|
49
|
+
constructor(
|
|
50
|
+
public readonly socket: WebSocket,
|
|
51
|
+
private readonly transport: WebSocketTransport
|
|
52
|
+
) {
|
|
53
|
+
this.id = createRequestId()
|
|
54
|
+
this.url = new URL(socket.url)
|
|
55
|
+
this[kEmitter] = new EventTarget()
|
|
56
|
+
|
|
57
|
+
// Emit outgoing client data ("ws.send()") as "message"
|
|
58
|
+
// events on the "client" connection.
|
|
59
|
+
this.transport.addEventListener('outgoing', (event) => {
|
|
60
|
+
const message = bindEvent(
|
|
61
|
+
this.socket,
|
|
62
|
+
new CancelableMessageEvent('message', {
|
|
63
|
+
data: event.data,
|
|
64
|
+
origin: event.origin,
|
|
65
|
+
cancelable: true,
|
|
66
|
+
})
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
this[kEmitter].dispatchEvent(message)
|
|
70
|
+
|
|
71
|
+
// This is a bit silly but forward the cancellation state
|
|
72
|
+
// of the "client" message event to the "outgoing" transport event.
|
|
73
|
+
// This way, other agens (like "server" connection) can know
|
|
74
|
+
// whether the client listener has pervented the default.
|
|
75
|
+
if (message.defaultPrevented) {
|
|
76
|
+
event.preventDefault()
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Emit the "close" event on the "client" connection
|
|
82
|
+
* whenever the underlying transport is closed.
|
|
83
|
+
* @note "client.close()" does NOT dispatch the "close"
|
|
84
|
+
* event on the WebSocket because it uses non-configurable
|
|
85
|
+
* close status code. Thus, we listen to the transport
|
|
86
|
+
* instead of the WebSocket's "close" event.
|
|
87
|
+
*/
|
|
88
|
+
this.transport.addEventListener('close', (event) => {
|
|
89
|
+
this[kEmitter].dispatchEvent(
|
|
90
|
+
bindEvent(this.socket, new CloseEvent('close', event))
|
|
91
|
+
)
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Listen for the outgoing events from the connected WebSocket client.
|
|
97
|
+
*/
|
|
98
|
+
public addEventListener<EventType extends keyof WebSocketClientEventMap>(
|
|
99
|
+
type: EventType,
|
|
100
|
+
listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,
|
|
101
|
+
options?: AddEventListenerOptions | boolean
|
|
102
|
+
): void {
|
|
103
|
+
if (!Reflect.has(listener, kBoundListener)) {
|
|
104
|
+
const boundListener = listener.bind(this.socket)
|
|
105
|
+
|
|
106
|
+
// Store the bound listener on the original listener
|
|
107
|
+
// so the exact bound function can be accessed in "removeEventListener()".
|
|
108
|
+
Object.defineProperty(listener, kBoundListener, {
|
|
109
|
+
value: boundListener,
|
|
110
|
+
enumerable: false,
|
|
111
|
+
configurable: false,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this[kEmitter].addEventListener(
|
|
116
|
+
type,
|
|
117
|
+
Reflect.get(listener, kBoundListener) as EventListener,
|
|
118
|
+
options
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Removes the listener for the given event.
|
|
124
|
+
*/
|
|
125
|
+
public removeEventListener<EventType extends keyof WebSocketClientEventMap>(
|
|
126
|
+
event: EventType,
|
|
127
|
+
listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,
|
|
128
|
+
options?: EventListenerOptions | boolean
|
|
129
|
+
): void {
|
|
130
|
+
this[kEmitter].removeEventListener(
|
|
131
|
+
event,
|
|
132
|
+
Reflect.get(listener, kBoundListener) as EventListener,
|
|
133
|
+
options
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Send data to the connected client.
|
|
139
|
+
*/
|
|
140
|
+
public send(data: WebSocketData): void {
|
|
141
|
+
this.transport.send(data)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Close the WebSocket connection.
|
|
146
|
+
* @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1).
|
|
147
|
+
* @param {string} reason A custom connection close reason.
|
|
148
|
+
*/
|
|
149
|
+
public close(code?: number, reason?: string): void {
|
|
150
|
+
this.transport.close(code, reason)
|
|
151
|
+
}
|
|
152
|
+
}
|