msw 2.9.0 → 2.10.1
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/lib/browser/index.js +8 -8
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/index.mjs +8 -8
- package/lib/browser/index.mjs.map +1 -1
- package/lib/core/handlers/WebSocketHandler.d.mts +10 -7
- package/lib/core/handlers/WebSocketHandler.d.ts +10 -7
- package/lib/core/handlers/WebSocketHandler.js +12 -8
- package/lib/core/handlers/WebSocketHandler.js.map +1 -1
- package/lib/core/handlers/WebSocketHandler.mjs +12 -8
- package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
- package/lib/core/ws/WebSocketClientManager.d.mts +4 -2
- package/lib/core/ws/WebSocketClientManager.d.ts +4 -2
- package/lib/core/ws/WebSocketClientManager.js +10 -0
- package/lib/core/ws/WebSocketClientManager.js.map +1 -1
- package/lib/core/ws/WebSocketClientManager.mjs +10 -0
- package/lib/core/ws/WebSocketClientManager.mjs.map +1 -1
- package/lib/core/ws/handleWebSocketEvent.js +26 -39
- package/lib/core/ws/handleWebSocketEvent.js.map +1 -1
- package/lib/core/ws/handleWebSocketEvent.mjs +26 -39
- package/lib/core/ws/handleWebSocketEvent.mjs.map +1 -1
- package/lib/core/ws/utils/getMessageLength.js.map +1 -1
- package/lib/core/ws/utils/getMessageLength.mjs.map +1 -1
- package/lib/core/ws/utils/getPublicData.js.map +1 -1
- package/lib/core/ws/utils/getPublicData.mjs.map +1 -1
- package/lib/iife/index.js +57 -54
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/package.json +3 -3
- package/src/core/handlers/WebSocketHandler.test.ts +12 -61
- package/src/core/handlers/WebSocketHandler.ts +27 -15
- package/src/core/ws/WebSocketClientManager.ts +33 -3
- package/src/core/ws/handleWebSocketEvent.ts +36 -55
- package/src/core/ws/utils/getMessageLength.ts +1 -1
- package/src/core/ws/utils/getPublicData.ts +1 -1
package/lib/mockServiceWorker.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Please do NOT modify this file.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const PACKAGE_VERSION = '2.
|
|
10
|
+
const PACKAGE_VERSION = '2.10.1'
|
|
11
11
|
const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af'
|
|
12
12
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
|
13
13
|
const activeClientIds = new Set()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "Seamless REST/GraphQL API mocking library for browser and Node.js.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./lib/core/index.js",
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
"@bundled-es-modules/statuses": "^1.0.1",
|
|
219
219
|
"@bundled-es-modules/tough-cookie": "^0.1.6",
|
|
220
220
|
"@inquirer/confirm": "^5.0.0",
|
|
221
|
-
"@mswjs/interceptors": "^0.
|
|
221
|
+
"@mswjs/interceptors": "^0.39.1",
|
|
222
222
|
"@open-draft/deferred-promise": "^2.2.0",
|
|
223
223
|
"@open-draft/until": "^2.1.0",
|
|
224
224
|
"@types/cookie": "^0.6.0",
|
|
@@ -280,7 +280,7 @@
|
|
|
280
280
|
"vitest-environment-miniflare": "^2.14.4",
|
|
281
281
|
"webpack": "^5.95.0",
|
|
282
282
|
"webpack-http-server": "^0.5.0",
|
|
283
|
-
"msw": "2.
|
|
283
|
+
"msw": "2.10.1"
|
|
284
284
|
},
|
|
285
285
|
"peerDependencies": {
|
|
286
286
|
"typescript": ">= 4.8.x"
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import type { WebSocketConnectionData } from '@mswjs/interceptors/WebSocket'
|
|
2
1
|
import { WebSocketHandler } from './WebSocketHandler'
|
|
3
2
|
|
|
4
3
|
describe('parse', () => {
|
|
5
4
|
it('matches an exact url', () => {
|
|
6
5
|
expect(
|
|
7
6
|
new WebSocketHandler('ws://localhost:3000').parse({
|
|
8
|
-
|
|
9
|
-
data: {
|
|
10
|
-
client: {
|
|
11
|
-
url: new URL('ws://localhost:3000'),
|
|
12
|
-
},
|
|
13
|
-
} as WebSocketConnectionData,
|
|
14
|
-
}),
|
|
7
|
+
url: new URL('ws://localhost:3000'),
|
|
15
8
|
}),
|
|
16
9
|
).toEqual({
|
|
17
10
|
match: {
|
|
@@ -24,13 +17,7 @@ describe('parse', () => {
|
|
|
24
17
|
it('ignores trailing slash', () => {
|
|
25
18
|
expect(
|
|
26
19
|
new WebSocketHandler('ws://localhost:3000').parse({
|
|
27
|
-
|
|
28
|
-
data: {
|
|
29
|
-
client: {
|
|
30
|
-
url: new URL('ws://localhost:3000/'),
|
|
31
|
-
},
|
|
32
|
-
} as WebSocketConnectionData,
|
|
33
|
-
}),
|
|
20
|
+
url: new URL('ws://localhost:3000/'),
|
|
34
21
|
}),
|
|
35
22
|
).toEqual({
|
|
36
23
|
match: {
|
|
@@ -41,13 +28,7 @@ describe('parse', () => {
|
|
|
41
28
|
|
|
42
29
|
expect(
|
|
43
30
|
new WebSocketHandler('ws://localhost:3000/').parse({
|
|
44
|
-
|
|
45
|
-
data: {
|
|
46
|
-
client: {
|
|
47
|
-
url: new URL('ws://localhost:3000'),
|
|
48
|
-
},
|
|
49
|
-
} as WebSocketConnectionData,
|
|
50
|
-
}),
|
|
31
|
+
url: new URL('ws://localhost:3000/'),
|
|
51
32
|
}),
|
|
52
33
|
).toEqual({
|
|
53
34
|
match: {
|
|
@@ -60,13 +41,7 @@ describe('parse', () => {
|
|
|
60
41
|
it('supports path parameters', () => {
|
|
61
42
|
expect(
|
|
62
43
|
new WebSocketHandler('ws://localhost:3000/:serviceName').parse({
|
|
63
|
-
|
|
64
|
-
data: {
|
|
65
|
-
client: {
|
|
66
|
-
url: new URL('ws://localhost:3000/auth'),
|
|
67
|
-
},
|
|
68
|
-
} as WebSocketConnectionData,
|
|
69
|
-
}),
|
|
44
|
+
url: new URL('ws://localhost:3000/auth'),
|
|
70
45
|
}),
|
|
71
46
|
).toEqual({
|
|
72
47
|
match: {
|
|
@@ -81,15 +56,9 @@ describe('parse', () => {
|
|
|
81
56
|
it('ignores "/socket.io/" prefix in the client url', () => {
|
|
82
57
|
expect(
|
|
83
58
|
new WebSocketHandler('ws://localhost:3000').parse({
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
url: new URL(
|
|
88
|
-
'ws://localhost:3000/socket.io/?EIO=4&transport=websocket',
|
|
89
|
-
),
|
|
90
|
-
},
|
|
91
|
-
} as WebSocketConnectionData,
|
|
92
|
-
}),
|
|
59
|
+
url: new URL(
|
|
60
|
+
'ws://localhost:3000/socket.io/?EIO=4&transport=websocket',
|
|
61
|
+
),
|
|
93
62
|
}),
|
|
94
63
|
).toEqual({
|
|
95
64
|
match: {
|
|
@@ -100,15 +69,9 @@ describe('parse', () => {
|
|
|
100
69
|
|
|
101
70
|
expect(
|
|
102
71
|
new WebSocketHandler('ws://localhost:3000/non-matching').parse({
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
url: new URL(
|
|
107
|
-
'ws://localhost:3000/socket.io/?EIO=4&transport=websocket',
|
|
108
|
-
),
|
|
109
|
-
},
|
|
110
|
-
} as WebSocketConnectionData,
|
|
111
|
-
}),
|
|
72
|
+
url: new URL(
|
|
73
|
+
'ws://localhost:3000/socket.io/?EIO=4&transport=websocket',
|
|
74
|
+
),
|
|
112
75
|
}),
|
|
113
76
|
).toEqual({
|
|
114
77
|
match: {
|
|
@@ -125,13 +88,7 @@ describe('parse', () => {
|
|
|
125
88
|
*/
|
|
126
89
|
expect(
|
|
127
90
|
new WebSocketHandler('ws://localhost:3000/clients/socket.io/123').parse({
|
|
128
|
-
|
|
129
|
-
data: {
|
|
130
|
-
client: {
|
|
131
|
-
url: new URL('ws://localhost:3000/clients/socket.io/123'),
|
|
132
|
-
},
|
|
133
|
-
} as WebSocketConnectionData,
|
|
134
|
-
}),
|
|
91
|
+
url: new URL('ws://localhost:3000/clients/socket.io/123'),
|
|
135
92
|
}),
|
|
136
93
|
).toEqual({
|
|
137
94
|
match: {
|
|
@@ -142,13 +99,7 @@ describe('parse', () => {
|
|
|
142
99
|
|
|
143
100
|
expect(
|
|
144
101
|
new WebSocketHandler('ws://localhost:3000').parse({
|
|
145
|
-
|
|
146
|
-
data: {
|
|
147
|
-
client: {
|
|
148
|
-
url: new URL('ws://localhost:3000/clients/socket.io/123'),
|
|
149
|
-
},
|
|
150
|
-
} as WebSocketConnectionData,
|
|
151
|
-
}),
|
|
102
|
+
url: new URL('ws://localhost:3000/clients/socket.io/123'),
|
|
152
103
|
}),
|
|
153
104
|
).toEqual({
|
|
154
105
|
match: {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Emitter } from 'strict-event-emitter'
|
|
2
2
|
import { createRequestId } from '@mswjs/interceptors'
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
WebSocketClientConnectionProtocol,
|
|
5
|
+
WebSocketConnectionData,
|
|
6
|
+
WebSocketServerConnectionProtocol,
|
|
7
|
+
} from '@mswjs/interceptors/WebSocket'
|
|
4
8
|
import {
|
|
5
9
|
type Match,
|
|
6
10
|
type Path,
|
|
@@ -18,12 +22,14 @@ export type WebSocketHandlerEventMap = {
|
|
|
18
22
|
connection: [args: WebSocketHandlerConnection]
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
export interface WebSocketHandlerConnection
|
|
25
|
+
export interface WebSocketHandlerConnection {
|
|
26
|
+
client: WebSocketClientConnectionProtocol
|
|
27
|
+
server: WebSocketServerConnectionProtocol
|
|
28
|
+
info: WebSocketConnectionData['info']
|
|
22
29
|
params: PathParams
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
export const kEmitter = Symbol('kEmitter')
|
|
26
|
-
export const kDispatchEvent = Symbol('kDispatchEvent')
|
|
27
33
|
export const kSender = Symbol('kSender')
|
|
28
34
|
const kStopPropagationPatched = Symbol('kStopPropagationPatched')
|
|
29
35
|
const KOnStopPropagation = Symbol('KOnStopPropagation')
|
|
@@ -44,11 +50,8 @@ export class WebSocketHandler {
|
|
|
44
50
|
this.__kind = 'EventHandler'
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
public parse(args: {
|
|
48
|
-
|
|
49
|
-
}): WebSocketHandlerParsedResult {
|
|
50
|
-
const { data: connection } = args.event
|
|
51
|
-
const { url: clientUrl } = connection.client
|
|
53
|
+
public parse(args: { url: URL }): WebSocketHandlerParsedResult {
|
|
54
|
+
const clientUrl = new URL(args.url)
|
|
52
55
|
|
|
53
56
|
/**
|
|
54
57
|
* @note Remove the Socket.IO path prefix from the WebSocket
|
|
@@ -65,23 +68,32 @@ export class WebSocketHandler {
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
public predicate(args: {
|
|
68
|
-
|
|
71
|
+
url: URL
|
|
69
72
|
parsedResult: WebSocketHandlerParsedResult
|
|
70
73
|
}): boolean {
|
|
71
74
|
return args.parsedResult.match.matches
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
async
|
|
75
|
-
|
|
76
|
-
): Promise<
|
|
77
|
-
const parsedResult = this.parse({
|
|
78
|
-
|
|
77
|
+
public async run(
|
|
78
|
+
connection: Omit<WebSocketHandlerConnection, 'params'>,
|
|
79
|
+
): Promise<boolean> {
|
|
80
|
+
const parsedResult = this.parse({
|
|
81
|
+
url: connection.client.url,
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
if (!this.predicate({ url: connection.client.url, parsedResult })) {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
79
87
|
|
|
80
88
|
const resolvedConnection: WebSocketHandlerConnection = {
|
|
81
89
|
...connection,
|
|
82
90
|
params: parsedResult.match.params || {},
|
|
83
91
|
}
|
|
84
92
|
|
|
93
|
+
return this.connect(resolvedConnection)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected connect(connection: WebSocketHandlerConnection): boolean {
|
|
85
97
|
// Support `event.stopPropagation()` for various client/server events.
|
|
86
98
|
connection.client.addEventListener(
|
|
87
99
|
'message',
|
|
@@ -111,7 +123,7 @@ export class WebSocketHandler {
|
|
|
111
123
|
|
|
112
124
|
// Emit the connection event on the handler.
|
|
113
125
|
// This is what the developer adds listeners for.
|
|
114
|
-
this[kEmitter].emit('connection',
|
|
126
|
+
return this[kEmitter].emit('connection', connection)
|
|
115
127
|
}
|
|
116
128
|
}
|
|
117
129
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
WebSocketData,
|
|
3
|
-
WebSocketClientConnection,
|
|
4
3
|
WebSocketClientConnectionProtocol,
|
|
4
|
+
WebSocketClientEventMap,
|
|
5
5
|
} from '@mswjs/interceptors/WebSocket'
|
|
6
6
|
import { WebSocketClientStore } from './WebSocketClientStore'
|
|
7
7
|
import { WebSocketMemoryClientStore } from './WebSocketMemoryClientStore'
|
|
@@ -105,7 +105,9 @@ export class WebSocketClientManager {
|
|
|
105
105
|
this.channel.postMessage({ type: 'db:update' })
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
private async addClient(
|
|
108
|
+
private async addClient(
|
|
109
|
+
client: WebSocketClientConnectionProtocol,
|
|
110
|
+
): Promise<void> {
|
|
109
111
|
await this.store.add(client)
|
|
110
112
|
// Sync the in-memory clients in this runtime with the
|
|
111
113
|
// updated database. This pulls in all the stored clients.
|
|
@@ -119,7 +121,9 @@ export class WebSocketClientManager {
|
|
|
119
121
|
* connection object because `addConnection()` is called only
|
|
120
122
|
* for the opened connections in the same runtime.
|
|
121
123
|
*/
|
|
122
|
-
public async addConnection(
|
|
124
|
+
public async addConnection(
|
|
125
|
+
client: WebSocketClientConnectionProtocol,
|
|
126
|
+
): Promise<void> {
|
|
123
127
|
// Store this client in the map of clients created in this runtime.
|
|
124
128
|
// This way, the manager can distinguish between this runtime clients
|
|
125
129
|
// and extraneous runtime clients when synchronizing clients storage.
|
|
@@ -208,4 +212,30 @@ export class WebSocketRemoteClientConnection
|
|
|
208
212
|
},
|
|
209
213
|
} as WebSocketBroadcastChannelMessage)
|
|
210
214
|
}
|
|
215
|
+
|
|
216
|
+
addEventListener<EventType extends keyof WebSocketClientEventMap>(
|
|
217
|
+
_type: EventType,
|
|
218
|
+
_listener: (
|
|
219
|
+
this: WebSocket,
|
|
220
|
+
event: WebSocketClientEventMap[EventType],
|
|
221
|
+
) => void,
|
|
222
|
+
_options?: AddEventListenerOptions | boolean,
|
|
223
|
+
): void {
|
|
224
|
+
throw new Error(
|
|
225
|
+
'WebSocketRemoteClientConnection.addEventListener is not supported',
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
removeEventListener<EventType extends keyof WebSocketClientEventMap>(
|
|
230
|
+
_event: EventType,
|
|
231
|
+
_listener: (
|
|
232
|
+
this: WebSocket,
|
|
233
|
+
event: WebSocketClientEventMap[EventType],
|
|
234
|
+
) => void,
|
|
235
|
+
_options?: EventListenerOptions | boolean,
|
|
236
|
+
): void {
|
|
237
|
+
throw new Error(
|
|
238
|
+
'WebSocketRemoteClientConnection.removeEventListener is not supported',
|
|
239
|
+
)
|
|
240
|
+
}
|
|
211
241
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { WebSocketConnectionData } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'
|
|
2
2
|
import { RequestHandler } from '../handlers/RequestHandler'
|
|
3
|
-
import { WebSocketHandler
|
|
3
|
+
import { WebSocketHandler } from '../handlers/WebSocketHandler'
|
|
4
4
|
import { webSocketInterceptor } from './webSocketInterceptor'
|
|
5
5
|
import {
|
|
6
6
|
onUnhandledRequest,
|
|
@@ -17,67 +17,48 @@ interface HandleWebSocketEventOptions {
|
|
|
17
17
|
|
|
18
18
|
export function handleWebSocketEvent(options: HandleWebSocketEventOptions) {
|
|
19
19
|
webSocketInterceptor.on('connection', async (connection) => {
|
|
20
|
-
const handlers = options.getHandlers()
|
|
20
|
+
const handlers = options.getHandlers().filter(isHandlerKind('EventHandler'))
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// Ignore this connection if the user hasn't defined any handlers.
|
|
23
|
+
if (handlers.length > 0) {
|
|
24
|
+
options?.onMockedConnection(connection)
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
await Promise.all(
|
|
27
|
+
handlers.map((handler) => {
|
|
28
|
+
// Iterate over the handlers and forward the connection
|
|
29
|
+
// event to WebSocket event handlers. This is equivalent
|
|
30
|
+
// to dispatching that event onto multiple listeners.
|
|
31
|
+
return handler.run(connection)
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
isHandlerKind('EventHandler')(handler) &&
|
|
35
|
-
handler.predicate({
|
|
36
|
-
event: connectionEvent,
|
|
37
|
-
parsedResult: handler.parse({
|
|
38
|
-
event: connectionEvent,
|
|
39
|
-
}),
|
|
40
|
-
})
|
|
41
|
-
) {
|
|
42
|
-
matchingHandlers.push(handler)
|
|
43
|
-
}
|
|
35
|
+
return
|
|
44
36
|
}
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
})
|
|
63
|
-
await onUnhandledRequest(
|
|
64
|
-
request,
|
|
65
|
-
options.getUnhandledRequestStrategy(),
|
|
66
|
-
).catch((error) => {
|
|
67
|
-
const errorEvent = new Event('error')
|
|
68
|
-
Object.defineProperty(errorEvent, 'cause', {
|
|
69
|
-
enumerable: true,
|
|
70
|
-
configurable: false,
|
|
71
|
-
value: error,
|
|
72
|
-
})
|
|
73
|
-
connection.client.socket.dispatchEvent(errorEvent)
|
|
38
|
+
// Construct a request representing this WebSocket connection.
|
|
39
|
+
const request = new Request(connection.client.url, {
|
|
40
|
+
headers: {
|
|
41
|
+
upgrade: 'websocket',
|
|
42
|
+
connection: 'upgrade',
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
await onUnhandledRequest(
|
|
46
|
+
request,
|
|
47
|
+
options.getUnhandledRequestStrategy(),
|
|
48
|
+
).catch((error) => {
|
|
49
|
+
const errorEvent = new Event('error')
|
|
50
|
+
Object.defineProperty(errorEvent, 'cause', {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
configurable: false,
|
|
53
|
+
value: error,
|
|
74
54
|
})
|
|
55
|
+
connection.client.socket.dispatchEvent(errorEvent)
|
|
56
|
+
})
|
|
75
57
|
|
|
76
|
-
|
|
58
|
+
options?.onPassthroughConnection(connection)
|
|
77
59
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
60
|
+
// If none of the "ws" handlers matched,
|
|
61
|
+
// establish the WebSocket connection as-is.
|
|
62
|
+
connection.server.connect()
|
|
82
63
|
})
|
|
83
64
|
}
|
|
@@ -9,7 +9,7 @@ export async function getPublicData(data: WebSocketData): Promise<string> {
|
|
|
9
9
|
|
|
10
10
|
// Handle all ArrayBuffer-like objects.
|
|
11
11
|
if (typeof data === 'object' && 'byteLength' in data) {
|
|
12
|
-
const text = new TextDecoder().decode(data)
|
|
12
|
+
const text = new TextDecoder().decode(data as ArrayBuffer)
|
|
13
13
|
return `ArrayBuffer(${truncateMessage(text)})`
|
|
14
14
|
}
|
|
15
15
|
|