msw 2.12.13 → 2.13.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.
Files changed (272) hide show
  1. package/lib/browser/index.d.mts +29 -19
  2. package/lib/browser/index.d.ts +29 -19
  3. package/lib/browser/index.js +1763 -1321
  4. package/lib/browser/index.js.map +1 -1
  5. package/lib/browser/index.mjs +1769 -1321
  6. package/lib/browser/index.mjs.map +1 -1
  7. package/lib/core/{HttpResponse-Dj6ibgFJ.d.ts → HttpResponse-CksOMVAa.d.ts} +5 -5
  8. package/lib/core/{HttpResponse-Be4eT3x6.d.mts → HttpResponse-DlRR1D-f.d.mts} +5 -5
  9. package/lib/core/HttpResponse.d.mts +1 -1
  10. package/lib/core/HttpResponse.d.ts +1 -1
  11. package/lib/core/experimental/compat.d.mts +17 -0
  12. package/lib/core/experimental/compat.d.ts +17 -0
  13. package/lib/core/experimental/compat.js +54 -0
  14. package/lib/core/experimental/compat.js.map +1 -0
  15. package/lib/core/experimental/compat.mjs +36 -0
  16. package/lib/core/experimental/compat.mjs.map +1 -0
  17. package/lib/core/experimental/define-network.d.mts +75 -0
  18. package/lib/core/experimental/define-network.d.ts +75 -0
  19. package/lib/core/experimental/define-network.js +124 -0
  20. package/lib/core/experimental/define-network.js.map +1 -0
  21. package/lib/core/experimental/define-network.mjs +107 -0
  22. package/lib/core/experimental/define-network.mjs.map +1 -0
  23. package/lib/core/experimental/frames/http-frame.d.mts +77 -0
  24. package/lib/core/experimental/frames/http-frame.d.ts +77 -0
  25. package/lib/core/experimental/frames/http-frame.js +194 -0
  26. package/lib/core/experimental/frames/http-frame.js.map +1 -0
  27. package/lib/core/experimental/frames/http-frame.mjs +176 -0
  28. package/lib/core/experimental/frames/http-frame.mjs.map +1 -0
  29. package/lib/core/experimental/frames/network-frame.d.mts +12 -0
  30. package/lib/core/experimental/frames/network-frame.d.ts +12 -0
  31. package/lib/core/{handlers/common.js → experimental/frames/network-frame.js} +19 -3
  32. package/lib/core/experimental/frames/network-frame.js.map +1 -0
  33. package/lib/core/experimental/frames/network-frame.mjs +13 -0
  34. package/lib/core/experimental/frames/network-frame.mjs.map +1 -0
  35. package/lib/core/experimental/frames/websocket-frame.d.mts +55 -0
  36. package/lib/core/experimental/frames/websocket-frame.d.ts +55 -0
  37. package/lib/core/experimental/frames/websocket-frame.js +129 -0
  38. package/lib/core/experimental/frames/websocket-frame.js.map +1 -0
  39. package/lib/core/experimental/frames/websocket-frame.mjs +116 -0
  40. package/lib/core/experimental/frames/websocket-frame.mjs.map +1 -0
  41. package/lib/core/experimental/handlers-controller.d.mts +35 -0
  42. package/lib/core/experimental/handlers-controller.d.ts +35 -0
  43. package/lib/core/experimental/handlers-controller.js +121 -0
  44. package/lib/core/experimental/handlers-controller.js.map +1 -0
  45. package/lib/core/experimental/handlers-controller.mjs +101 -0
  46. package/lib/core/experimental/handlers-controller.mjs.map +1 -0
  47. package/lib/core/experimental/index.d.mts +17 -0
  48. package/lib/core/experimental/index.d.ts +17 -0
  49. package/lib/core/experimental/index.js +36 -0
  50. package/lib/core/experimental/index.js.map +1 -0
  51. package/lib/core/experimental/index.mjs +20 -0
  52. package/lib/core/experimental/index.mjs.map +1 -0
  53. package/lib/core/experimental/on-unhandled-frame.d.mts +12 -0
  54. package/lib/core/experimental/on-unhandled-frame.d.ts +12 -0
  55. package/lib/core/experimental/on-unhandled-frame.js +90 -0
  56. package/lib/core/experimental/on-unhandled-frame.js.map +1 -0
  57. package/lib/core/experimental/on-unhandled-frame.mjs +70 -0
  58. package/lib/core/experimental/on-unhandled-frame.mjs.map +1 -0
  59. package/lib/core/experimental/request-utils.d.mts +12 -0
  60. package/lib/core/experimental/request-utils.d.ts +12 -0
  61. package/lib/core/experimental/request-utils.js +50 -0
  62. package/lib/core/experimental/request-utils.js.map +1 -0
  63. package/lib/core/experimental/request-utils.mjs +30 -0
  64. package/lib/core/experimental/request-utils.mjs.map +1 -0
  65. package/lib/core/experimental/setup-api.d.mts +33 -0
  66. package/lib/core/experimental/setup-api.d.ts +33 -0
  67. package/lib/core/experimental/setup-api.js +61 -0
  68. package/lib/core/experimental/setup-api.js.map +1 -0
  69. package/lib/core/experimental/setup-api.mjs +43 -0
  70. package/lib/core/experimental/setup-api.mjs.map +1 -0
  71. package/lib/core/experimental/sources/interceptor-source.d.mts +28 -0
  72. package/lib/core/experimental/sources/interceptor-source.d.ts +28 -0
  73. package/lib/core/experimental/sources/interceptor-source.js +142 -0
  74. package/lib/core/experimental/sources/interceptor-source.js.map +1 -0
  75. package/lib/core/experimental/sources/interceptor-source.mjs +124 -0
  76. package/lib/core/experimental/sources/interceptor-source.mjs.map +1 -0
  77. package/lib/core/experimental/sources/network-source.d.mts +31 -0
  78. package/lib/core/experimental/sources/network-source.d.ts +31 -0
  79. package/lib/core/experimental/sources/network-source.js +50 -0
  80. package/lib/core/experimental/sources/network-source.js.map +1 -0
  81. package/lib/core/experimental/sources/network-source.mjs +30 -0
  82. package/lib/core/experimental/sources/network-source.mjs.map +1 -0
  83. package/lib/core/getResponse.d.mts +1 -1
  84. package/lib/core/getResponse.d.ts +1 -1
  85. package/lib/core/graphql.d.mts +1 -1
  86. package/lib/core/graphql.d.ts +1 -1
  87. package/lib/core/handlers/GraphQLHandler.d.mts +1 -1
  88. package/lib/core/handlers/GraphQLHandler.d.ts +1 -1
  89. package/lib/core/handlers/HttpHandler.d.mts +1 -1
  90. package/lib/core/handlers/HttpHandler.d.ts +1 -1
  91. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  92. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  93. package/lib/core/handlers/RequestHandler.js +5 -6
  94. package/lib/core/handlers/RequestHandler.js.map +1 -1
  95. package/lib/core/handlers/RequestHandler.mjs +5 -6
  96. package/lib/core/handlers/RequestHandler.mjs.map +1 -1
  97. package/lib/core/handlers/WebSocketHandler.d.mts +8 -4
  98. package/lib/core/handlers/WebSocketHandler.d.ts +8 -4
  99. package/lib/core/handlers/WebSocketHandler.js +18 -5
  100. package/lib/core/handlers/WebSocketHandler.js.map +1 -1
  101. package/lib/core/handlers/WebSocketHandler.mjs +18 -5
  102. package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
  103. package/lib/core/http.d.mts +1 -1
  104. package/lib/core/http.d.ts +1 -1
  105. package/lib/core/index.d.mts +7 -12
  106. package/lib/core/index.d.ts +7 -12
  107. package/lib/core/index.js +2 -2
  108. package/lib/core/index.js.map +1 -1
  109. package/lib/core/index.mjs +1 -1
  110. package/lib/core/index.mjs.map +1 -1
  111. package/lib/core/network-frame-B7A0ggXE.d.mts +56 -0
  112. package/lib/core/network-frame-usYiHS0K.d.ts +56 -0
  113. package/lib/core/passthrough.d.mts +1 -1
  114. package/lib/core/passthrough.d.ts +1 -1
  115. package/lib/core/sharedOptions.d.mts +6 -2
  116. package/lib/core/sharedOptions.d.ts +6 -2
  117. package/lib/core/sharedOptions.js.map +1 -1
  118. package/lib/core/sse.d.mts +1 -1
  119. package/lib/core/sse.d.ts +1 -1
  120. package/lib/core/sse.js.map +1 -1
  121. package/lib/core/sse.mjs.map +1 -1
  122. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  123. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  124. package/lib/core/utils/cookieStore.js.map +1 -1
  125. package/lib/core/utils/cookieStore.mjs.map +1 -1
  126. package/lib/core/utils/executeHandlers.d.mts +1 -1
  127. package/lib/core/utils/executeHandlers.d.ts +1 -1
  128. package/lib/core/utils/handleRequest.d.mts +2 -1
  129. package/lib/core/utils/handleRequest.d.ts +2 -1
  130. package/lib/core/utils/internal/isHandlerKind.d.mts +3 -3
  131. package/lib/core/utils/internal/isHandlerKind.d.ts +3 -3
  132. package/lib/core/utils/internal/isHandlerKind.js +2 -1
  133. package/lib/core/utils/internal/isHandlerKind.js.map +1 -1
  134. package/lib/core/utils/internal/isHandlerKind.mjs +2 -1
  135. package/lib/core/utils/internal/isHandlerKind.mjs.map +1 -1
  136. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +1 -1
  137. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +1 -1
  138. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  139. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  140. package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
  141. package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
  142. package/lib/core/utils/matching/matchRequestUrl.js +1 -1
  143. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  144. package/lib/core/utils/matching/matchRequestUrl.mjs +1 -1
  145. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  146. package/lib/core/utils/request/onUnhandledRequest.d.mts +2 -2
  147. package/lib/core/utils/request/onUnhandledRequest.d.ts +2 -2
  148. package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
  149. package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
  150. package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
  151. package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
  152. package/lib/core/ws/handleWebSocketEvent.js +1 -1
  153. package/lib/core/ws/handleWebSocketEvent.js.map +1 -1
  154. package/lib/core/ws/handleWebSocketEvent.mjs +1 -1
  155. package/lib/core/ws/handleWebSocketEvent.mjs.map +1 -1
  156. package/lib/core/ws/utils/attachWebSocketLogger.d.mts +1 -1
  157. package/lib/core/ws/utils/attachWebSocketLogger.d.ts +1 -1
  158. package/lib/core/ws/utils/attachWebSocketLogger.js +39 -10
  159. package/lib/core/ws/utils/attachWebSocketLogger.js.map +1 -1
  160. package/lib/core/ws/utils/attachWebSocketLogger.mjs +39 -10
  161. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +1 -1
  162. package/lib/core/ws.d.mts +3 -3
  163. package/lib/core/ws.d.ts +3 -3
  164. package/lib/core/ws.js.map +1 -1
  165. package/lib/core/ws.mjs.map +1 -1
  166. package/lib/iife/index.js +2022 -1433
  167. package/lib/iife/index.js.map +1 -1
  168. package/lib/mockServiceWorker.js +1 -1
  169. package/lib/native/index.d.mts +21 -29
  170. package/lib/native/index.d.ts +21 -29
  171. package/lib/native/index.js +48 -116
  172. package/lib/native/index.js.map +1 -1
  173. package/lib/native/index.mjs +51 -118
  174. package/lib/native/index.mjs.map +1 -1
  175. package/lib/node/index.d.mts +55 -33
  176. package/lib/node/index.d.ts +55 -33
  177. package/lib/node/index.js +152 -154
  178. package/lib/node/index.js.map +1 -1
  179. package/lib/node/index.mjs +156 -156
  180. package/lib/node/index.mjs.map +1 -1
  181. package/package.json +10 -2
  182. package/src/browser/{setupWorker/glossary.ts → glossary.ts} +16 -33
  183. package/src/browser/index.ts +2 -3
  184. package/src/browser/{setupWorker/setupWorker.node.test.ts → setup-worker.node.test.ts} +2 -4
  185. package/src/browser/setup-worker.ts +148 -0
  186. package/src/browser/sources/fallback-http-source.ts +56 -0
  187. package/src/browser/sources/service-worker-source.ts +455 -0
  188. package/src/browser/tsconfig.browser.json +7 -2
  189. package/src/browser/utils/deserializeRequest.ts +1 -1
  190. package/src/browser/{setupWorker/start/utils/getWorkerByRegistration.ts → utils/get-worker-by-registration.ts} +3 -1
  191. package/src/browser/{setupWorker/start/utils/getWorkerInstance.ts → utils/get-worker-instance.ts} +4 -4
  192. package/src/browser/utils/pruneGetRequestBody.test.ts +1 -3
  193. package/src/browser/utils/pruneGetRequestBody.ts +1 -1
  194. package/src/browser/utils/validate-worker-scope.ts +19 -0
  195. package/src/browser/utils/workerChannel.ts +2 -2
  196. package/src/core/experimental/compat.ts +50 -0
  197. package/src/core/experimental/define-network.test.ts +124 -0
  198. package/src/core/experimental/define-network.ts +215 -0
  199. package/src/core/experimental/frames/http-frame.test.ts +360 -0
  200. package/src/core/experimental/frames/http-frame.ts +271 -0
  201. package/src/core/experimental/frames/network-frame.ts +64 -0
  202. package/src/core/experimental/frames/websocket-frame.test.ts +280 -0
  203. package/src/core/experimental/frames/websocket-frame.ts +188 -0
  204. package/src/core/experimental/handlers-controller.test.ts +198 -0
  205. package/src/core/experimental/handlers-controller.ts +145 -0
  206. package/src/core/experimental/index.ts +16 -0
  207. package/src/core/experimental/on-unhandled-frame.test.ts +360 -0
  208. package/src/core/experimental/on-unhandled-frame.ts +110 -0
  209. package/src/core/experimental/request-utils.test.ts +70 -0
  210. package/src/core/experimental/request-utils.ts +39 -0
  211. package/src/core/experimental/setup-api.ts +59 -0
  212. package/src/core/experimental/sources/interceptor-source.ts +185 -0
  213. package/src/core/experimental/sources/network-source.test.ts +74 -0
  214. package/src/core/experimental/sources/network-source.ts +56 -0
  215. package/src/core/handlers/RequestHandler.ts +9 -10
  216. package/src/core/handlers/WebSocketHandler.ts +27 -11
  217. package/src/core/index.ts +3 -7
  218. package/src/core/sharedOptions.ts +9 -4
  219. package/src/core/sse.ts +1 -1
  220. package/src/core/utils/cookieStore.ts +2 -1
  221. package/src/core/utils/internal/isHandlerKind.test.ts +20 -22
  222. package/src/core/utils/internal/isHandlerKind.ts +5 -9
  223. package/src/core/utils/matching/matchRequestUrl.test.ts +87 -3
  224. package/src/core/utils/matching/matchRequestUrl.ts +2 -2
  225. package/src/core/utils/request/onUnhandledRequest.ts +2 -2
  226. package/src/core/ws/WebSocketClientManager.test.ts +2 -10
  227. package/src/core/ws/handleWebSocketEvent.ts +5 -1
  228. package/src/core/ws/utils/attachWebSocketLogger.ts +43 -11
  229. package/src/core/ws.test.ts +1 -3
  230. package/src/core/ws.ts +6 -6
  231. package/src/iife/index.ts +1 -1
  232. package/src/native/index.ts +34 -11
  233. package/src/node/async-handlers-controller.test.ts +50 -0
  234. package/src/node/async-handlers-controller.ts +69 -0
  235. package/src/node/glossary.ts +19 -18
  236. package/src/node/index.ts +6 -2
  237. package/src/node/setup-server-common.ts +100 -0
  238. package/src/node/setup-server.ts +91 -0
  239. package/src/tsconfig.core.json +8 -0
  240. package/src/tsconfig.node.json +8 -3
  241. package/src/tsconfig.src.json +0 -2
  242. package/src/tsconfig.worker.json +2 -1
  243. package/lib/core/SetupApi.d.mts +0 -44
  244. package/lib/core/SetupApi.d.ts +0 -44
  245. package/lib/core/SetupApi.js +0 -112
  246. package/lib/core/SetupApi.js.map +0 -1
  247. package/lib/core/SetupApi.mjs +0 -92
  248. package/lib/core/SetupApi.mjs.map +0 -1
  249. package/lib/core/handlers/common.d.mts +0 -3
  250. package/lib/core/handlers/common.d.ts +0 -3
  251. package/lib/core/handlers/common.js.map +0 -1
  252. package/lib/core/handlers/common.mjs +0 -1
  253. package/lib/core/handlers/common.mjs.map +0 -1
  254. package/src/browser/setupWorker/setupWorker.ts +0 -184
  255. package/src/browser/setupWorker/start/createFallbackRequestListener.ts +0 -71
  256. package/src/browser/setupWorker/start/createRequestListener.ts +0 -138
  257. package/src/browser/setupWorker/start/createResponseListener.ts +0 -57
  258. package/src/browser/setupWorker/start/createStartHandler.ts +0 -137
  259. package/src/browser/setupWorker/start/utils/enableMocking.ts +0 -30
  260. package/src/browser/setupWorker/start/utils/prepareStartHandler.test.ts +0 -59
  261. package/src/browser/setupWorker/start/utils/prepareStartHandler.ts +0 -44
  262. package/src/browser/setupWorker/start/utils/printStartMessage.test.ts +0 -84
  263. package/src/browser/setupWorker/start/utils/printStartMessage.ts +0 -51
  264. package/src/browser/setupWorker/start/utils/validateWorkerScope.ts +0 -18
  265. package/src/browser/setupWorker/stop/utils/printStopMessage.test.ts +0 -26
  266. package/src/browser/setupWorker/stop/utils/printStopMessage.ts +0 -13
  267. package/src/browser/utils/checkWorkerIntegrity.ts +0 -42
  268. package/src/core/SetupApi.ts +0 -127
  269. package/src/core/handlers/common.ts +0 -1
  270. package/src/node/SetupServerApi.ts +0 -87
  271. package/src/node/SetupServerCommonApi.ts +0 -169
  272. package/src/node/setupServer.ts +0 -15
@@ -0,0 +1,145 @@
1
+ import { invariant } from 'outvariant'
2
+ import { type RequestHandler } from '../handlers/RequestHandler'
3
+ import { type WebSocketHandler } from '../handlers/WebSocketHandler'
4
+ import { devUtils } from '../utils/internal/devUtils'
5
+
6
+ export type AnyHandler = RequestHandler | WebSocketHandler
7
+ export type HandlersMap = Partial<Record<AnyHandler['kind'], Array<AnyHandler>>>
8
+
9
+ export function groupHandlersByKind(handlers: Array<AnyHandler>): HandlersMap {
10
+ const groups: HandlersMap = {}
11
+
12
+ /**
13
+ * @note `Object.groupBy` is not implemented in Node.js v20.
14
+ */
15
+ for (const handler of handlers) {
16
+ ;(groups[handler.kind] ||= []).push(handler)
17
+ }
18
+
19
+ return groups
20
+ }
21
+
22
+ export interface HandlersControllerState {
23
+ initialHandlers: HandlersMap
24
+ handlers: HandlersMap
25
+ }
26
+
27
+ export abstract class HandlersController {
28
+ protected getInitialState(
29
+ initialHandlers: Array<AnyHandler>,
30
+ ): HandlersControllerState {
31
+ invariant(
32
+ this.#validateHandlers(initialHandlers),
33
+ devUtils.formatMessage(
34
+ '[MSW] Failed to apply given request handlers: invalid input. Did you forget to spread the request handlers Array?',
35
+ ),
36
+ )
37
+
38
+ const normalizedInitialHandlers = groupHandlersByKind(initialHandlers)
39
+
40
+ return {
41
+ initialHandlers: normalizedInitialHandlers,
42
+ handlers: { ...normalizedInitialHandlers },
43
+ }
44
+ }
45
+
46
+ protected abstract getState(): HandlersControllerState
47
+ protected abstract setState(nextState: Partial<HandlersControllerState>): void
48
+
49
+ public currentHandlers(): Array<AnyHandler> {
50
+ return Object.values(this.getState().handlers)
51
+ .flat()
52
+ .filter((handler) => handler != null)
53
+ }
54
+
55
+ public getHandlersByKind(kind: AnyHandler['kind']): Array<AnyHandler> {
56
+ return this.getState().handlers[kind] || []
57
+ }
58
+
59
+ public use(nextHandlers: Array<AnyHandler>): void {
60
+ invariant(
61
+ this.#validateHandlers(nextHandlers),
62
+ devUtils.formatMessage(
63
+ '[MSW] Failed to call "use()" with the given request handlers: invalid input. Did you forget to spread the array of request handlers?',
64
+ ),
65
+ )
66
+
67
+ if (nextHandlers.length === 0) {
68
+ return
69
+ }
70
+
71
+ const { handlers } = this.getState()
72
+
73
+ // Iterate over next handlers and prepend them to their respective lists.
74
+ // Iterate in a reverse order to the keep the order of the runtime handlers as provided.
75
+ for (let i = nextHandlers.length - 1; i >= 0; i--) {
76
+ const handler = nextHandlers[i]
77
+ handlers[handler.kind] = handlers[handler.kind]
78
+ ? [handler, ...handlers[handler.kind]!]
79
+ : [handler]
80
+ }
81
+
82
+ this.setState({ handlers })
83
+ }
84
+
85
+ public reset(nextHandlers: Array<AnyHandler>): void {
86
+ invariant(
87
+ nextHandlers.length > 0 ? this.#validateHandlers(nextHandlers) : true,
88
+ devUtils.formatMessage(
89
+ 'Failed to replace initial handlers during reset: invalid handlers. Did you forget to spread the handlers array?',
90
+ ),
91
+ )
92
+
93
+ const { initialHandlers } = this.getState()
94
+
95
+ if (nextHandlers.length === 0) {
96
+ this.setState({
97
+ handlers: { ...initialHandlers },
98
+ })
99
+
100
+ return
101
+ }
102
+
103
+ const normalizedNextHandlers = groupHandlersByKind(nextHandlers)
104
+
105
+ this.setState({
106
+ initialHandlers: normalizedNextHandlers,
107
+ handlers: { ...normalizedNextHandlers },
108
+ })
109
+ }
110
+
111
+ #validateHandlers(handlers: Array<AnyHandler>): boolean {
112
+ return handlers.every((handler) => !Array.isArray(handler))
113
+ }
114
+ }
115
+
116
+ export class InMemoryHandlersController extends HandlersController {
117
+ #handlers: HandlersMap
118
+ #initialHandlers: HandlersMap
119
+
120
+ constructor(initialHandlers: Array<AnyHandler>) {
121
+ super()
122
+
123
+ const initialState = this.getInitialState(initialHandlers)
124
+
125
+ this.#initialHandlers = initialState.initialHandlers
126
+ this.#handlers = initialState.handlers
127
+ }
128
+
129
+ protected getState(): HandlersControllerState {
130
+ return {
131
+ initialHandlers: this.#initialHandlers,
132
+ handlers: this.#handlers,
133
+ }
134
+ }
135
+
136
+ protected setState(nextState: Partial<HandlersControllerState>): void {
137
+ if (nextState.initialHandlers) {
138
+ this.#initialHandlers = nextState.initialHandlers
139
+ }
140
+
141
+ if (nextState.handlers) {
142
+ this.#handlers = nextState.handlers
143
+ }
144
+ }
145
+ }
@@ -0,0 +1,16 @@
1
+ export { defineNetwork, DefineNetworkOptions } from './define-network'
2
+
3
+ /* Network sources */
4
+ export { NetworkSource } from './sources/network-source'
5
+ export { InterceptorSource } from './sources/interceptor-source'
6
+
7
+ /* Frames */
8
+ export { NetworkFrame } from './frames/network-frame'
9
+ export {
10
+ HttpNetworkFrame,
11
+ type HttpNetworkFrameEventMap,
12
+ } from './frames/http-frame'
13
+ export {
14
+ WebSocketNetworkFrame,
15
+ type WebSocketNetworkFrameEventMap,
16
+ } from './frames/websocket-frame'
@@ -0,0 +1,360 @@
1
+ // @vitest-environment node
2
+ import type {
3
+ WebSocketClientConnection,
4
+ WebSocketServerConnection,
5
+ } from '@mswjs/interceptors/WebSocket'
6
+ import { HttpNetworkFrame } from './frames/http-frame'
7
+ import { WebSocketNetworkFrame } from './frames/websocket-frame'
8
+ import {
9
+ executeUnhandledFrameHandle,
10
+ UnhandledFrameCallback,
11
+ } from './on-unhandled-frame'
12
+
13
+ beforeAll(() => {
14
+ vi.spyOn(console, 'warn').mockImplementation(() => void 0)
15
+ vi.spyOn(console, 'error').mockImplementation(() => void 0)
16
+ })
17
+
18
+ afterEach(() => {
19
+ vi.clearAllMocks()
20
+ })
21
+
22
+ afterAll(() => {
23
+ vi.restoreAllMocks()
24
+ })
25
+
26
+ class TestHttpFrame extends HttpNetworkFrame {
27
+ constructor(request: Request) {
28
+ super({ request })
29
+ }
30
+
31
+ respondWith = () => {}
32
+ errorWith = () => {}
33
+ passthrough = () => {}
34
+ }
35
+
36
+ class TestWebSocketFrame extends WebSocketNetworkFrame {
37
+ constructor() {
38
+ super({
39
+ connection: {
40
+ client: {
41
+ url: new URL('wss://localhost/test'),
42
+ } as WebSocketClientConnection,
43
+ server: {} as WebSocketServerConnection,
44
+ info: { protocols: [] },
45
+ },
46
+ })
47
+ }
48
+
49
+ passthrough = () => {}
50
+ errorWith = () => {}
51
+ }
52
+
53
+ it('does not print any warnings or errors using the "bypass" strategy', async () => {
54
+ await expect(
55
+ executeUnhandledFrameHandle(
56
+ new TestHttpFrame(new Request('http://localhost/test')),
57
+ 'bypass',
58
+ ),
59
+ ).resolves.toBeUndefined()
60
+ expect(console.warn).not.toHaveBeenCalled()
61
+ expect(console.error).not.toHaveBeenCalled()
62
+ })
63
+
64
+ it('prints a warning for the HTTP frame using the "warn" strategy', async () => {
65
+ await expect(
66
+ executeUnhandledFrameHandle(
67
+ new TestHttpFrame(new Request('http://localhost/test')),
68
+ 'warn',
69
+ ),
70
+ ).resolves.toBeUndefined()
71
+
72
+ expect.soft(console.warn).toHaveBeenCalledOnce()
73
+ expect(console.warn).toHaveBeenCalledWith(
74
+ `[MSW] Warning: intercepted a request without a matching request handler:
75
+
76
+ • GET http://localhost/test
77
+
78
+ If you still wish to intercept this unhandled request, please create a request handler for it.
79
+ Read more: https://mswjs.io/docs/http/intercepting-requests`,
80
+ )
81
+ expect(console.error).not.toHaveBeenCalled()
82
+ })
83
+
84
+ it('rejects and prints an error for the HTTP frame using the "error" strategy', async () => {
85
+ await expect(
86
+ executeUnhandledFrameHandle(
87
+ new TestHttpFrame(new Request('http://localhost/test')),
88
+ 'error',
89
+ ),
90
+ ).rejects.toThrow(
91
+ `[MSW] Cannot bypass a request when using the "error" strategy for the "onUnhandledRequest" option.`,
92
+ )
93
+
94
+ expect.soft(console.error).toHaveBeenCalledOnce()
95
+ expect(console.error).toHaveBeenCalledWith(
96
+ `[MSW] Error: intercepted a request without a matching request handler:
97
+
98
+ • GET http://localhost/test
99
+
100
+ If you still wish to intercept this unhandled request, please create a request handler for it.
101
+ Read more: https://mswjs.io/docs/http/intercepting-requests`,
102
+ )
103
+ expect(console.warn).not.toHaveBeenCalled()
104
+ })
105
+
106
+ it('invokes the custom callback for the HTTP frame', async () => {
107
+ const callback = vi.fn()
108
+ const frame = new TestHttpFrame(new Request('http://localhost/test'))
109
+
110
+ await expect(
111
+ executeUnhandledFrameHandle(frame, callback),
112
+ ).resolves.toBeUndefined()
113
+
114
+ expect(callback).toHaveBeenCalledOnce()
115
+ expect(callback).toHaveBeenCalledWith({
116
+ defaults: {
117
+ warn: expect.any(Function),
118
+ error: expect.any(Function),
119
+ },
120
+ frame,
121
+ })
122
+ })
123
+
124
+ it('does not print anything for common asset HTTP requests', async () => {
125
+ await expect(
126
+ executeUnhandledFrameHandle(
127
+ new TestHttpFrame(new Request('http://localhost/image.png')),
128
+ 'warn',
129
+ ),
130
+ ).resolves.toBeUndefined()
131
+
132
+ expect(console.warn).not.toHaveBeenCalled()
133
+ expect(console.error).not.toHaveBeenCalled()
134
+
135
+ await expect(
136
+ executeUnhandledFrameHandle(
137
+ new TestHttpFrame(new Request('http://localhost/image.png')),
138
+ 'error',
139
+ ),
140
+ ).resolves.toBeUndefined()
141
+
142
+ expect(console.warn).not.toHaveBeenCalled()
143
+ expect(console.error).not.toHaveBeenCalled()
144
+ })
145
+
146
+ it('delegates common asset HTTP requests handling to the custom callback', async () => {
147
+ const callback = vi.fn()
148
+ const frame = new TestHttpFrame(new Request('http://localhost/image.png'))
149
+
150
+ await expect(
151
+ executeUnhandledFrameHandle(frame, callback),
152
+ ).resolves.toBeUndefined()
153
+
154
+ expect(callback).toHaveBeenCalledOnce()
155
+ expect(callback).toHaveBeenCalledWith({
156
+ defaults: {
157
+ warn: expect.any(Function),
158
+ error: expect.any(Function),
159
+ },
160
+ frame,
161
+ })
162
+ })
163
+
164
+ it('supports printing the default warning in the custom callback for the HTTP frame', async () => {
165
+ const callback = vi.fn<UnhandledFrameCallback>(({ defaults }) => {
166
+ defaults.warn()
167
+ })
168
+ const frame = new TestHttpFrame(new Request('http://localhost/test'))
169
+
170
+ await expect(
171
+ executeUnhandledFrameHandle(frame, callback),
172
+ ).resolves.toBeUndefined()
173
+
174
+ expect(callback).toHaveBeenCalledOnce()
175
+ expect(callback).toHaveBeenCalledWith({
176
+ defaults: {
177
+ warn: expect.any(Function),
178
+ error: expect.any(Function),
179
+ },
180
+ frame,
181
+ })
182
+ expect.soft(console.warn).toHaveBeenCalledOnce()
183
+ expect(console.warn).toHaveBeenCalledWith(
184
+ `[MSW] Warning: intercepted a request without a matching request handler:
185
+
186
+ • GET http://localhost/test
187
+
188
+ If you still wish to intercept this unhandled request, please create a request handler for it.
189
+ Read more: https://mswjs.io/docs/http/intercepting-requests`,
190
+ )
191
+ expect(console.error).not.toHaveBeenCalled()
192
+ })
193
+
194
+ it('supports printing the default error in the custom callback for the HTTP frame', async () => {
195
+ const callback = vi.fn<UnhandledFrameCallback>(({ defaults }) => {
196
+ defaults.error()
197
+ })
198
+ const frame = new TestHttpFrame(new Request('http://localhost/test'))
199
+
200
+ await expect(
201
+ executeUnhandledFrameHandle(frame, callback),
202
+ ).resolves.toBeUndefined()
203
+
204
+ expect(callback).toHaveBeenCalledOnce()
205
+ expect(callback).toHaveBeenCalledWith({
206
+ defaults: {
207
+ warn: expect.any(Function),
208
+ error: expect.any(Function),
209
+ },
210
+ frame,
211
+ })
212
+ expect.soft(console.error).toHaveBeenCalledOnce()
213
+ expect(console.error).toHaveBeenCalledWith(
214
+ `[MSW] Error: intercepted a request without a matching request handler:
215
+
216
+ • GET http://localhost/test
217
+
218
+ If you still wish to intercept this unhandled request, please create a request handler for it.
219
+ Read more: https://mswjs.io/docs/http/intercepting-requests`,
220
+ )
221
+ expect(console.warn).not.toHaveBeenCalled()
222
+ })
223
+
224
+ it('throws if given an unknown strategy for the HTTP frame', async () => {
225
+ await expect(
226
+ executeUnhandledFrameHandle(
227
+ new TestHttpFrame(new Request('http://localhost/test')),
228
+ // @ts-expect-error Intentionally invalid value.
229
+ 'intentionally-invalid',
230
+ ),
231
+ ).rejects.toThrow(
232
+ `[MSW] Failed to react to an unhandled network frame: unknown strategy "intentionally-invalid". Please provide one of the supported strategies ("bypass", "warn", "error") or a custom callback function as the value of the "onUnhandledRequest" option.`,
233
+ )
234
+ })
235
+
236
+ it('prints a warning for the WebSocket frame using the "warn" strategy', async () => {
237
+ await expect(
238
+ executeUnhandledFrameHandle(new TestWebSocketFrame(), 'warn'),
239
+ ).resolves.toBeUndefined()
240
+
241
+ expect.soft(console.warn).toHaveBeenCalledOnce()
242
+ expect(console.warn).toHaveBeenCalledWith(
243
+ `[MSW] Warning: intercepted a WebSocket connection without a matching event handler:
244
+
245
+ • wss://localhost/test
246
+
247
+ If you still wish to intercept this unhandled connection, please create an event handler for it.
248
+ Read more: https://mswjs.io/docs/websocket`,
249
+ )
250
+ expect(console.error).not.toHaveBeenCalled()
251
+ })
252
+
253
+ it('rejects and prints an error for the WebSocket frame using the "error" strategy', async () => {
254
+ await expect(
255
+ executeUnhandledFrameHandle(new TestWebSocketFrame(), 'error'),
256
+ ).rejects.toThrow(
257
+ `[MSW] Cannot bypass a request when using the "error" strategy for the "onUnhandledRequest" option.`,
258
+ )
259
+
260
+ expect.soft(console.error).toHaveBeenCalledOnce()
261
+ expect(console.error).toHaveBeenCalledWith(
262
+ `[MSW] Error: intercepted a WebSocket connection without a matching event handler:
263
+
264
+ • wss://localhost/test
265
+
266
+ If you still wish to intercept this unhandled connection, please create an event handler for it.
267
+ Read more: https://mswjs.io/docs/websocket`,
268
+ )
269
+ expect(console.warn).not.toHaveBeenCalled()
270
+ })
271
+
272
+ it('invokes the custom callback for the WebSocket frame', async () => {
273
+ const callback = vi.fn()
274
+ const frame = new TestWebSocketFrame()
275
+
276
+ await expect(
277
+ executeUnhandledFrameHandle(frame, callback),
278
+ ).resolves.toBeUndefined()
279
+
280
+ expect(callback).toHaveBeenCalledOnce()
281
+ expect(callback).toHaveBeenCalledWith({
282
+ defaults: {
283
+ warn: expect.any(Function),
284
+ error: expect.any(Function),
285
+ },
286
+ frame,
287
+ })
288
+ })
289
+
290
+ it('throws if given an unknown strategy for the WebSocket frame', async () => {
291
+ await expect(
292
+ executeUnhandledFrameHandle(
293
+ new TestWebSocketFrame(),
294
+ // @ts-expect-error Intentionally invalid value.
295
+ 'intentionally-invalid',
296
+ ),
297
+ ).rejects.toThrow(
298
+ `[MSW] Failed to react to an unhandled network frame: unknown strategy "intentionally-invalid". Please provide one of the supported strategies ("bypass", "warn", "error") or a custom callback function as the value of the "onUnhandledRequest" option.`,
299
+ )
300
+ })
301
+
302
+ it('supports printing the default warning in the custom callback for the HTTP frame', async () => {
303
+ const callback = vi.fn<UnhandledFrameCallback>(({ defaults }) => {
304
+ defaults.warn()
305
+ })
306
+ const frame = new TestWebSocketFrame()
307
+
308
+ await expect(
309
+ executeUnhandledFrameHandle(frame, callback),
310
+ ).resolves.toBeUndefined()
311
+
312
+ expect(callback).toHaveBeenCalledOnce()
313
+ expect(callback).toHaveBeenCalledWith({
314
+ defaults: {
315
+ warn: expect.any(Function),
316
+ error: expect.any(Function),
317
+ },
318
+ frame,
319
+ })
320
+ expect.soft(console.warn).toHaveBeenCalledOnce()
321
+ expect(console.warn).toHaveBeenCalledWith(
322
+ `[MSW] Warning: intercepted a WebSocket connection without a matching event handler:
323
+
324
+ • wss://localhost/test
325
+
326
+ If you still wish to intercept this unhandled connection, please create an event handler for it.
327
+ Read more: https://mswjs.io/docs/websocket`,
328
+ )
329
+ expect(console.error).not.toHaveBeenCalled()
330
+ })
331
+
332
+ it('supports printing the default error in the custom callback for the HTTP frame', async () => {
333
+ const callback = vi.fn<UnhandledFrameCallback>(({ defaults }) => {
334
+ defaults.error()
335
+ })
336
+ const frame = new TestWebSocketFrame()
337
+
338
+ await expect(
339
+ executeUnhandledFrameHandle(frame, callback),
340
+ ).resolves.toBeUndefined()
341
+
342
+ expect(callback).toHaveBeenCalledOnce()
343
+ expect(callback).toHaveBeenCalledWith({
344
+ defaults: {
345
+ warn: expect.any(Function),
346
+ error: expect.any(Function),
347
+ },
348
+ frame,
349
+ })
350
+ expect.soft(console.error).toHaveBeenCalledOnce()
351
+ expect(console.error).toHaveBeenCalledWith(
352
+ `[MSW] Error: intercepted a WebSocket connection without a matching event handler:
353
+
354
+ • wss://localhost/test
355
+
356
+ If you still wish to intercept this unhandled connection, please create an event handler for it.
357
+ Read more: https://mswjs.io/docs/websocket`,
358
+ )
359
+ expect(console.warn).not.toHaveBeenCalled()
360
+ })
@@ -0,0 +1,110 @@
1
+ import { invariant } from 'outvariant'
2
+ import { isCommonAssetRequest } from '../isCommonAssetRequest'
3
+ import { devUtils, InternalError } from '../utils/internal/devUtils'
4
+ import { HttpNetworkFrame } from './frames/http-frame'
5
+ import { type AnyNetworkFrame } from './frames/network-frame'
6
+
7
+ export type UnhandledFrameHandle =
8
+ | UnhandledFrameStrategy
9
+ | UnhandledFrameCallback
10
+
11
+ export type UnhandledFrameStrategy = 'bypass' | 'warn' | 'error'
12
+
13
+ export type UnhandledFrameCallback = (args: {
14
+ frame: AnyNetworkFrame
15
+ defaults: UnhandledFrameDefaults
16
+ }) => Promise<void> | void
17
+
18
+ export type UnhandledFrameDefaults = {
19
+ warn: () => void
20
+ error: () => void
21
+ }
22
+
23
+ export async function executeUnhandledFrameHandle(
24
+ frame: AnyNetworkFrame,
25
+ handle: UnhandledFrameHandle,
26
+ ): Promise<void> {
27
+ const printStrategyMessage = async (
28
+ strategy: UnhandledFrameStrategy,
29
+ ): Promise<void> => {
30
+ if (strategy === 'bypass') {
31
+ return
32
+ }
33
+
34
+ const message = await frame.getUnhandledMessage()
35
+
36
+ switch (strategy) {
37
+ case 'warn': {
38
+ return devUtils.warn('Warning: %s', message)
39
+ }
40
+
41
+ case 'error': {
42
+ return devUtils.error('Error: %s', message)
43
+ }
44
+ }
45
+ }
46
+
47
+ const applyStrategy = async (
48
+ strategy: UnhandledFrameStrategy,
49
+ ): Promise<void> => {
50
+ invariant.as(
51
+ InternalError,
52
+ strategy === 'bypass' || strategy === 'warn' || strategy === 'error',
53
+ /**
54
+ * @fixme Rename "onUnhandledRequest" to "onUnhandledFrame" in the error message
55
+ * with the next major release.
56
+ */
57
+ devUtils.formatMessage(
58
+ 'Failed to react to an unhandled network frame: unknown strategy "%s". Please provide one of the supported strategies ("bypass", "warn", "error") or a custom callback function as the value of the "onUnhandledRequest" option.',
59
+ strategy,
60
+ ),
61
+ )
62
+
63
+ if (strategy === 'bypass') {
64
+ return
65
+ }
66
+
67
+ await printStrategyMessage(strategy)
68
+
69
+ if (strategy === 'error') {
70
+ return Promise.reject(
71
+ new InternalError(
72
+ devUtils.formatMessage(
73
+ 'Cannot bypass a request when using the "error" strategy for the "onUnhandledRequest" option.',
74
+ ),
75
+ ),
76
+ )
77
+ }
78
+ }
79
+
80
+ if (typeof handle === 'function') {
81
+ return handle({
82
+ frame,
83
+ defaults: {
84
+ warn: printStrategyMessage.bind(null, 'warn'),
85
+ /**
86
+ * @note The defaults only print the corresponding messages now.
87
+ * They do not affect the frame resolution (e.g. do not error the frame).
88
+ * That is only for backward compatibility reasons. In the future, these should
89
+ * be an alias to `applyStrategy.bind(null, 'error')` instead.
90
+ */
91
+ error: printStrategyMessage.bind(null, 'error'),
92
+ },
93
+ })
94
+ }
95
+
96
+ /**
97
+ * Ignore unhandled common HTTP assets.
98
+ * @note Calling this here applies the common assets check
99
+ * only to the scenarios when `onUnhandledFrame` was set to a predefined strategy.
100
+ * When using a custom function, you need to check for common assets manually.
101
+ */
102
+ if (
103
+ frame instanceof HttpNetworkFrame &&
104
+ isCommonAssetRequest(frame.data.request)
105
+ ) {
106
+ return
107
+ }
108
+
109
+ return applyStrategy(handle)
110
+ }
@@ -0,0 +1,70 @@
1
+ import {
2
+ deleteRequestPassthroughHeader,
3
+ isPassthroughResponse,
4
+ REQUEST_INTENTION_HEADER_NAME,
5
+ RequestIntention,
6
+ shouldBypassRequest,
7
+ } from './request-utils'
8
+
9
+ describe(shouldBypassRequest, () => {
10
+ it('returns true for a request with bypass header', () => {
11
+ expect(
12
+ shouldBypassRequest(
13
+ new Request('http://example.com', {
14
+ headers: {
15
+ accept: 'msw/passthrough',
16
+ },
17
+ }),
18
+ ),
19
+ ).toBe(true)
20
+ })
21
+
22
+ it('returns false for a regular request', () => {
23
+ expect(shouldBypassRequest(new Request('http://example.com'))).toBe(false)
24
+ })
25
+ })
26
+
27
+ describe(isPassthroughResponse, () => {
28
+ it('returns true for a passthrough response', () => {
29
+ expect(
30
+ isPassthroughResponse(
31
+ new Response(null, {
32
+ status: 302,
33
+ headers: {
34
+ [REQUEST_INTENTION_HEADER_NAME]: RequestIntention.passthrough,
35
+ },
36
+ }),
37
+ ),
38
+ ).toBe(true)
39
+ })
40
+
41
+ it('returns false for a regular response', () => {
42
+ expect(isPassthroughResponse(new Response(null))).toBe(false)
43
+ expect(isPassthroughResponse(new Response(null, { status: 302 }))).toBe(
44
+ false,
45
+ )
46
+ })
47
+ })
48
+
49
+ describe(deleteRequestPassthroughHeader, () => {
50
+ it('removes the bypass header from the request', () => {
51
+ const request = new Request('http://example.com', {
52
+ headers: {
53
+ accept: 'msw/passthrough',
54
+ },
55
+ })
56
+ deleteRequestPassthroughHeader(request)
57
+ expect(request.headers.get('accept')).toBeNull()
58
+ })
59
+
60
+ it('does not remove other headers', () => {
61
+ const request = new Request('http://example.com', {
62
+ headers: {
63
+ accept: 'msw/passthrough',
64
+ 'content-type': 'application/json',
65
+ },
66
+ })
67
+ deleteRequestPassthroughHeader(request)
68
+ expect(request.headers.get('content-type')).toBe('application/json')
69
+ })
70
+ })