0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vitest と Happy DOM を使用した React コンポーネントのテスト環境構築

Posted at

Vitest と Happy DOM を使用した React コンポーネントのテスト環境構築

React アプリケーションのテストを VitestHappy DOM を使用して行う手順を、以下の流れで説明します。


1. 必要なライブラリのインストール

まず、テストに必要なライブラリをインストールします。

コマンド

npm install --save-dev vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event happy-dom

ライブラリの説明

  • vitest: 高速なテストランナー。
  • @testing-library/react: React コンポーネントのテストを支援。
  • @testing-library/jest-dom: DOM に関するカスタムマッチャーを提供。
  • @testing-library/user-event: ユーザー操作(クリックなど)のシミュレーションをサポート。
  • happy-dom: 軽量で高速なブラウザエミュレーション環境。

2. React コンポーネントの作成

テスト対象となる簡単なボタンコンポーネントを作成します。

ファイル構成

src/
├── components/
│   ├── ButtonComponent.tsx
├── test/
│   ├── setup.ts
├── vite.config.ts

ButtonComponent.tsx のコード

import React from 'react';
import { Button } from '@mantine/core';

interface ButtonComponentProps {
  label: string;
  onClick: () => void;
}

const ButtonComponent: React.FC<ButtonComponentProps> = ({ label, onClick }) => {
  return (
    <Button onClick={onClick} data-testid="mantine-button">
      {label}
    </Button>
  );
};

export default ButtonComponent;

3. テストの準備

テストセットアップファイルの作成

setup.ts ファイルを作成し、テストに必要な設定を記述します。

setup.ts のコード

import '@testing-library/jest-dom';

// Happy DOM を使用する際に必要な設定
Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(),
    removeListener: vi.fn(),
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn(),
  })),
});

vite.config.ts の設定

vite.config.ts で Happy DOM を使用するように設定します。

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'happy-dom', // テスト環境を happy-dom に設定
    globals: true, // describe, it, expect などをグローバルで使用可能にする
    setupFiles: './src/test/setup.ts', // テストセットアップファイルを指定
  },
});

4. テストコードの作成

ButtonComponent をテストするコードを作成します。

ファイル構成

src/
├── components/
│   ├── __tests__/
│   │   ├── ButtonComponent.test.tsx

ButtonComponent.test.tsx のコード

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MantineProvider } from '@mantine/core';
import ButtonComponent from '../ButtonComponent';

describe('ButtonComponent', () => {
  test('renders with the correct label', () => {
    render(
      <MantineProvider>
        <ButtonComponent label="Click Me" onClick={() => {}} />
      </MantineProvider>
    );

    const buttonElement = screen.getByTestId('mantine-button');
    expect(buttonElement).toBeInTheDocument();
    expect(buttonElement).toHaveTextContent('Click Me');
  });

  test('calls onClick handler when clicked', async () => {
    const handleClick = vi.fn();
    render(
      <MantineProvider>
        <ButtonComponent label="Click Me" onClick={handleClick} />
      </MantineProvider>
    );

    const buttonElement = screen.getByTestId('mantine-button');
    await userEvent.click(buttonElement);

    expect(handleClick).toHaveBeenCalledTimes(1);
  });
});

5. テストの実行

テストが正常に動作することを確認します。

コマンド

npm run test

テスト結果

以下のような出力が表示されれば成功です:

 PASS  src/components/__tests__/ButtonComponent.test.tsx
  ButtonComponent
    ✓ renders with the correct label (x ms)
    ✓ calls onClick handler when clicked (x ms)

6. 補足

Happy DOM と jsdom の違い

  • Happy DOM:
    • 高速で軽量。
    • 基本的な DOM API のサポート。
    • シンプルなテストに適している。
  • jsdom:
    • DOM API のサポートが充実。
    • より複雑なブラウザシナリオに対応。

選択のポイント

複雑なブラウザ依存機能(例: getBoundingClientRect)が必要ない場合、Happy DOM は十分な選択肢です。


以上で、VitestHappy DOM を使った React コンポーネントのテスト環境構築とテストの実行手順が完了です!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?