前提
前回のこちらの記事の続編になります。msw自体の説明や後述のコードはこちらを参考にしてください。
StoryBookとは
Storybookは、UIコンポーネントとページを分離して構築するためのオープンソースツールです。UIの開発、テスト、およびドキュメント化に活用することができます。動作イメージや仕様については以下の公式を参考ください。
StoryBookの環境準備
StoryBookCLIのCLIをインストールします。
npm install -g @storybook/cli
StoryBook環境の初期化を行います。
npx sb init
StoryBookを起動します。実行のコマンドは環境によってことなりますが、上記コマンドの最後に出力されると思います。以下はcreate-react-app+npmの環境の場合です。
npm run storybook
create-react-appで作成したプロジェクトでは@storybook/preset-create-react-app
のバージョンが低いと失敗したので、エラーが発生した場合、package.jsonを以下のように修正し、再度npm i
を実行してください。
"@storybook/preset-create-react-app": "^4.0.0",
起動後のブラウザで以下のようなデフォルトのストーリーファイル(Button,Header,Page)が表示されます。
msw連携
storybook起動時にmswのServiceWorker起動
mswとmswのstorybookの連携アドオンをインストールします
npm i -D msw msw-storybook-addon
mswのServiceWorkerを設定します。(前回の記事で設定していればスキップ可能です)
npx msw init public/ --save
.storybook/preview.js にプラグインを追加し、起動するようにします。
import { initialize, mswDecorator } from "msw-storybook-addon";
// Initialize MSW
initialize();
// Provide the MSW addon decorator globally
export const decorators = [mswDecorator];
.storybook/main.js を以下のように書き換えます。
module.exports = {
...
staticDirs: ["../public"], //追加
};
package.jsonを以下のように書き換えます。(-sオプションは6.4以降でdeprecatedなので消します)
"scripts": {
・・・
"storybook": "start-storybook -p 6006", //変更箇所
"build-storybook": "build-storybook" //変更箇所
},
この時点で一度起動(npm run storybook
)します。mswのServiceWorkerの起動に成功するとブラウザのコンソールログに以下のようなメッセージが表示されます。
ストーリーファイルからmswのAPIモックを呼び出す
前回作成したコンポーネント(UserList.tsx)に対するストーリーファイル(UserList.stories.tsx)を作成します。
前回カスタムフックのテスト用に作成したAPIモック(mocks/handlers.ts)をそのまま使うことができます。異常系のように普段のAPIと違う挙動をしたい場合、parameterを上書きすることもできます。
import { handlers } from "../mocks/handlers";
import { rest } from "msw";
import UserList from "./UserList";
export default {
title: "UserList",
component: UserList,
};
export const SuccessBehavior = () => <UserList />;
SuccessBehavior.parameters = {
// 正常系は定義済みのhandlersをそのまま利用
msw: {
handlers: handlers,
},
};
export const FailureBehavior = () => <UserList />;
FailureBehavior.parameters = {
// 異常系はhandlersを上書き
msw: {
handlers: [
rest.get("/api/users", (req, res, ctx) => {
return res(ctx.status(500), ctx.json({ message: "Internal Server Error" }));
}),
],
},
};
ストーリーファイルの作成場所を変更した場合、.storybook/main.jsも変更します。
module.exports = {
// stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
stories: ["../src/components/**/*.stories.@(js|jsx|ts|tsx)"], //components配下に移動した場合
...
再度storybookを起動します。(main.js等を書き換えた場合、再起動が必要です)
npm run storybook
StoryBook上で通信結果に応じた表示を確認することができました。
- API通信成功時に表示されるコンポーネント(コンソールには200 OK)
- API通信失敗時に表示されるコンポーネント(コンソールには500 Internal Error)
感想
前回のテストにmswを導入するだけではメリットを感じにくかったですが、こうやってStoryBookのデータ連携でも簡単に使えるとモチベーションがあがりました。StoryBook自体まだまだ初心者なので色々覚えていきたいと思います。
参考