msw-fetch-mock 0.3.3 → 0.4.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.
- package/README.md +46 -15
- package/README.zh-TW.md +274 -0
- package/dist/browser.cjs +5 -4
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +2 -1
- package/dist/{chunk-OSKJXLRH.cjs → chunk-27BEAYUI.cjs} +4 -4
- package/dist/chunk-3RE2WWHX.cjs +1 -0
- package/dist/{chunk-3RAWYKAG.js → chunk-3XFP4NAO.js} +30 -0
- package/dist/chunk-GZFGTCZB.js +0 -0
- package/dist/{chunk-NFPFLI3N.js → chunk-IWHL7QPE.js} +1 -1
- package/dist/{chunk-N6B7UP6B.cjs → chunk-VUNESK75.cjs} +30 -0
- package/dist/{fetch-mock-DhiqmHdF.d.cts → fetch-mock-1oOS8WUJ.d.cts} +31 -1
- package/dist/{fetch-mock-DhiqmHdF.d.ts → fetch-mock-1oOS8WUJ.d.ts} +31 -1
- package/dist/index.cjs +4 -3
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -2
- package/dist/legacy.cjs +5 -5
- package/dist/legacy.d.cts +2 -2
- package/dist/legacy.d.ts +2 -2
- package/dist/legacy.js +1 -1
- package/dist/native.cjs +92 -0
- package/dist/native.d.cts +20 -0
- package/dist/native.d.ts +20 -0
- package/dist/native.js +92 -0
- package/dist/node.cjs +4 -3
- package/dist/node.d.cts +14 -2
- package/dist/node.d.ts +14 -2
- package/dist/node.js +3 -2
- package/docs/api.md +35 -10
- package/docs/api.zh-TW.md +707 -0
- package/docs/cloudflare-migration.zh-TW.md +80 -0
- package/docs/msw-v1-legacy.zh-TW.md +94 -0
- package/package.json +15 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Cloudflare Workers 遷移指南
|
|
2
|
+
|
|
3
|
+
如果你正在將測試從 Cloudflare Workers 的 `cloudflare:test` 遷移到標準的 Node.js 測試環境,`msw-fetch-mock` 提供了你已經熟悉的相同 `fetchMock` API。
|
|
4
|
+
|
|
5
|
+
## API 對照
|
|
6
|
+
|
|
7
|
+
| cloudflare:test | msw-fetch-mock |
|
|
8
|
+
| -------------------------------------------------- | ----------------------------------------------------------- |
|
|
9
|
+
| `import { fetchMock } from 'cloudflare:test'` | `import { fetchMock } from 'msw-fetch-mock'` |
|
|
10
|
+
| `fetchMock.activate()` | `await fetchMock.activate()` |
|
|
11
|
+
| `fetchMock.disableNetConnect()` | `fetchMock.disableNetConnect()` |
|
|
12
|
+
| `fetchMock.enableNetConnect(matcher?)` | `fetchMock.enableNetConnect(matcher?)` |
|
|
13
|
+
| `fetchMock.deactivate()` | `fetchMock.deactivate()` |
|
|
14
|
+
| `fetchMock.get(origin).intercept(opts).reply(...)` | `fetchMock.get(origin).intercept(opts).reply(...)` |
|
|
15
|
+
| `.replyWithError(error)` | `.replyWithError(error)` |
|
|
16
|
+
| `.reply(...).delay(ms)` | `.reply(...).delay(ms)` |
|
|
17
|
+
| `fetchMock.getCallHistory()` | `fetchMock.getCallHistory()` 或 `fetchMock.calls` |
|
|
18
|
+
| `fetchMock.clearCallHistory()` | `fetchMock.clearCallHistory()` 或 `fetchMock.calls.clear()` |
|
|
19
|
+
| `fetchMock.assertNoPendingInterceptors()` | `fetchMock.assertNoPendingInterceptors()` |
|
|
20
|
+
|
|
21
|
+
## 遷移前(cloudflare:test)
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { fetchMock } from 'cloudflare:test';
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
fetchMock.activate();
|
|
28
|
+
fetchMock.disableNetConnect();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => fetchMock.assertNoPendingInterceptors());
|
|
32
|
+
|
|
33
|
+
it('呼叫 API', async () => {
|
|
34
|
+
fetchMock
|
|
35
|
+
.get('https://api.example.com')
|
|
36
|
+
.intercept({ path: '/data', method: 'GET' })
|
|
37
|
+
.reply(200, { result: 'ok' });
|
|
38
|
+
|
|
39
|
+
const res = await fetch('https://api.example.com/data');
|
|
40
|
+
expect(await res.json()).toEqual({ result: 'ok' });
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 遷移後(msw-fetch-mock)
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { fetchMock } from 'msw-fetch-mock';
|
|
48
|
+
|
|
49
|
+
beforeAll(async () => {
|
|
50
|
+
await fetchMock.activate();
|
|
51
|
+
});
|
|
52
|
+
afterAll(() => fetchMock.deactivate());
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
fetchMock.assertNoPendingInterceptors();
|
|
55
|
+
fetchMock.reset();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('呼叫 API', async () => {
|
|
59
|
+
fetchMock
|
|
60
|
+
.get('https://api.example.com')
|
|
61
|
+
.intercept({ path: '/data', method: 'GET' })
|
|
62
|
+
.reply(200, { result: 'ok' });
|
|
63
|
+
|
|
64
|
+
const res = await fetch('https://api.example.com/data');
|
|
65
|
+
expect(await res.json()).toEqual({ result: 'ok' });
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 主要差異
|
|
70
|
+
|
|
71
|
+
| 面向 | cloudflare:test | msw-fetch-mock |
|
|
72
|
+
| --------------- | --------------------------------------------- | ------------------------------------------------- |
|
|
73
|
+
| 匯入 | `import { fetchMock } from 'cloudflare:test'` | `import { fetchMock } from 'msw-fetch-mock'` |
|
|
74
|
+
| Server 生命週期 | 隱式(由測試框架管理) | 顯式(`activate()` / `deactivate()`) |
|
|
75
|
+
| 呼叫歷史存取 | `fetchMock.getCallHistory()` | `fetchMock.getCallHistory()` 或 `fetchMock.calls` |
|
|
76
|
+
| 呼叫歷史清理 | 每次測試自動清理 | 在 `afterEach` 中呼叫 `reset()` |
|
|
77
|
+
| 未處理的請求 | 必須呼叫 `disableNetConnect()` | 預設 `onUnhandledRequest: 'error'`(直接拒絕) |
|
|
78
|
+
| 執行環境 | Cloudflare Workers (workerd) | Node.js |
|
|
79
|
+
|
|
80
|
+
> **注意:** `getCallHistory()` 和 `clearCallHistory()` 是為了 Cloudflare 相容性而提供的別名。你可以使用 Cloudflare 風格的方法或 `fetchMock.calls` getter — 兩者是等價的。
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# MSW v1 Legacy 指南
|
|
2
|
+
|
|
3
|
+
如果你正在使用 MSW v1(`msw@^1.x`),請使用 `msw-fetch-mock/legacy` 子路徑匯出。API 與 v2 版本相同 — 只有設定方式不同。
|
|
4
|
+
|
|
5
|
+
## 安裝
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -D msw-fetch-mock msw@^1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 設定
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { rest } from 'msw';
|
|
15
|
+
import { setupServer } from 'msw/node';
|
|
16
|
+
import { createFetchMock } from 'msw-fetch-mock/legacy';
|
|
17
|
+
|
|
18
|
+
const server = setupServer();
|
|
19
|
+
const fetchMock = createFetchMock(rest, server);
|
|
20
|
+
|
|
21
|
+
beforeAll(() => fetchMock.activate());
|
|
22
|
+
afterAll(() => fetchMock.deactivate());
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
fetchMock.assertNoPendingInterceptors();
|
|
25
|
+
fetchMock.reset();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('模擬 GET 請求', async () => {
|
|
29
|
+
fetchMock
|
|
30
|
+
.get('https://api.example.com')
|
|
31
|
+
.intercept({ path: '/users', method: 'GET' })
|
|
32
|
+
.reply(200, { users: [{ id: '1', name: 'Alice' }] });
|
|
33
|
+
|
|
34
|
+
const res = await fetch('https://api.example.com/users');
|
|
35
|
+
const data = await res.json();
|
|
36
|
+
|
|
37
|
+
expect(data.users).toHaveLength(1);
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## API 對照
|
|
42
|
+
|
|
43
|
+
| MSW v2(`msw-fetch-mock`) | MSW v1(`msw-fetch-mock/legacy`) |
|
|
44
|
+
| -------------------------------------------- | ---------------------------------------------- |
|
|
45
|
+
| `import { fetchMock } from 'msw-fetch-mock'` | 無單例 — 必須使用 `createFetchMock` |
|
|
46
|
+
| `import { createFetchMock } from '.../node'` | `import { createFetchMock } from '.../legacy'` |
|
|
47
|
+
| `createFetchMock(server?)` | `createFetchMock(rest, server?)` |
|
|
48
|
+
| `import { http } from 'msw'` | `import { rest } from 'msw'` |
|
|
49
|
+
|
|
50
|
+
## 主要差異
|
|
51
|
+
|
|
52
|
+
| 面向 | MSW v2 | MSW v1(Legacy) |
|
|
53
|
+
| ---------------- | ----------------------------------------- | --------------------------------- |
|
|
54
|
+
| 匯入 | `msw-fetch-mock` 或 `msw-fetch-mock/node` | `msw-fetch-mock/legacy` |
|
|
55
|
+
| 工廠函式 | `createFetchMock(server?)` | `createFetchMock(rest, server?)` |
|
|
56
|
+
| 單例 | `fetchMock` 預建實例 | 不提供 — 使用 `createFetchMock` |
|
|
57
|
+
| Handler 內部實作 | 使用 `http.*` + `HttpResponse` | 使用 `rest.*` + `(req, res, ctx)` |
|
|
58
|
+
| MSW 版本 | `msw@^2.12.7` | `msw@^1.0.0` |
|
|
59
|
+
|
|
60
|
+
## 匯出項目
|
|
61
|
+
|
|
62
|
+
`msw-fetch-mock/legacy` 子路徑匯出:
|
|
63
|
+
|
|
64
|
+
| 匯出 | 類型 | 說明 |
|
|
65
|
+
| -------------------------------- | ---- | ----------------------------------- |
|
|
66
|
+
| `createFetchMock(rest, server?)` | 函式 | 建立適用於 MSW v1 的 FetchMock 實例 |
|
|
67
|
+
| `FetchMock` | 類別 | 核心模擬類別(與 v2 相同) |
|
|
68
|
+
| `createLegacyHandlerFactory` | 函式 | 低階:建立 v1 相容的 handler 工廠 |
|
|
69
|
+
| `LegacyRestApi` | 型別 | MSW v1 的 `rest` 物件型別 |
|
|
70
|
+
|
|
71
|
+
## 從 MSW v1 遷移到 v2
|
|
72
|
+
|
|
73
|
+
當你將 MSW 從 v1 升級到 v2 時,更新你的匯入:
|
|
74
|
+
|
|
75
|
+
```diff
|
|
76
|
+
- import { rest } from 'msw';
|
|
77
|
+
- import { createFetchMock } from 'msw-fetch-mock/legacy';
|
|
78
|
+
- const fetchMock = createFetchMock(rest, server);
|
|
79
|
+
+ import { createFetchMock } from 'msw-fetch-mock/node';
|
|
80
|
+
+ const fetchMock = createFetchMock(server);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
或使用單例進行獨立模式:
|
|
84
|
+
|
|
85
|
+
```diff
|
|
86
|
+
- import { rest } from 'msw';
|
|
87
|
+
- import { setupServer } from 'msw/node';
|
|
88
|
+
- import { createFetchMock } from 'msw-fetch-mock/legacy';
|
|
89
|
+
- const server = setupServer();
|
|
90
|
+
- const fetchMock = createFetchMock(rest, server);
|
|
91
|
+
+ import { fetchMock } from 'msw-fetch-mock';
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
其餘 API(`get()`、`intercept()`、`reply()`、`calls` 等)維持不變。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msw-fetch-mock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Undici-style fetch mock API built on MSW (Mock Service Worker)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,6 +57,15 @@
|
|
|
57
57
|
},
|
|
58
58
|
"import": "./dist/legacy.js",
|
|
59
59
|
"require": "./dist/legacy.cjs"
|
|
60
|
+
},
|
|
61
|
+
"./native": {
|
|
62
|
+
"source": "./src/native.ts",
|
|
63
|
+
"types": {
|
|
64
|
+
"import": "./dist/native.d.ts",
|
|
65
|
+
"require": "./dist/native.d.cts"
|
|
66
|
+
},
|
|
67
|
+
"import": "./dist/native.js",
|
|
68
|
+
"require": "./dist/native.cjs"
|
|
60
69
|
}
|
|
61
70
|
},
|
|
62
71
|
"files": [
|
|
@@ -81,6 +90,11 @@
|
|
|
81
90
|
"peerDependencies": {
|
|
82
91
|
"msw": "^1.0.0 || ^2.12.7"
|
|
83
92
|
},
|
|
93
|
+
"peerDependenciesMeta": {
|
|
94
|
+
"msw": {
|
|
95
|
+
"optional": true
|
|
96
|
+
}
|
|
97
|
+
},
|
|
84
98
|
"devDependencies": {
|
|
85
99
|
"@eslint/js": "^9.39.2",
|
|
86
100
|
"eslint": "^9.39.2",
|