🧪
StorybookでもVitestのMockが使えるようになりました
概要
Storybookでは外部APIとのやり取りなどを行う複雑なモジュールをモックする仕組は存在していたものの、セットアップが複雑であったために導入を諦めた方はいらっしゃると思います。
VitestのMockモジュールさえ使えれば。。!
そんなことを思ったことはありませんか?実はStorybookにて最近導入されたsb.mock()を利用することで、VitestのMockを利用できるようになったのです。
参考リポジトリ
導入方法
ここではTodoリストを取得するフックをtodos/queries.tsモックする方法を紹介します
todos/queries.tsは以下のようになっています
import { useQuery } from "@tanstack/react-query";
import { fetchTodos } from "./api";
export function useGetTodos() {
return useQuery({
queryKey: ["todos"],
queryFn: fetchTodos, // 外部APIを叩いている
});
}
preview.tsファイルにてモックしたいファイルを指定
.storybook/preview.tsxにてモックしたいモジュールのファイルを指定します
import type { Preview } from '@storybook/react-vite'
import { sb } from 'storybook/test'
sb.mock(import('../src/features/todos/queries.ts'))
モックを利用しているコンポーネントのstoryを実装
todos/queries.tsを利用しているコンポーネントのstoryを実装します。sb.mock()によってuseGetTodosをモック可能になったため、以下のような実装が可能になります。
import type { Meta, StoryObj } from '@storybook/react-vite';
import { TodoList } from './TodoList';
import { useGetTodos } from '../features/todos/queries';
import type { Mock } from 'vitest';
const meta: Meta<typeof TodoList> = {
title: 'Components/TodoList',
component: TodoList,
};
export default meta;
type Story = StoryObj<typeof TodoList>;
export const Default: Story = {
beforeEach: () => {
(useGetTodos as unknown as Mock).mockReturnValue({
isLoading: false,
isError: false,
data: [
{ id: 1, title: 'Learn Storybook', completed: false },
{ id: 2, title: 'Build a Todo App', completed: true },
{ id: 3, title: 'Master Tailwind CSS', completed: false },
],
});
},
};
Interaction Testも実施可能
モックされたモジュールを用いてレンダリングされたコンポーネントのInteraction Testも可能です。以下はisErrorがtrueの時にエラー状態になっていることを確認するテストです。
export const Error: Story = {
beforeEach: () => {
useGetTodosMock.mockReturnValue({
isLoading: false,
isError: true,
data: undefined,
});
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByText('Error loading todos. Please try again later.')).toBeInTheDocument();
},
};
また上記テストをGithub Actions上でも実行可能です。
Discussion