StorybookでMock Service Worker (MSW) を使えるようにする。
この記事は、Storybookの component story format 3.0 で利用できるようになったPlay functionsでmockサーバーを利用するために Mock Service Worker (MSW) を使えるようにするための議事録です。
今回は、msw-storybook-addon というアドオンを適応します。
MSWとアドオンをインストールする
yarn add msw msw-storybook-addon -D
パブリックフォルダーにMSWのServiceWorkerを生成する
サービスワーカーのセットアップを実施します。
一から記述するのは大変面倒なので、mswが提供しているinit
を利用します。
npx msw init public/ --save
アドオンを構成する
.storybook/preview.js
でMSWを初期化し、mswDecorator
を用いてStorybookでMSWを利用できるようにします。
import { initialize, mswDecorator } from 'msw-storybook-addon';
// Initialize MSW
initialize();
// Provide the MSW addon decorator globally
export const decorators = [mswDecorator];
Storybookのstatic directoryを指定
Storybook がルートパスからアクセスできるディレクトリ(static directory)を指定します。
今回は、public/
です。.storybook/main.js
のstaticDirs
に設定します。
module.exports = {
// ...
staticDirs: ['../public'],
};
MSWが動いているかどうか確認する
設定したMSWが起動されているかどうか確認します。
yarn storybook
# Storybookを立ち上げるためのコマンド
立ち上がったStorybook上のdevtoolコンソールで、下記のメッセージが表示されていれば成功です。
[MSW] Mocking enabled.
リクエストハンドラーを設定する
リクエストハンドラーを個別に設定する場合は、ストーリーコンポーネントのparameters
に設定を渡します。
handlers
には、配列かObjectで渡すことができます。
import { ComponentStory } from '@storybook/react'
import { rest } from 'msw'
export const SuccessBehavior: ComponentStory<typeof UserProfile> = (args) => <UserProfile {...args} />
SuccessBehavior.parameters = {
msw: {
handlers: [
rest.get('/user', (req, res, ctx) => {
return res(
ctx.json({
firstName: 'Neil',
lastName: 'Maverick',
})
)
}),
]
},
}
共通のリクエストハンドラーを設定する
ほとんどのコンポーネントが/login
などをモックする必要がある場合、preview.js
でグローバルなリクエストハンドラーを設定することができます。
// These handlers will be applied in every story
export const parameters = {
// ...
msw: {
handlers: {
auth: [
rest.get('/login', (req, res, ctx) => {
return res(
ctx.json({
success: true,
})
)
}),
rest.get('/logout', (req, res, ctx) => {
return res(
ctx.json({
success: true,
})
)
}),
],
}
}
};
個々のストーリーコンポーネントで他のリクエストハンドラーを使用できます。
個々で設定したリクエストハンドラーはグローバルに設定したリクエストハンドラーとマージされます。
// This story will include the auth handlers from preview.js and profile handlers
SuccessBehavior.parameters = {
msw: {
handlers: {
profile: rest.get('/profile', (req, res, ctx) => {
return res(
ctx.json({
firstName: 'Neil',
lastName: 'Maverick',
})
)
}),
}
}
}
特定のリクエストハンドラーにオーバーライトする
グローバルに設定したリクエストハンドラーを特定のストーリーコンポーネントで書き換えたい場合は、特定のkeyに合わせるよう設定することでオーバーライトすることができます。
// This story will overwrite the auth handlers from preview.js
FailureBehavior.parameters = {
msw: {
handlers: {
auth: rest.get('/login', (req, res, ctx) => {
return res(ctx.status(403))
}),
}
}
}
最後に
MSWは、通常のモックサーバーとしても利用できる為、テスト以外の目的でも便利に利用することができそうです。
今回初めてStorybookのformat 3.0を利用したのですが、ユーザの利用ケース事にテストを書くことができ、管理画面も提供できるので、そのまま仕様書として出しても申し分なさそうなものを作成することができました。
ハッカー飯で丁寧にテストについて教えていただいたてんかわさんにはすごく感謝です。🙌
次のTRYとして近いうちに、chromaticを用いたビジュアルリグレッションテストも実施してみたいと思います。
フロントエンドのテストもどこまでやるのがベストなのか、まだ模索していますが、これからもインプットとアウトプットしていきたいと思います。
参考
Discussion