msw 2.9.0 → 2.10.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.
@@ -7,7 +7,7 @@
7
7
  * - Please do NOT modify this file.
8
8
  */
9
9
 
10
- const PACKAGE_VERSION = '2.9.0'
10
+ const PACKAGE_VERSION = '2.10.0'
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.9.0",
3
+ "version": "2.10.0",
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",
@@ -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.9.0"
283
+ "msw": "2.10.0"
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
- event: new MessageEvent('connection', {
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
- event: new MessageEvent('connection', {
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
- event: new MessageEvent('connection', {
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
- event: new MessageEvent('connection', {
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
- event: new MessageEvent('connection', {
85
- data: {
86
- client: {
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
- event: new MessageEvent('connection', {
104
- data: {
105
- client: {
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
- event: new MessageEvent('connection', {
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
- event: new MessageEvent('connection', {
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: {
@@ -23,7 +23,6 @@ export interface WebSocketHandlerConnection extends WebSocketConnectionData {
23
23
  }
24
24
 
25
25
  export const kEmitter = Symbol('kEmitter')
26
- export const kDispatchEvent = Symbol('kDispatchEvent')
27
26
  export const kSender = Symbol('kSender')
28
27
  const kStopPropagationPatched = Symbol('kStopPropagationPatched')
29
28
  const KOnStopPropagation = Symbol('KOnStopPropagation')
@@ -44,11 +43,8 @@ export class WebSocketHandler {
44
43
  this.__kind = 'EventHandler'
45
44
  }
46
45
 
47
- public parse(args: {
48
- event: MessageEvent<WebSocketConnectionData>
49
- }): WebSocketHandlerParsedResult {
50
- const { data: connection } = args.event
51
- const { url: clientUrl } = connection.client
46
+ public parse(args: { url: URL }): WebSocketHandlerParsedResult {
47
+ const clientUrl = new URL(args.url)
52
48
 
53
49
  /**
54
50
  * @note Remove the Socket.IO path prefix from the WebSocket
@@ -65,23 +61,30 @@ export class WebSocketHandler {
65
61
  }
66
62
 
67
63
  public predicate(args: {
68
- event: MessageEvent<WebSocketConnectionData>
64
+ url: URL
69
65
  parsedResult: WebSocketHandlerParsedResult
70
66
  }): boolean {
71
67
  return args.parsedResult.match.matches
72
68
  }
73
69
 
74
- async [kDispatchEvent](
75
- event: MessageEvent<WebSocketConnectionData>,
76
- ): Promise<void> {
77
- const parsedResult = this.parse({ event })
78
- const connection = event.data
70
+ public async run(connection: WebSocketConnectionData): Promise<boolean> {
71
+ const parsedResult = this.parse({
72
+ url: connection.client.url,
73
+ })
74
+
75
+ if (!this.predicate({ url: connection.client.url, parsedResult })) {
76
+ return false
77
+ }
79
78
 
80
79
  const resolvedConnection: WebSocketHandlerConnection = {
81
80
  ...connection,
82
81
  params: parsedResult.match.params || {},
83
82
  }
84
83
 
84
+ return this.connect(resolvedConnection)
85
+ }
86
+
87
+ protected connect(connection: WebSocketHandlerConnection): boolean {
85
88
  // Support `event.stopPropagation()` for various client/server events.
86
89
  connection.client.addEventListener(
87
90
  'message',
@@ -111,7 +114,7 @@ export class WebSocketHandler {
111
114
 
112
115
  // Emit the connection event on the handler.
113
116
  // This is what the developer adds listeners for.
114
- this[kEmitter].emit('connection', resolvedConnection)
117
+ return this[kEmitter].emit('connection', connection)
115
118
  }
116
119
  }
117
120
 
@@ -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, kDispatchEvent } from '../handlers/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
- const connectionEvent = new MessageEvent('connection', {
23
- data: connection,
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
- // First, filter only those WebSocket handlers that
27
- // match the "ws.link()" endpoint predicate. Don't dispatch
28
- // anything yet so the logger can be attached to the connection
29
- // before it potentially sends events.
30
- const matchingHandlers: Array<WebSocketHandler> = []
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
- for (const handler of handlers) {
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
- if (matchingHandlers.length > 0) {
47
- options?.onMockedConnection(connection)
48
-
49
- // Iterate over the handlers and forward the connection
50
- // event to WebSocket event handlers. This is equivalent
51
- // to dispatching that event onto multiple listeners.
52
- for (const handler of matchingHandlers) {
53
- handler[kDispatchEvent](connectionEvent)
54
- }
55
- } else {
56
- // Construct a request representing this WebSocket connection.
57
- const request = new Request(connection.client.url, {
58
- headers: {
59
- upgrade: 'websocket',
60
- connection: 'upgrade',
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
- options?.onPassthroughConnection(connection)
58
+ options?.onPassthroughConnection(connection)
77
59
 
78
- // If none of the "ws" handlers matched,
79
- // establish the WebSocket connection as-is.
80
- connection.server.connect()
81
- }
60
+ // If none of the "ws" handlers matched,
61
+ // establish the WebSocket connection as-is.
62
+ connection.server.connect()
82
63
  })
83
64
  }
@@ -15,5 +15,5 @@ export function getMessageLength(data: WebSocketData): number {
15
15
  return data.byteLength
16
16
  }
17
17
 
18
- return new Blob([data]).size
18
+ return new Blob([data as any]).size
19
19
  }
@@ -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