はじめに
こんにちは、エンジニアのkeitaMaxです。
今回はmswを使用してStorybookでAPIを呼び出すテストを書いていこうと思います。
Laravel10,Inertia.js,React,Storybookを使用します。
インストール
以下コマンドでインストールします。
npm install msw@latest --save-dev
npm i msw msw-storybook-addon -D
mswの初期設定
以下コマンドで初期設定します。
まずmsw
ファイルをpublic
と同じ階層に作成します。
その後以下のコマンドを実行します。
npx msw init msw/ --save
するとmsw
フォルダ配下にmockServiceWorker.js
ファイルが作成されます。
※これしないと、以下のようにbuildする時に怒られます。
(!) The public directory feature may not work correctly. outDir /Users/niheikeita/develop/real-estate-search-app/src/public/build and publicDir /Users/niheikeita/develop/real-estate-search-app/src/public are not separate folders.
Storybookの設定
preview.tsの設定
以下のようにloaders: [mswLoader],
を追加します。
import type { Preview } from "@storybook/react";
import "../resources/css/app.css";
import { initialize, mswLoader } from 'msw-storybook-addon' // 追加
initialize()
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
loaders: [mswLoader], // 追加
};
global.route = (name, params, absolute) => {
return `/${name}`;
};
export default preview;
vite.config.jsの修正
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
laravel({
input: 'resources/js/app.tsx',
refresh: true,
}),
react(),
],
publicDir: 'public', // 追加
});
※これ設定しないと以下のようにエラーが出るので注意してください。
Error: [MSW] Failed to register a Service Worker for scope ('http://localhost:6007/') with script ('http://localhost:6007/mockServiceWorker.js'): Service Worker script does not exist at the given path.
at async startWorkerInstance (/node_modules/.cache/storybook/dd4df79305cd50a532e8ccaa21ee67a8cbbc890739d67fa2856713328caf1b91/sb-vite/deps/msw-storybook-addon.js?v=0d345a9a:1202:24))
at async SetupWorkerApi.start (/node_modules/.cache/storybook/dd4df79305cd50a532e8ccaa21ee67a8cbbc890739d67fa2856713328caf1b91/sb-vite/deps/msw-storybook-addon.js?v=0d345a9a:2709:12))
テストの作成
実際にテストを書いてみます。
/api/upload
というAPIを読んでいるコンポーネントがあったので、それをモックしてみようと思います。
以下のようになります。
import { Meta, StoryObj } from '@storybook/react';
import { UploadImageArea } from '.';
import { useState } from 'react';
import { HttpResponse, ResponseResolver, http } from 'msw';
const meta: Meta<typeof UploadImageArea> = {
title: 'views/Admin/PropertyRegister/components/UploadImageArea',
component: UploadImageArea,
// 追加 ⇩ ⇩ ⇩ ⇩
parameters: {
msw: {
handlers: [
http.post('/api/upload', () => {
return HttpResponse.json({
test: 'Test',
})
}),
],
},
},
// 追加⇧⇧⇧⇧
tags: ['autodocs'],
}
export default meta
type Story = StoryObj<typeof meta>
export const Test: Story = {
render() {
const [images, setImages] = useState<{ url: any; id: any; }[]>([]);
return (
<UploadImageArea
images={images}
onImageChange={setImages} />
)
},
}
これでnpm run storybook
コマンドを叩いてtest: 'Test'
というレスポンスが来ているか確認すると、しっかりと設定した値が返却されていることがわかります。
おわりに
StorybookだけだとAPIのテストができないということで困ったこともあったのですが、mswを使用すると簡単にテストができました。
今後も積極的に使用していきたいと思います。
この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。
最後まで読んでいただきありがとうございました!
参考