msw
APIリクエストをインターセプトしてモックデータを返したりすることができるパッケージです。
今回はREST API(Fetch APIを利用)想定で進めます。
src/mocks/handlers.js
// src/mocks/handlers.js
import { http } from 'msw'
export const handlers = [
http.get('https://jsonplaceholder.typicode.com/todos/1', () => {
console.log('Captured a "GET https://jsonplaceholder.typicode.com/todos/1" request')
}),
http.post('/posts', () => {
console.log('Captured a "POST /posts" request')
}),
http.delete('/posts/:id', ({ params }) => {
console.log(`Captured a "DELETE /posts/${params.id}" request`)
}),
]
参照:https://mswjs.io/docs/network-behavior/rest
リクエストハンドラ
http.get('/posts', () => {
console.log('Captured a "GET /posts" request')
}),
参照:https://mswjs.io/docs/network-behavior/rest
レスポンスリゾルバ
HttpResponse部分のこと
http.get('/posts', () => {
return HttpResponse.json(Array.from(allPosts.values()))
}),
参照:https://mswjs.io/docs/network-behavior/rest
リクエスト本文を読み取る
request本文を読み取る
request.json()はPromiss型を返すためawaiが必要
request.json() は、リクエストのボディを JSON 形式として解析するためのメソッド
http.post('/posts', async ({ request }) => {
const newPost = await request.json()
allPosts.set(newPost.id, newPost)
return HttpResponse.json(newPost, { status: 201 })
}),
参照:https://mswjs.io/docs/network-behavior/rest
パスパラメータの読み取り
リクエストパス内の1つのセグメント内でパラメーターを読み取る
「/posts/[任意の値]」があれば引っかかるようになる
http.delete('/posts/:id', ({ params }) => {
const { id } = params
const deletedPost = allPosts.get(id)
if (!deletedPost) {
return new HttpResponse(null, { status: 404 })
}
allPosts.delete(id)
return HttpResponse.json(deletedPost)
}),
参照:https://mswjs.io/docs/network-behavior/rest
mockServiceWorker.js
npx msw init ./public --save
実行するとpackage.jsonに登録される。
mockServiceWorker.jsの保存先が登録され読み込みが行われる。
{
"name": "my-app",
"msw": {
"workerDirectory": "./public"
}
}
参照:https://mswjs.io/docs/cli/init
src/mocks/browser.ts
Browser integration
フロントサイドでモックサーバーを起動する
import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'
export const worker = setupWorker(...handlers)
参照:https://mswjs.io/docs/integrations/browser
src/mocks/server.ts
Node.js integration
SSR
import { setupServer } from 'msw/node'
import { handlers } from './handlers'
export const server = setupServer(...handlers)
参照:https://mswjs.io/docs/integrations/node
pages/_app.tsx
フロントサイドかサーバーサイドかの判定が必要
これはmswのissueにも問題が上がってた対策です
開発環境のみで動くようにすることも必要(process.env.NODE_ENV)
if (process.env.NODE_ENV === 'development') {
if (typeof window !== 'undefined') {
import('../mocks/browser').then(({ worker }) => {
worker.start()
});
}else{
import('../mocks/server').then(({ server }) => {
server.listen()
});
}
}
起動確認
npm run dev
pages/index.tsx
index.tsxでインターセプトするURLをfetchで呼び出してみましょう
const test = async () => {
await fetch("https://jsonplaceholder.typicode.com/todos/1");
return;
};
おまけ
今回はPageRouterなので検証していないが、appRouterの場合はこちらにexampleがあります(まだDraftですが・・・)