はじめに
今回はViteとTypeScriptのアプリを作成し、テストを行った際にエラーが発生したので、解決方法をまとめます。
開発環境
言語・フレームワーク | バージョン |
---|---|
supabase/supabase-js | 2.45.4 |
Node.js | 18.17.1 |
react | 18.3.1 |
typescript | 5.5.3 |
ts-jest | 29.2.5 |
vite | 5.4.8 |
テスト内容
テストの内容は、h1
タグのdata-testid="title"
を取得するという簡単なものです。
【テスト対象ファイル】
return (
<>
<h1 data-testid="title">TODOリスト</h1>
...
</>
【テスト実行ファイル】
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import App from '../App';
// createClient関数をモック
jest.mock('@supabase/supabase-js', () => ({
createClient: jest.fn(() => ({
from: jest.fn().mockReturnThis(),
select: jest.fn().mockResolvedValue({ data: [], error: null }),
insert: jest.fn().mockResolvedValue({ error: null }),
delete: jest.fn().mockResolvedValue({ data: [], error: null }),
eq: jest.fn().mockReturnThis(),
})),
}));
describe('App', () => {
test('タイトルがあること', async () => {
render(<App />);
const title = screen.getByTestId('title');
await waitFor(() => {
expect(title).toBeInTheDocument();
});
});
});
エラー内容
エラーは1つ解消しては、また別のエラーが発生するというように複数生じたため、できるだけ時系列にまとめて書きたいと思います。
1. jsdomの環境変数の使い方が間違っている。
FAIL src/__tests__/App.spec.tsx
App
✕ タイトルがあること (4 ms)
● App › タイトルがあること
The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string.
Consider using the "jsdom" test environment.
対応策としては、テスト実行ファイルの先頭に以下のコメントを追記しました。
/**
* @jest-environment jsdom
*/
2. toBeInTheDocument()が見つからない
1の対応策を行ったところ、続いて以下のエラーが発生しました。
FAIL src/__tests__/App.spec.tsx
App
✕ タイトルがあること (1101 ms)
● App › タイトルがあること
TypeError: expect(...).toBeInTheDocument is not a function
Ignored nodes: comments, script, style
こちらについては、新たにインポート文をテスト実行ファイルに追加しました。
import '@testing-library/jest-dom';
3. dotenvが見つからない
最後のエラーは、dotenvが見つからないとのこと。
FAIL src/__tests__/App.spec.tsx
● Test suite failed to run
Cannot find module 'dotenv' from 'jest.setup.ts'
そのため、dotenvをインストールするコマンドを実行。
npm i dotenv --save-dev
テスト実行ファイル修正
「エラー内容」で記載した修正を行った後、テスト対象ファイルのApp.tsx
ではデータベースに登録している内容を非同期で取得して表示している箇所があります。
そちらの処理完了前にテスト実行ファイルのApp.spec.tsx
が実行されてしまうことを考慮し、testid
を取得する処理も非同期に行うことで、無事テストが通りました。
【テスト実行ファイル】
import { render, screen, waitFor } from "@testing-library/react";
import App from "../App";
import '@testing-library/jest-dom';
describe("App", () => {
test("タイトルがあること", async () => {
render(<App />);
await waitFor(() => {
const title = screen.getByTestId("title");
expect(title).toBeInTheDocument();
})
});
});
PASS src/__tests__/App.spec.tsx (7.081 s)
App
✓ タイトルがあること (119 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.31 s
Ran all test suites.
最後に
テストを実行する際に多くの設定ファイルを編集する必要があり、依存関係の理解が少し進みました。
解釈が違うところや、別の書き方を推奨している場合などあれば、コメントで教えてください。
参考サイト