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
@@ -1,8 +1,8 @@
1
1
  import { until } from 'until-async'
2
- import { devUtils } from '~/core/utils/internal/devUtils'
3
- import { getAbsoluteWorkerUrl } from '../../../utils/getAbsoluteWorkerUrl'
4
- import { getWorkerByRegistration } from './getWorkerByRegistration'
5
- import { ServiceWorkerInstanceTuple, FindWorker } from '../../glossary'
2
+ import { devUtils } from '#core/utils/internal/devUtils'
3
+ import { getAbsoluteWorkerUrl } from './getAbsoluteWorkerUrl'
4
+ import { getWorkerByRegistration } from './get-worker-by-registration'
5
+ import type { ServiceWorkerInstanceTuple, FindWorker } from '../glossary'
6
6
 
7
7
  /**
8
8
  * Returns an active Service Worker instance.
@@ -1,6 +1,4 @@
1
- /**
2
- * @vitest-environment jsdom
3
- */
1
+ // @vitest-environment jsdom
4
2
  import { TextEncoder } from 'util'
5
3
  import { pruneGetRequestBody } from './pruneGetRequestBody'
6
4
 
@@ -1,4 +1,4 @@
1
- import type { ServiceWorkerIncomingRequest } from '../setupWorker/glossary'
1
+ import type { ServiceWorkerIncomingRequest } from '../glossary'
2
2
 
3
3
  type Input = Pick<ServiceWorkerIncomingRequest, 'method' | 'body'>
4
4
 
@@ -0,0 +1,19 @@
1
+ import { devUtils } from '#core/utils/internal/devUtils'
2
+
3
+ /**
4
+ * Print a warning if the given Service Worker registration has a scope
5
+ * outside of the current page's location. That is to help with debugging
6
+ * issues caused by the incorrectly registered Service Worker.
7
+ */
8
+ export function validateWorkerScope(
9
+ registration: ServiceWorkerRegistration,
10
+ ): void {
11
+ if (!location.href.startsWith(registration.scope)) {
12
+ devUtils.warn(
13
+ `Cannot intercept requests on this page because it's outside of the worker's scope ("${registration.scope}"). If you wish to mock API requests on this page, you must resolve this scope issue.
14
+
15
+ - (Recommended) Register the worker at the root level ("/") of your application.
16
+ - Set the "Service-Worker-Allowed" response header to allow out-of-scope workers.`,
17
+ )
18
+ }
19
+ }
@@ -1,7 +1,7 @@
1
1
  import { invariant } from 'outvariant'
2
2
  import { Emitter, TypedEvent } from 'rettime'
3
- import { isObject } from '~/core/utils/internal/isObject'
4
- import type { StringifiedResponse } from '../setupWorker/glossary'
3
+ import { isObject } from '#core/utils/internal/isObject'
4
+ import type { StringifiedResponse } from '../glossary'
5
5
  import { supportsServiceWorker } from '../utils/supports'
6
6
 
7
7
  export interface WorkerChannelOptions {
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Collection of helpers for bridging the compatibility between the old and the new APIs.
3
+ */
4
+ import { invariant } from 'outvariant'
5
+ import { type UnhandledRequestStrategy } from '../utils/request/onUnhandledRequest'
6
+ import {
7
+ executeUnhandledFrameHandle,
8
+ type UnhandledFrameCallback,
9
+ } from './on-unhandled-frame'
10
+ import { HttpNetworkFrame } from './frames/http-frame'
11
+ import { WebSocketNetworkFrame } from './frames/websocket-frame'
12
+
13
+ export function fromLegacyOnUnhandledRequest(
14
+ getLegacyValue: () => UnhandledRequestStrategy | undefined,
15
+ ): UnhandledFrameCallback {
16
+ return ({ frame, defaults }) => {
17
+ const legacyOnUnhandledRequestStrategy = getLegacyValue()
18
+
19
+ if (legacyOnUnhandledRequestStrategy == null) {
20
+ return
21
+ }
22
+
23
+ if (typeof legacyOnUnhandledRequestStrategy === 'function') {
24
+ const request =
25
+ frame instanceof HttpNetworkFrame
26
+ ? frame.data.request
27
+ : frame instanceof WebSocketNetworkFrame
28
+ ? new Request(frame.data.connection.client.url, {
29
+ headers: {
30
+ connection: 'upgrade',
31
+ upgrade: 'websocket',
32
+ },
33
+ })
34
+ : null
35
+
36
+ invariant(
37
+ request != null,
38
+ 'Failed to coerce a network frame to a legacy `onUnhandledRequest` strategy: unknown frame protocol "%s"',
39
+ frame.protocol,
40
+ )
41
+
42
+ return legacyOnUnhandledRequestStrategy(request, {
43
+ warning: defaults.warn,
44
+ error: defaults.error,
45
+ })
46
+ }
47
+
48
+ return executeUnhandledFrameHandle(frame, legacyOnUnhandledRequestStrategy)
49
+ }
50
+ }
@@ -0,0 +1,124 @@
1
+ import { NetworkSource } from './sources/network-source'
2
+ import { defineNetwork } from './define-network'
3
+
4
+ describe('enable()', () => {
5
+ it('throws if called on already enabled network', () => {
6
+ class SyncNetworkSource extends NetworkSource {
7
+ enable = () => {}
8
+ }
9
+ const network = defineNetwork({
10
+ sources: [new SyncNetworkSource()],
11
+ })
12
+
13
+ expect(network.enable()).toBeUndefined()
14
+ expect(() => network.enable()).toThrow(
15
+ 'Failed to call "enable" on the network: already enabled',
16
+ )
17
+
18
+ network.disable()
19
+ expect(network.enable()).toBeUndefined()
20
+ })
21
+
22
+ it('returns a sync enable if all the sources are sync', () => {
23
+ class SyncNetworkSource extends NetworkSource {
24
+ enable = () => {}
25
+ }
26
+ const network = defineNetwork({
27
+ sources: [new SyncNetworkSource()],
28
+ })
29
+
30
+ expect(network.enable()).toBeUndefined()
31
+ })
32
+
33
+ it('returns an async enable if any of the sources are async', () => {
34
+ class SyncNetworkSource extends NetworkSource {
35
+ enable = () => {}
36
+ }
37
+ class AsyncNetworkSource extends NetworkSource {
38
+ enable = async () => {}
39
+ }
40
+
41
+ const network = defineNetwork({
42
+ sources: [new SyncNetworkSource(), new AsyncNetworkSource()],
43
+ })
44
+
45
+ expect(network.enable()).toBeInstanceOf(Promise)
46
+ })
47
+
48
+ it('returns an async enable if all the sources are async', () => {
49
+ class AsyncNetworkSource extends NetworkSource {
50
+ enable = async () => {}
51
+ }
52
+
53
+ const network = defineNetwork({
54
+ sources: [new AsyncNetworkSource()],
55
+ })
56
+
57
+ expect(network.enable()).toBeInstanceOf(Promise)
58
+ })
59
+ })
60
+
61
+ describe('disable()', () => {
62
+ it('throws if called on already enabled network', () => {
63
+ class SyncNetworkSource extends NetworkSource {
64
+ enable = () => {}
65
+ }
66
+ const network = defineNetwork({
67
+ sources: [new SyncNetworkSource()],
68
+ })
69
+
70
+ network.enable()
71
+ expect(network.disable()).toBeUndefined()
72
+ expect(() => network.disable()).toThrow(
73
+ 'Failed to call "disable" on the network: already disabled',
74
+ )
75
+
76
+ network.enable()
77
+ expect(network.disable()).toBeUndefined()
78
+ })
79
+
80
+ it('returns a sync disable if all the sources are sync', () => {
81
+ class SyncNetworkSource extends NetworkSource {
82
+ enable = () => {}
83
+ disable = () => {}
84
+ }
85
+ const network = defineNetwork({
86
+ sources: [new SyncNetworkSource()],
87
+ })
88
+
89
+ network.enable()
90
+ expect(network.disable()).toBeUndefined()
91
+ })
92
+
93
+ it('returns an async disable if any of the sources are async', async () => {
94
+ class SyncNetworkSource extends NetworkSource {
95
+ enable = () => {}
96
+ disable = () => {}
97
+ }
98
+ class AsyncNetworkSource extends NetworkSource {
99
+ enable = async () => {}
100
+ disable = async () => {}
101
+ }
102
+
103
+ const network = defineNetwork({
104
+ sources: [new SyncNetworkSource(), new AsyncNetworkSource()],
105
+ })
106
+
107
+ await network.enable()
108
+ expect(network.disable()).toBeInstanceOf(Promise)
109
+ })
110
+
111
+ it('returns an async disable if all the sources are async', async () => {
112
+ class AsyncNetworkSource extends NetworkSource {
113
+ enable = async () => {}
114
+ disable = async () => {}
115
+ }
116
+
117
+ const network = defineNetwork({
118
+ sources: [new AsyncNetworkSource()],
119
+ })
120
+
121
+ await network.enable()
122
+ expect(network.disable()).toBeInstanceOf(Promise)
123
+ })
124
+ })
@@ -0,0 +1,215 @@
1
+ import { invariant } from 'outvariant'
2
+ import { Emitter, type DefaultEventMap } from 'rettime'
3
+ import {
4
+ type NetworkSource,
5
+ type ExtractSourceEvents,
6
+ } from './sources/network-source'
7
+ import { type NetworkFrameResolutionContext } from './frames/network-frame'
8
+ import { type UnhandledFrameHandle } from './on-unhandled-frame'
9
+ import {
10
+ AnyHandler,
11
+ HandlersController,
12
+ InMemoryHandlersController,
13
+ } from './handlers-controller'
14
+ import { toReadonlyArray } from '../utils/internal/toReadonlyArray'
15
+
16
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
17
+ k: infer I,
18
+ ) => void
19
+ ? I
20
+ : never
21
+
22
+ type MergeEventMaps<Sources extends Array<NetworkSource<any>>> =
23
+ UnionToIntersection<ExtractSourceEvents<Sources[number]>> extends infer R
24
+ ? R extends Record<string, any>
25
+ ? R
26
+ : DefaultEventMap
27
+ : DefaultEventMap
28
+
29
+ type MaybePromise<T> =
30
+ Extract<T, Promise<unknown>> extends never ? void : Promise<void>
31
+
32
+ export interface DefineNetworkOptions<
33
+ Sources extends Array<NetworkSource<any>>,
34
+ > {
35
+ /**
36
+ * List of the network sources.
37
+ * Every network source emits frames, and every frame describes how
38
+ * to handle the various network scenarios, like mocking a response,
39
+ * erroring the request, or performing it as-is.
40
+ */
41
+ sources: Sources
42
+ /**
43
+ * List of handlers to describe the network.
44
+ */
45
+ handlers?: Array<AnyHandler> | HandlersController
46
+ context?: NetworkFrameResolutionContext
47
+ onUnhandledFrame?: UnhandledFrameHandle
48
+ }
49
+
50
+ export interface NetworkApi<Sources extends Array<NetworkSource<any>>>
51
+ extends NetworkHandlersApi {
52
+ readyState: NetworkReadyState
53
+ /**
54
+ * Enable the network interception and handling.
55
+ */
56
+ enable: () => MaybePromise<ReturnType<Sources[number]['enable']>>
57
+ /**
58
+ * Disable the network interception and handling.
59
+ */
60
+ disable: () => MaybePromise<ReturnType<Sources[number]['disable']>>
61
+ /**
62
+ * Configure the network instance with additional options.
63
+ * The options provided in the `.configure()` call will override the same
64
+ * options in the `defineNetwork()` call.
65
+ */
66
+ configure: (options: Partial<DefineNetworkOptions<Sources>>) => void
67
+ events: Emitter<MergeEventMaps<Sources>>
68
+ }
69
+
70
+ export interface NetworkHandlersApi {
71
+ use: (...handlers: Array<AnyHandler>) => void
72
+ resetHandlers: (...handlers: Array<AnyHandler>) => void
73
+ restoreHandlers: () => void
74
+ listHandlers: () => ReadonlyArray<AnyHandler>
75
+ }
76
+
77
+ function colorlessPromiseAll<T>(values: Array<T>): MaybePromise<T>
78
+ function colorlessPromiseAll(values: Array<unknown>): Promise<void> | void {
79
+ const promises: Array<Promise<void>> = []
80
+
81
+ for (const value of values) {
82
+ if (value instanceof Promise) {
83
+ promises.push(value)
84
+ }
85
+ }
86
+
87
+ if (promises.length > 0) {
88
+ return Promise.all(promises).then(() => {})
89
+ }
90
+ }
91
+
92
+ export enum NetworkReadyState {
93
+ DISABLED,
94
+ ENABLED,
95
+ }
96
+
97
+ /**
98
+ * Define a network instance with the given configuration.
99
+ * @example
100
+ * import { InterceptorSource } from 'msw/experimental'
101
+ * import { handlers } from './handlers'
102
+ *
103
+ * const network = defineNetwork({
104
+ * sources: [new InterceptorSource({ interceptors })],
105
+ * handlers,
106
+ * })
107
+ * await network.enable()
108
+ */
109
+ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
110
+ options: DefineNetworkOptions<Sources>,
111
+ ): NetworkApi<Sources> {
112
+ let readyState: NetworkReadyState = NetworkReadyState.DISABLED
113
+ const events = new Emitter<MergeEventMaps<Sources>>()
114
+
115
+ const deriveHandlersController = (
116
+ handlers: DefineNetworkOptions<Sources>['handlers'],
117
+ ) => {
118
+ return handlers instanceof HandlersController
119
+ ? handlers
120
+ : new InMemoryHandlersController(handlers || [])
121
+ }
122
+
123
+ let resolvedOptions: DefineNetworkOptions<Sources> = {
124
+ ...options,
125
+ }
126
+
127
+ /**
128
+ * @note Create the handlers controller immediately because
129
+ * certain setup APIs, like `setupServer`, don't await `.enable` (`.listen`).
130
+ */
131
+ let handlersController = deriveHandlersController(resolvedOptions.handlers)
132
+ let listenersController: AbortController
133
+
134
+ return {
135
+ get readyState() {
136
+ return readyState
137
+ },
138
+ events,
139
+ configure(options) {
140
+ invariant(readyState === NetworkReadyState.DISABLED, '')
141
+
142
+ if (
143
+ options.handlers &&
144
+ !Object.is(options.handlers, resolvedOptions.handlers)
145
+ ) {
146
+ handlersController = deriveHandlersController(options.handlers)
147
+ }
148
+
149
+ resolvedOptions = {
150
+ ...resolvedOptions,
151
+ ...options,
152
+ }
153
+ },
154
+ enable() {
155
+ invariant(
156
+ readyState === NetworkReadyState.DISABLED,
157
+ 'Failed to call "enable" on the network: already enabled',
158
+ )
159
+
160
+ listenersController = new AbortController()
161
+ readyState = NetworkReadyState.ENABLED
162
+
163
+ const result = resolvedOptions.sources.map((source) => {
164
+ source.on('frame', async ({ frame }) => {
165
+ frame.events.on('*', (event) => events.emit(event), {
166
+ signal: listenersController.signal,
167
+ })
168
+
169
+ const handlers = frame.getHandlers(handlersController)
170
+
171
+ await frame.resolve(
172
+ handlers,
173
+ resolvedOptions.onUnhandledFrame || 'warn',
174
+ resolvedOptions.context,
175
+ )
176
+ })
177
+
178
+ return source.enable()
179
+ })
180
+
181
+ return colorlessPromiseAll(result) as MaybePromise<
182
+ ReturnType<Sources[number]['enable']>
183
+ >
184
+ },
185
+ disable() {
186
+ invariant(
187
+ readyState === NetworkReadyState.ENABLED,
188
+ 'Failed to call "disable" on the network: already disabled',
189
+ )
190
+
191
+ listenersController.abort()
192
+ readyState = NetworkReadyState.DISABLED
193
+
194
+ return colorlessPromiseAll(
195
+ resolvedOptions.sources.map((source) => source.disable()),
196
+ ) as MaybePromise<ReturnType<Sources[number]['disable']>>
197
+ },
198
+ use(...handlers) {
199
+ handlersController.use(handlers)
200
+ },
201
+ resetHandlers(...handlers) {
202
+ handlersController.reset(handlers)
203
+ },
204
+ restoreHandlers() {
205
+ for (const handler of handlersController.currentHandlers()) {
206
+ if ('isUsed' in handler) {
207
+ handler.isUsed = false
208
+ }
209
+ }
210
+ },
211
+ listHandlers() {
212
+ return toReadonlyArray(handlersController.currentHandlers())
213
+ },
214
+ }
215
+ }