TypeScript + Reactの開発環境にjestを導入する
重い腰をあげjestを導入します
jest
JavaScriptおよびTypeScriptのためのテストランナー
Jestのインストール
$ yarn add --dev jest
コマンド追加
package.json
にテスト用のコマンドを追加
ウォッチモードにしておきます
{
"scripts": {
"test": "jest --watch"
}
}
関連するパッケージのインストール
JavaScriptの場合これで動きますが、今回はTypeScript+Reactです
追加していきましょう
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に書き換える
いろいろ設定できるらしい
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のテストもあるため
testEnvironment
をnode
からjest-environment-jsdom
に変更します
const config = {
preset: 'ts-jest',
testEnvironment: 'jest-environment-jsdom'
}
パッケージ追加はここまで
まだテストが通らないのです.......
tsconfigの設定
jsx
TypeScriptプロジェクトでJSX(JavaScript XML)を処理する方法を指定するための設定
react
はJSXコードがトランスパイルされるため、出力されるJavaScriptコードには変更が加えられる
reactのプロジェクトではreact
にするのが推奨
今回はreact
にします
"compilerOptions": {
"jsx": "react",
}
補足
preserve
はJSXコードはそのままの形式で保持され、ビルド時間が短縮される
大規模プロジェクトではこっちにした方がいいかも?
preserve
の時はJSXコードはそのままの形式で保持される
なので、babel-jestなどでトランスパイルしないといけない
(多分こんな感じ)
const config = {
preset: 'ts-jest',
testEnvironment: 'jest-environment-jsdom',
transform: {
'^.+\\.tsx?$': ['babel-jest'],
}
}
next.jsは、自信でトランスパイルできるかつ、buildした際に勝手にpreserve
に戻されて煩わしいためpreserve
にしておく
(next.jsのjest導入についてはnext.js公式ドキュメントの手順でやった方が良さそう...)
テスト実行
いよいよテストを実行します...
簡単なテストを追加します
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