@mswjs/interceptors 0.26.14 → 0.27.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/README.md +33 -18
- package/lib/browser/interceptors/WebSocket/index.d.ts +31 -48
- package/lib/browser/interceptors/WebSocket/index.js +120 -66
- package/lib/browser/interceptors/WebSocket/index.js.map +1 -1
- package/lib/browser/interceptors/WebSocket/index.mjs +120 -66
- package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/interceptors/WebSocket/WebSocketClassTransport.ts +63 -27
- package/src/interceptors/WebSocket/WebSocketClientConnection.ts +31 -15
- package/src/interceptors/WebSocket/WebSocketOverride.ts +2 -2
- package/src/interceptors/WebSocket/WebSocketServerConnection.ts +108 -50
- package/src/interceptors/WebSocket/WebSocketTransport.ts +27 -28
|
@@ -28,56 +28,32 @@ export class WebSocketServerConnection {
|
|
|
28
28
|
this[kEmitter] = new EventTarget()
|
|
29
29
|
this.mockCloseController = new AbortController()
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
this.transport.
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const messageEvent = bindEvent(
|
|
41
|
-
this.realWebSocket!,
|
|
42
|
-
new CancelableMessageEvent('message', {
|
|
43
|
-
data: event.data,
|
|
44
|
-
origin: event.origin,
|
|
45
|
-
cancelable: true,
|
|
46
|
-
})
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @note Emit "message" event on the WebSocketClassServer
|
|
51
|
-
* instance to let the interceptor know about these
|
|
52
|
-
* incoming events from the original server. In that listener,
|
|
53
|
-
* the interceptor can modify or skip the event forwarding
|
|
54
|
-
* to the mock WebSocket instance.
|
|
55
|
-
*/
|
|
56
|
-
this[kEmitter].dispatchEvent(messageEvent)
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @note Forward the incoming server events to the client.
|
|
60
|
-
* Preventing the default on the message event stops this.
|
|
61
|
-
*/
|
|
62
|
-
if (!messageEvent.defaultPrevented) {
|
|
63
|
-
this.socket.dispatchEvent(
|
|
64
|
-
bindEvent(
|
|
65
|
-
/**
|
|
66
|
-
* @note Bind the forwarded original server events
|
|
67
|
-
* to the mock WebSocket instance so it would
|
|
68
|
-
* dispatch them straight away.
|
|
69
|
-
*/
|
|
70
|
-
this.socket,
|
|
71
|
-
// Clone the message event again to prevent
|
|
72
|
-
// the "already being dispatched" exception.
|
|
73
|
-
new MessageEvent('message', {
|
|
74
|
-
data: event.data,
|
|
75
|
-
origin: event.origin,
|
|
76
|
-
})
|
|
77
|
-
)
|
|
78
|
-
)
|
|
31
|
+
// Automatically forward outgoing client events
|
|
32
|
+
// to the actual server unless the outgoing message event
|
|
33
|
+
// has been prevented. The "outgoing" transport event it
|
|
34
|
+
// dispatched by the "client" connection.
|
|
35
|
+
this.transport.addEventListener('outgoing', (event) => {
|
|
36
|
+
// Ignore client messages if the server connection
|
|
37
|
+
// hasn't been established yet. Nowhere to forward.
|
|
38
|
+
if (this.readyState === -1) {
|
|
39
|
+
return
|
|
79
40
|
}
|
|
80
|
-
|
|
41
|
+
|
|
42
|
+
// Every outgoing client message can prevent this forwarding
|
|
43
|
+
// by preventing the default of the outgoing message event.
|
|
44
|
+
// This listener will be added before user-defined listeners,
|
|
45
|
+
// so execute the logic on the next tick.
|
|
46
|
+
queueMicrotask(() => {
|
|
47
|
+
if (!event.defaultPrevented) {
|
|
48
|
+
this.send(event.data)
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
this.transport.addEventListener(
|
|
54
|
+
'incoming',
|
|
55
|
+
this.handleIncomingMessage.bind(this)
|
|
56
|
+
)
|
|
81
57
|
}
|
|
82
58
|
|
|
83
59
|
/**
|
|
@@ -108,8 +84,33 @@ export class WebSocketServerConnection {
|
|
|
108
84
|
// Inherit the binary type from the mock WebSocket client.
|
|
109
85
|
realWebSocket.binaryType = this.socket.binaryType
|
|
110
86
|
|
|
87
|
+
// Allow the interceptor to listen to when the server connection
|
|
88
|
+
// has been established. This isn't necessary to operate with the connection
|
|
89
|
+
// but may be beneficial in some cases (like conditionally adding logging).
|
|
90
|
+
realWebSocket.addEventListener(
|
|
91
|
+
'open',
|
|
92
|
+
(event) => {
|
|
93
|
+
this[kEmitter].dispatchEvent(
|
|
94
|
+
bindEvent(this.realWebSocket!, new Event('open', event))
|
|
95
|
+
)
|
|
96
|
+
},
|
|
97
|
+
{ once: true }
|
|
98
|
+
)
|
|
99
|
+
|
|
111
100
|
realWebSocket.addEventListener('message', (event) => {
|
|
112
|
-
|
|
101
|
+
// Dispatch the "incoming" transport event instead of
|
|
102
|
+
// invoking the internal handler directly. This way,
|
|
103
|
+
// anyone can listen to the "incoming" event but this
|
|
104
|
+
// class is the one resulting in it.
|
|
105
|
+
this.transport.dispatchEvent(
|
|
106
|
+
bindEvent(
|
|
107
|
+
this.realWebSocket!,
|
|
108
|
+
new MessageEvent('incoming', {
|
|
109
|
+
data: event.data,
|
|
110
|
+
origin: event.origin,
|
|
111
|
+
})
|
|
112
|
+
)
|
|
113
|
+
)
|
|
113
114
|
})
|
|
114
115
|
|
|
115
116
|
// Close the original connection when the mock client closes.
|
|
@@ -215,6 +216,9 @@ export class WebSocketServerConnection {
|
|
|
215
216
|
this.socket.url
|
|
216
217
|
)
|
|
217
218
|
|
|
219
|
+
// Remove the "close" event listener from the server
|
|
220
|
+
// so it doesn't close the underlying WebSocket client
|
|
221
|
+
// when you call "server.close()".
|
|
218
222
|
realWebSocket.removeEventListener('close', this.handleRealClose)
|
|
219
223
|
|
|
220
224
|
if (
|
|
@@ -225,6 +229,60 @@ export class WebSocketServerConnection {
|
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
realWebSocket.close()
|
|
232
|
+
|
|
233
|
+
// Dispatch the "close" event on the server connection.
|
|
234
|
+
queueMicrotask(() => {
|
|
235
|
+
this[kEmitter].dispatchEvent(
|
|
236
|
+
bindEvent(this.realWebSocket, new CloseEvent('close'))
|
|
237
|
+
)
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private handleIncomingMessage(event: MessageEvent<WebSocketData>): void {
|
|
242
|
+
// Clone the event to dispatch it on this class
|
|
243
|
+
// once again and prevent the "already being dispatched"
|
|
244
|
+
// exception. Clone it here so we can observe this event
|
|
245
|
+
// being prevented in the "server.on()" listeners.
|
|
246
|
+
const messageEvent = bindEvent(
|
|
247
|
+
event.target,
|
|
248
|
+
new CancelableMessageEvent('message', {
|
|
249
|
+
data: event.data,
|
|
250
|
+
origin: event.origin,
|
|
251
|
+
cancelable: true,
|
|
252
|
+
})
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* @note Emit "message" event on the server connection
|
|
257
|
+
* instance to let the interceptor know about these
|
|
258
|
+
* incoming events from the original server. In that listener,
|
|
259
|
+
* the interceptor can modify or skip the event forwarding
|
|
260
|
+
* to the mock WebSocket instance.
|
|
261
|
+
*/
|
|
262
|
+
this[kEmitter].dispatchEvent(messageEvent)
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @note Forward the incoming server events to the client.
|
|
266
|
+
* Preventing the default on the message event stops this.
|
|
267
|
+
*/
|
|
268
|
+
if (!messageEvent.defaultPrevented) {
|
|
269
|
+
this.socket.dispatchEvent(
|
|
270
|
+
bindEvent(
|
|
271
|
+
/**
|
|
272
|
+
* @note Bind the forwarded original server events
|
|
273
|
+
* to the mock WebSocket instance so it would
|
|
274
|
+
* dispatch them straight away.
|
|
275
|
+
*/
|
|
276
|
+
this.socket,
|
|
277
|
+
// Clone the message event again to prevent
|
|
278
|
+
// the "already being dispatched" exception.
|
|
279
|
+
new MessageEvent('message', {
|
|
280
|
+
data: event.data,
|
|
281
|
+
origin: event.origin,
|
|
282
|
+
})
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
}
|
|
228
286
|
}
|
|
229
287
|
|
|
230
288
|
private handleMockClose(_event: Event): void {
|
|
@@ -1,40 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export type WebSocketTransportOnIncomingCallback = (
|
|
4
|
-
event: MessageEvent<WebSocketData>
|
|
5
|
-
) => void
|
|
6
|
-
|
|
7
|
-
export type WebSocketTransportOnOutgoingCallback = (data: WebSocketData) => void
|
|
1
|
+
import { CloseEvent } from './utils/events'
|
|
8
2
|
|
|
9
|
-
export type
|
|
10
|
-
|
|
11
|
-
export abstract class WebSocketTransport {
|
|
12
|
-
/**
|
|
13
|
-
* A callback for the incoming server events.
|
|
14
|
-
* This is called when the WebSocket client receives
|
|
15
|
-
* a message from the server.
|
|
16
|
-
*/
|
|
17
|
-
abstract onIncoming: WebSocketTransportOnIncomingCallback
|
|
3
|
+
export type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView
|
|
18
4
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
export type WebSocketTransportEventMap = {
|
|
6
|
+
incoming: MessageEvent<WebSocketData>
|
|
7
|
+
outgoing: MessageEvent<WebSocketData>
|
|
8
|
+
close: CloseEvent
|
|
9
|
+
}
|
|
24
10
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
11
|
+
export type StrictEventListenerOrEventListenerObject<EventType extends Event> =
|
|
12
|
+
| ((event: EventType) => void)
|
|
13
|
+
| {
|
|
14
|
+
handleEvent(event: EventType): void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface WebSocketTransport {
|
|
18
|
+
addEventListener<EventType extends keyof WebSocketTransportEventMap>(
|
|
19
|
+
event: EventType,
|
|
20
|
+
listener: StrictEventListenerOrEventListenerObject<
|
|
21
|
+
WebSocketTransportEventMap[EventType]
|
|
22
|
+
> | null,
|
|
23
|
+
options?: boolean | AddEventListenerOptions
|
|
24
|
+
): void
|
|
25
|
+
|
|
26
|
+
dispatchEvent<EventType extends keyof WebSocketTransportEventMap>(
|
|
27
|
+
event: WebSocketTransportEventMap[EventType]
|
|
28
|
+
): boolean
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* Send the data from the server to this client.
|
|
33
32
|
*/
|
|
34
|
-
|
|
33
|
+
send(data: WebSocketData): void
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
36
|
* Close the client connection.
|
|
38
37
|
*/
|
|
39
|
-
|
|
38
|
+
close(code?: number, reason?: string): void
|
|
40
39
|
}
|