msw-fetch-mock 0.2.1 → 0.3.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/README.md CHANGED
@@ -8,6 +8,13 @@ Undici-style fetch mock API built on [MSW](https://mswjs.io/) (Mock Service Work
8
8
 
9
9
  If you're familiar with Cloudflare Workers' `fetchMock` (from `cloudflare:test`) or Node.js undici's `MockAgent`, you already know this API.
10
10
 
11
+ Supports both **Node.js** (`msw/node`) and **Browser** (`msw/browser`) environments via subpath exports.
12
+
13
+ ## Requirements
14
+
15
+ - **Node.js** >= 18
16
+ - **MSW** ^1.0.0 (via `/legacy`) or ^2.12.7
17
+
11
18
  ## Install
12
19
 
13
20
  ```bash
@@ -18,10 +25,12 @@ npm install -D msw-fetch-mock msw
18
25
 
19
26
  ## Quick Start
20
27
 
21
- ### Standalone (Cloudflare migration)
28
+ ### Node.js (Vitest, Jest)
22
29
 
23
30
  ```typescript
31
+ // Works with default import or explicit /node subpath
24
32
  import { fetchMock } from 'msw-fetch-mock';
33
+ // import { fetchMock } from 'msw-fetch-mock/node';
25
34
 
26
35
  beforeAll(() => fetchMock.activate({ onUnhandledRequest: 'error' }));
27
36
  afterAll(() => fetchMock.deactivate());
@@ -43,6 +52,25 @@ it('mocks a GET request', async () => {
43
52
  });
44
53
  ```
45
54
 
55
+ ### Browser (Storybook, Vitest Browser Mode)
56
+
57
+ ```typescript
58
+ import { setupWorker } from 'msw/browser';
59
+ import { createFetchMock } from 'msw-fetch-mock/browser';
60
+
61
+ const worker = setupWorker();
62
+ const fetchMock = createFetchMock(worker);
63
+
64
+ beforeAll(async () => {
65
+ await fetchMock.activate({ onUnhandledRequest: 'error' });
66
+ });
67
+ afterAll(() => fetchMock.deactivate());
68
+ afterEach(() => {
69
+ fetchMock.assertNoPendingInterceptors();
70
+ fetchMock.reset();
71
+ });
72
+ ```
73
+
46
74
  ### With an existing MSW server
47
75
 
48
76
  If you already use MSW, pass your server to share a single interceptor:
@@ -51,9 +79,10 @@ If you already use MSW, pass your server to share a single interceptor:
51
79
  import { setupServer } from 'msw/node';
52
80
  import { http, HttpResponse } from 'msw';
53
81
  import { FetchMock } from 'msw-fetch-mock';
82
+ import { NodeMswAdapter } from 'msw-fetch-mock/node';
54
83
 
55
84
  const server = setupServer(http.get('/api/users', () => HttpResponse.json([{ id: 1 }])));
56
- const fetchMock = new FetchMock(server);
85
+ const fetchMock = new FetchMock(new NodeMswAdapter(server));
57
86
 
58
87
  beforeAll(() => server.listen());
59
88
  afterAll(() => server.close());
@@ -63,7 +92,27 @@ afterEach(() => {
63
92
  });
64
93
  ```
65
94
 
66
- > **Note:** Only one MSW server can be active at a time. If another server is already listening, standalone `activate()` will throw an error guiding you to use `new FetchMock(server)` instead.
95
+ > **Note:** Only one MSW server can be active at a time. If another server is already listening, standalone `activate()` will throw an error guiding you to use `new FetchMock(new NodeMswAdapter(server))` instead.
96
+
97
+ ### Legacy (MSW v1)
98
+
99
+ ```typescript
100
+ import { rest } from 'msw';
101
+ import { setupServer } from 'msw/node';
102
+ import { createFetchMock } from 'msw-fetch-mock/legacy';
103
+
104
+ const server = setupServer();
105
+ const fetchMock = createFetchMock(rest, server);
106
+
107
+ beforeAll(() => fetchMock.activate());
108
+ afterAll(() => fetchMock.deactivate());
109
+ afterEach(() => {
110
+ fetchMock.assertNoPendingInterceptors();
111
+ fetchMock.reset();
112
+ });
113
+ ```
114
+
115
+ See [MSW v1 Legacy Guide](docs/msw-v1-legacy.md) for details.
67
116
 
68
117
  ## Unhandled Requests
69
118
 
@@ -93,19 +142,37 @@ fetchMock.activate({
93
142
 
94
143
  ## API Overview
95
144
 
145
+ ### Import Paths
146
+
147
+ | Path | Environment | MSW version |
148
+ | ------------------------ | ---------------------------- | ----------- |
149
+ | `msw-fetch-mock` | Node.js (re-exports `/node`) | v2 |
150
+ | `msw-fetch-mock/node` | Node.js | v2 |
151
+ | `msw-fetch-mock/browser` | Browser | v2 |
152
+ | `msw-fetch-mock/legacy` | Node.js (MSW v1) | v1 |
153
+
96
154
  ### `fetchMock` (singleton)
97
155
 
98
156
  A pre-built `FetchMock` instance for standalone use. Import and call `activate()` — no setup needed.
157
+ Available from `msw-fetch-mock` and `msw-fetch-mock/node`.
99
158
 
100
- ### `new FetchMock(server?)`
159
+ ### `createFetchMock(server?)` / `createFetchMock(worker)`
101
160
 
102
- Creates a `FetchMock` instance. Pass an existing MSW `SetupServer` to share interceptors; omit to create one internally.
161
+ Factory function that creates a `FetchMock` with the appropriate adapter.
162
+
163
+ - Node: `createFetchMock(server?)` — optionally pass an existing MSW `SetupServer`
164
+ - Browser: `createFetchMock(worker)` — pass an MSW `SetupWorker` (required)
165
+ - Legacy: `createFetchMock(rest, server?)` — pass MSW v1 `rest` object
166
+
167
+ ### `new FetchMock(adapter?)`
168
+
169
+ Creates a `FetchMock` instance with an explicit `MswAdapter`. Use `NodeMswAdapter` or `BrowserMswAdapter`.
103
170
 
104
171
  ### Intercepting & Replying
105
172
 
106
173
  ```typescript
107
174
  fetchMock
108
- .get(origin) // select origin
175
+ .get(origin) // string, RegExp, or function
109
176
  .intercept({ path, method, headers, body, query }) // match criteria
110
177
  .reply(status, body, options) // define response
111
178
  .times(n) / .persist(); // repeat control
@@ -127,10 +194,49 @@ fetchMock.assertNoPendingInterceptors(); // throws if unconsumed interceptors re
127
194
  fetchMock.reset(); // clears interceptors + call history + handlers
128
195
  ```
129
196
 
197
+ ## Tested Environments
198
+
199
+ E2E tests run on every CI push across these environments:
200
+
201
+ | Environment | Module System | Test Framework |
202
+ | -------------- | ------------- | ------------------- |
203
+ | Jest ESM | ESM (import) | Jest |
204
+ | Jest CJS | CJS (require) | Jest |
205
+ | Node.js Test | ESM (import) | Node test runner |
206
+ | Node.js CJS | CJS (require) | Node test runner |
207
+ | Vitest Browser | ESM (import) | Vitest + Playwright |
208
+
130
209
  ## Documentation
131
210
 
132
211
  - [API Reference](docs/api.md) — full API details, matching options, reply callbacks
133
212
  - [Cloudflare Workers Migration](docs/cloudflare-migration.md) — migrating from `cloudflare:test` fetchMock
213
+ - [MSW v1 Legacy Guide](docs/msw-v1-legacy.md) — using msw-fetch-mock with MSW v1
214
+
215
+ ## Development
216
+
217
+ ```bash
218
+ pnpm install
219
+ pnpm build # build with tsup
220
+ pnpm test # unit tests (vitest)
221
+ pnpm test:e2e # e2e tests (jest-esm, jest-cjs, node-test, node-cjs)
222
+ ```
223
+
224
+ ### E2E Tests
225
+
226
+ E2E tests verify the published package works across different runtimes and module systems. The script builds, packs a tarball via `npm pack`, and installs it into each `e2e/` project — mirroring CI exactly.
227
+
228
+ ```bash
229
+ # Run default suites (skip vitest-browser)
230
+ pnpm test:e2e
231
+
232
+ # Run a single suite
233
+ pnpm test:e2e -- node-cjs
234
+
235
+ # Run all suites including vitest-browser (auto-installs Playwright)
236
+ pnpm test:e2e -- --all
237
+ ```
238
+
239
+ Available suites: `jest-esm`, `jest-cjs`, `node-test`, `node-cjs`, `vitest-browser`
134
240
 
135
241
  ## License
136
242
 
@@ -0,0 +1,43 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkHYRDB2FHcjs = require('./chunk-HYRDB2FH.cjs');
4
+
5
+
6
+
7
+
8
+ var _chunk43CWIVXOcjs = require('./chunk-43CWIVXO.cjs');
9
+
10
+ // src/browser-adapter.ts
11
+ var BrowserMswAdapter = class {
12
+
13
+ constructor(worker) {
14
+ this.worker = worker;
15
+ }
16
+ use(...handlers) {
17
+ this.worker.use(...handlers);
18
+ }
19
+ resetHandlers(...handlers) {
20
+ this.worker.resetHandlers(...handlers);
21
+ }
22
+ async activate(options) {
23
+ await this.worker.start({
24
+ onUnhandledRequest: options.onUnhandledRequest
25
+ });
26
+ }
27
+ deactivate() {
28
+ this.worker.stop();
29
+ }
30
+ };
31
+
32
+ // src/browser.ts
33
+ _chunk43CWIVXOcjs.FetchMock._handlerFactory = _chunkHYRDB2FHcjs.v2HandlerFactory;
34
+ function createFetchMock(worker) {
35
+ return new (0, _chunk43CWIVXOcjs.FetchMock)(new BrowserMswAdapter(worker));
36
+ }
37
+
38
+
39
+
40
+
41
+
42
+
43
+ exports.BrowserMswAdapter = BrowserMswAdapter; exports.FetchMock = _chunk43CWIVXOcjs.FetchMock; exports.MockCallHistory = _chunk43CWIVXOcjs.MockCallHistory; exports.MockCallHistoryLog = _chunk43CWIVXOcjs.MockCallHistoryLog; exports.createFetchMock = createFetchMock;
@@ -0,0 +1,15 @@
1
+ import { M as MswAdapter, S as SetupWorkerLike, R as ResolvedActivateOptions, F as FetchMock } from './fetch-mock-BNke4Oik.cjs';
2
+ export { A as ActivateOptions, C as CallHistoryFilterCriteria, H as HandlerFactory, I as InterceptOptions, a as MockCallHistory, b as MockCallHistoryLog, c as MockCallHistoryLogData, d as MockInterceptor, e as MockPool, f as MockReplyChain, O as OnUnhandledRequest, P as PendingInterceptor, g as ReplyOptions } from './fetch-mock-BNke4Oik.cjs';
3
+
4
+ declare class BrowserMswAdapter implements MswAdapter {
5
+ private readonly worker;
6
+ constructor(worker: SetupWorkerLike);
7
+ use(...handlers: Array<unknown>): void;
8
+ resetHandlers(...handlers: Array<unknown>): void;
9
+ activate(options: ResolvedActivateOptions): Promise<void>;
10
+ deactivate(): void;
11
+ }
12
+
13
+ declare function createFetchMock(worker: SetupWorkerLike): FetchMock;
14
+
15
+ export { BrowserMswAdapter, FetchMock, MswAdapter, SetupWorkerLike, createFetchMock };
@@ -0,0 +1,15 @@
1
+ import { M as MswAdapter, S as SetupWorkerLike, R as ResolvedActivateOptions, F as FetchMock } from './fetch-mock-BNke4Oik.js';
2
+ export { A as ActivateOptions, C as CallHistoryFilterCriteria, H as HandlerFactory, I as InterceptOptions, a as MockCallHistory, b as MockCallHistoryLog, c as MockCallHistoryLogData, d as MockInterceptor, e as MockPool, f as MockReplyChain, O as OnUnhandledRequest, P as PendingInterceptor, g as ReplyOptions } from './fetch-mock-BNke4Oik.js';
3
+
4
+ declare class BrowserMswAdapter implements MswAdapter {
5
+ private readonly worker;
6
+ constructor(worker: SetupWorkerLike);
7
+ use(...handlers: Array<unknown>): void;
8
+ resetHandlers(...handlers: Array<unknown>): void;
9
+ activate(options: ResolvedActivateOptions): Promise<void>;
10
+ deactivate(): void;
11
+ }
12
+
13
+ declare function createFetchMock(worker: SetupWorkerLike): FetchMock;
14
+
15
+ export { BrowserMswAdapter, FetchMock, MswAdapter, SetupWorkerLike, createFetchMock };
@@ -0,0 +1,43 @@
1
+ import {
2
+ v2HandlerFactory
3
+ } from "./chunk-D26SJTTI.js";
4
+ import {
5
+ FetchMock,
6
+ MockCallHistory,
7
+ MockCallHistoryLog
8
+ } from "./chunk-ATXIIOZA.js";
9
+
10
+ // src/browser-adapter.ts
11
+ var BrowserMswAdapter = class {
12
+ worker;
13
+ constructor(worker) {
14
+ this.worker = worker;
15
+ }
16
+ use(...handlers) {
17
+ this.worker.use(...handlers);
18
+ }
19
+ resetHandlers(...handlers) {
20
+ this.worker.resetHandlers(...handlers);
21
+ }
22
+ async activate(options) {
23
+ await this.worker.start({
24
+ onUnhandledRequest: options.onUnhandledRequest
25
+ });
26
+ }
27
+ deactivate() {
28
+ this.worker.stop();
29
+ }
30
+ };
31
+
32
+ // src/browser.ts
33
+ FetchMock._handlerFactory = v2HandlerFactory;
34
+ function createFetchMock(worker) {
35
+ return new FetchMock(new BrowserMswAdapter(worker));
36
+ }
37
+ export {
38
+ BrowserMswAdapter,
39
+ FetchMock,
40
+ MockCallHistory,
41
+ MockCallHistoryLog,
42
+ createFetchMock
43
+ };