背景
テストについて学んでいる中で、Vitestを使いたいとなった時に環境構築で時間を溶かしたのでその備忘です。
事前の環境
Vite + React + TypeScript
やりたいこと
function Home() {
return <h1>Vitestを使いたい</h1>;
}
export default Home;
このようなコンポーネントに対して、以下のようなテストをしようとしました。(取ってきた要素が指定の文字列になっているか)
test("「Vitestを使いたい」の文字が表示されるか", () => {
render(<Home />);
const target = screen.getByRole("heading", { level: 1 });
expect(target).toHaveTextContent("Vitestを使いたい");
});
最初の準備と出たエラー
まずはVitest, Testing Libraryのドキュメントを参考に必要なものをインストールしました。
npm install -D vitest
npm install --save-dev @testing-library/react
toHaveTextContentはjest-domの機能なのでjest-domをインストールしました。
npm install --save-dev @testing-library/jest-dom
今のHome.test.tsxの状態は以下のような感じです。
import { expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Home from "./Home";
test("「Vitestを使いたい」の文字が表示されるか", () => {
render(<Home />);
const target = screen.getByRole("heading", { level: 1 });
expect(target).toHaveTextContent("Vitestを使いたい");
});
Vitestのドキュメントにある設定を追加して、
{
"scripts": {
"test": "vitest"
}
}
これでnpm run test
したところ、
ReferenceError: expect is not defined
このようなエラーが出ました。
このエラーを解消するために以下のことをやっていきました。
解消するためにしたこと
jest-domまわり
jest-domのドキュメントを見ると、環境ごとの設定が書いてあります。
Vitestを使ってる場合や、TypeScriptを使ってる場合の記述があるのでそれを実行していきます。
Vitest用
import "@testing-library/jest-dom/vitest";
上記でVitest用のjest-domをインポートしてるのでHome.test.tsxの方でimportしているjest-domの設定は削除しました。
import { expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import Home from "./Home";
test("「Vitestを使いたい」の文字が表示されるか", () => {
render(<Home />);
const target = screen.getByRole("heading", { level: 1 });
expect(target).toHaveTextContent("Vitestを使いたい");
});
/// <reference types="vitest" />
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
test: {
setupFiles: ["./vitest-setup.ts"],
},
});
jest-domのドキュメントを見ると「vitest.config.js」となっていますが、
Vitestのドキュメントを見ると一つにまとめるやり方を推奨していたので既にある「vite.config.ts」に設定を入れました。
また、その場合は一番上の行の「///〜〜」の内容を入れる必要があります。
(それとTypeScriptなので.jsではなく.tsに注意)
TypeScript用
"include": [
...
"./vitest-setup.ts"
],
さらに、
「With another Jest-compatible expect」
とあるので、今回はJestではなくVitestを使っているのでこちらの設定も入れました。
import { expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import Home from "./Home";
import * as matchers from "@testing-library/jest-dom/matchers";
expect.extend(matchers);
test("「Vitestを使いたい」の文字が表示されるか", () => {
render(<Home />);
const target = screen.getByRole("heading", { level: 1 });
expect(target).toHaveTextContent("Vitestを使いたい");
});
これで再度npm run test
すると、
ReferenceError: expect is not defined
まだエラーが出てます。とほほ。。
jsdomまわり
ドキュメントのセットアップ関連を見ると、Testing LibraryのドキュメントのReactのSetupページに、「Using without Jest」と書いている内容があります。
今回JestではなくVitestを使っているのでこれに該当するjsdomをインストールしました。
npm install --save-dev jsdom
また、Vitestのドキュメントに、使う環境(jsdomを使うのか他のものを使うのか)を設定する内容が書いてあるのでそれを反映しました。
// @vitest-environment jsdom
import { expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import Home from "./Home";
import * as matchers from "@testing-library/jest-dom/matchers";
expect.extend(matchers);
test("「Vitestを使いたい」の文字が表示されるか", () => {
render(<Home />);
const target = screen.getByRole("heading", { level: 1 });
expect(target).toHaveTextContent("Vitestを使いたい");
});
これでnpm run test
したところ、
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 14:18:53
Duration 423ms (transform 20ms, setup 51ms, collect 43ms, tests 20ms, environment 215ms, prepare 31ms)
無事テストが通りました👏
Home.tsxの内容を、
function Home() {
return <h1>Vitest難しい</h1>;
}
export default Home;
と変更して再度テストすると、
Expected element to have text content:
Vitestを使いたい
Received:
Vitest難しい
Test Files 1 failed (1)
Tests 1 failed (1)
Start at 14:21:23
Duration 437ms (transform 22ms, setup 56ms, collect 51ms, tests 23ms, environment 217ms, prepare 31ms)
きちんと失敗しています。
参考