🩰

TypeScript + Reactの開発環境にjestを導入する

2023/07/04に公開

重い腰をあげjestを導入します

jest

JavaScriptおよびTypeScriptのためのテストランナー

Jestのインストール

jest

$ yarn add --dev jest

コマンド追加

package.jsonにテスト用のコマンドを追加
ウォッチモードにしておきます

package.json
{
  "scripts": {
    "test": "jest --watch"
  }
}

関連するパッケージのインストール

JavaScriptの場合これで動きますが、今回はTypeScript+Reactです
追加していきましょう

TypeScript

TypeScript を使用する

@types/jest

jestの型定義
@types/jest

$ yarn add --dev @types/jest

ts-jest

JestをTypeScriptに対応させるためのもの
ts-jest

$ yarn add --dev ts-jest

設定ファイル

$ yarn ts-jest config:init

jest.config.jsがcommonJSで生成される
今回はpackage.jsonで"type": "module"に設定しているため
ECMAScriptに書き換える

いろいろ設定できるらしい
https://jestjs.io/docs/configuration

TypeScriptだけならここまででOKですが、まだReactが残っています!

React

react-testing-library

Reactコンポーネントをテストするためのライブラリ
react-testing-library

$ yarn add --dev @testing-library/react

jest-dom

DOMアサーションライブラリ
jest-dom

$ yarn add --dev @testing-library/jest-dom 

jest-environment-jsdom

ブラウザのDOM環境をシミュレートするライブラリ
jest-environment-jsdomを追加
Jestテスト内でDOM操作やDOM関連のテストを実行することを可能にする

$ yarn add --dev jest-environment-jsdom 

@testing-library/user-event

react-testing-libraryでのテスト中にユーザーの操作をシミュレートするための補助ツール
これを使用することで、ユーザーの操作をよりリアルに再現し、テストの品質と信頼性を向上させることができるらしい
@testing-library/user-event

yarn add --dev @testing-library/user-event

設定

今回はDOMのテストもあるため
testEnvironmentnodeからjest-environment-jsdomに変更します

jest.config.mjs
const config = {
  preset: 'ts-jest',
  testEnvironment: 'jest-environment-jsdom'
}

パッケージ追加はここまで

まだテストが通らないのです.......

tsconfigの設定

jsx

TypeScriptプロジェクトでJSX(JavaScript XML)を処理する方法を指定するための設定
reactはJSXコードがトランスパイルされるため、出力されるJavaScriptコードには変更が加えられる
reactのプロジェクトではreactにするのが推奨
今回はreactにします

tsconfig.json
"compilerOptions": {
	"jsx": "react",
}

補足

preserveはJSXコードはそのままの形式で保持され、ビルド時間が短縮される
大規模プロジェクトではこっちにした方がいいかも?

preserveの時はJSXコードはそのままの形式で保持される

なので、babel-jestなどでトランスパイルしないといけない
(多分こんな感じ)

jest.config.mjs
const config = {
  preset: 'ts-jest',
  testEnvironment: 'jest-environment-jsdom',
  transform: {
    '^.+\\.tsx?$': ['babel-jest'],
  }
}

next.jsは、自信でトランスパイルできるかつ、buildした際に勝手にpreserveに戻されて煩わしいためpreserveにしておく
(next.jsのjest導入についてはnext.js公式ドキュメントの手順でやった方が良さそう...)

テスト実行

いよいよテストを実行します...
簡単なテストを追加します

Button.test.tsx
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import Button from './Button';

describe('Button', () => {
  it('should call onClick when clicked', async () => {
    const user = userEvent.setup();
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click Me</Button>);
    const button = screen.getByRole('button', { name: /click me/i });

    await user.click(button);

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

こんな感じで!通りますよね!よかった〜

Discussion