Vite + React + TypeScript に Jest + Testing Library を入れる

Vite + React + TypeScript 環境に Jest + Testing Library を入れてテストを書けるようにする。

導入は下記記事のコピペになった。

一応公式サイトも参照する。

Jest 導入

npm install jest --save-dev
npm install @types/jest --save-dev
npm install ts-jest --save-dev

jest.config.json を作り、下記内容を入力。

{
  "roots": [
    "<rootDir>/src"
  ],
  "testMatch": [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)"
  ],
  "transform": {
    "^.+\\.(ts|tsx)$": "ts-jest"
  }
}

package.json に “test” を追加。“test:watch” は追加するほどでもないので追加していない。

"scripts": {
  // 中略
  "test": "jest --config ./jest.config.json"
}

Jest 動作確認

試験対象は下記のバリデータで独自のバリデーションメソッドを設定している箇所。

sololog_gql/sololog_front/src/validate/Blog.ts

export const PasswordValidator = (showPasswordInput: boolean) => {
  return {
    validate: (value: string) => {
      if (showPasswordInput && value === "") {
        return CONSTANT.ERROR_MESSAGE.REQUIRED;
      }
    },
    // 中略
  };
};

個人的にテストコードはテスト対象と同ディレクトリにあるほうがいいので、同ディレクトリに Blog.test.ts を作成。

import { CONSTANT } from "../constants";
import { PasswordValidator } from "./Blog";

describe("PasswordValidator", () => {
  test("showPasswordInput = true のとき、未入力だとエラーになる", () => {
    const validator = PasswordValidator(true);
    expect(validator.validate("")).toBe(CONSTANT.ERROR_MESSAGE.REQUIRED);
  });

  test("showPasswordInput = true のとき、入力済だとエラーにならない", () => {
    const validator = PasswordValidator(true);
    expect(validator.validate("a")).toBe(undefined);
  });

  test("showPasswordInput = false のとき、未入力でもエラーにならない", () => {
    const validator = PasswordValidator(false);
    expect(validator.validate("")).toBe(undefined);
  });
});

Testing Library 導入

npm install @testing-library/react --save-dev
npm install @testing-library/jest-dom --save-dev 
npm install @testing-library/user-event --save-dev
npm install @testing-library/react-hooks --save-dev
npm install --save-dev jest-environment-jsdom

jest.config.json に testEnvironment 設定を追加。

{
  "roots": ["<rootDir>/src"],
  // 中略
  "testEnvironment": "jest-environment-jsdom"
}

import '@testing-library/jest-dom' を書かないといけない点は、私は毎回テストファイルに書くことにするので設定への追記はしない。

Testing Library 動作確認

試験対象はリンクコンポーネント。

sololog_front/src/ui/LinkText.tsx

import { ExternalLinkIcon } from "@chakra-ui/icons";
import { Text } from "@chakra-ui/react";

interface LinkTextProps {
  text: string;
  isExternal?: boolean;
}

export const LinkText = (props: LinkTextProps) => {
  if (props.isExternal) {
    return (
      <Text as="u" color="blue.600" wordBreak={"break-word"}>
        {props.text}&nbsp;
        <ExternalLinkIcon mx="2px" data-testid="test-external-link-icon" />
      </Text>
    );
  }
  return (
    <Text as="u" color="blue.600" wordBreak={"break-word"}>
      {props.text}
    </Text>
  );
};

<ExternalLinkIcon /> の存在チェックのテストを書きたかったが、これを指定するいい方法が思いつかなかったので data-testid 属性を追加している。

同ディレクトリに LinkTest.test.tsx を作成。

import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { LinkText } from "./LinkText";

test("text が描画されている", () => {
  render(<LinkText text="http://example.com" />);
  screen.debug();
  expect(screen.getByText("http://example.com")).toBeInTheDocument();
});

test("isExternal = true のとき ExternalLinkIcon が描画されている", () => {
  render(<LinkText text="http://example.com" isExternal={true} />);
  screen.debug();
  expect(screen.queryByTestId("test-external-link-icon")).toBeInTheDocument();
});

test("isExternal = false のとき ExternalLinkIcon が描画されていない", () => {
  render(<LinkText text="http://example.com" isExternal={false} />);
  screen.debug();
  expect(
    screen.queryByTestId("test-external-link-icon")
  ).not.toBeInTheDocument();
});

test("isExternal 未指定のとき ExternalLinkIcon が描画されていない", () => {
  render(<LinkText text="http://example.com" />);
  screen.debug();
  expect(
    screen.queryByTestId("test-external-link-icon")
  ).not.toBeInTheDocument();
});

data-testid="test-external-link-icon" の要素が存在しないことを試験する場合、screen.getByTestId で要素を取ると要素が存在しないとき例外が発生するので NG。

screen.queryByTestId を使うと要素が存在しなくてもエラーにならない。

特定のテストだけ実行する方法

npm run test、つまり本記事においては jest --config ./jest.config.json を実行するとすべてのテストコードが実行され、割と遅い。

npm run test path/to/test のように試験したいテストが存在するパスを指定すると、特定ディレクトリまたは特定ファイルのみテストを実行できる。

以上