React Remixのユニットテストセットアップ


注意

Remix は 2022 年 4 月時点でかなり活発に開発が進んでいるフレームワークなので、この記事の内容はバージョン差異や作成時期により再現できない可能性があります。

この記事で利用したテンプレートは下記のコマンドで作成し、CloudFlare Pages の構成を選択した構成です。typescript 利用です。

npx create-remix@latest
  • remix: 1.3.3
  • wrangler: beta

Remix のユニットテスト

下記のように remix-run 経由でユニットテスト関連の関数を利用できる計画が進行中のようです。ただ、1.3.3 時点だと作成中で、まだありません。自身で色々追加する必要があります

import {} from "@remix-run/tests";

今回の記事は下記のコミットおよび、github の repository をほぼそのままに導入しました。

将来的に remix-run から提供されるのは jest ではなく vitest?後々 remix から tests が提供されたときに移行しやすいよう、上記で導入されている vitest を追加することにしました。個人的には、@testing-library が使えるなら jest でも vitest でも良いので。

vitest、@testing-library の追加

必要なライブラリを全て導入します。user-event や testing-library/jest-dom は必須ではないです。あると便利。

@testing-library

yarn add -D @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event

vitest

yarn add -D vite vitest vite-tsconfig-paths @vitejs/plugin-react @happy-dom

config 設定

remix.config.je

module.exports = {
  // ignoredRouteFilesにテストファイルを追加。index.spec.tsxのように書く想定
  ignoredRouteFiles: [".*", "**/*.spec.{js,jsx,ts,tsx}"],

vitest.config.ts

/// <reference types="vitest" />
/// <reference types="vite/client" />

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  plugins: [react(), tsconfigPaths()],
  test: {
    globals: true,
    environment: "happy-dom",
    setupFiles: "./setup-test-env.ts",
  },
});

setup-test-env.ts

import "@testing-library/jest-dom";

テストのイメージ

通常の React の Component のテストは動作。server Component など Remix 固有系はテスト書けていないので不明。

import React from "react";
import { render, within, act, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { PaymentCard } from "./index";

const CATEGORY = "テストカテゴリ";
const PAYMENT = "1500";
const renderComp = () => {
  const utils = render(<PaymentCard category={CATEGORY} payment={PAYMENT} />);
  return {
    ...utils,
  };
};

describe("PaymentCard", () => {
  test("カテゴリが表示されること", () => {
    const { getByTestId } = renderComp();
    const category = within(getByTestId("payment-card-category"));
    expect(category.queryByText(CATEGORY)).toBeInTheDocument();
  });
});

感想

vitest と happy-dom という使ったことがないものが出てきていて、テストも jest + jest-dom の組み合わせから esmodule を使った次の段階への移行が始まっているのかなという印象です。ただ、jest で書いたテストはほぼそのまま動いたので、開発者目線だとストレスはなく、テスト早くなって良かった!というところ。実装の詳細をテストしない@testing-library の思想とても好き。今回の組み合わせは浅いところしか触っていないので深淵はどうなっているやらですがひとまず安心です。

ユニットテストより上の階層だと、cypress + msw の組み合わせが React 界隈だとデファクト(Kent さん強すぎるからだとは思いつつも)になりつつあるのかなと感じていて、Remix もその流れではあるようです。

e2e テスト書くとき、仕事だと chrome だけでは。。。という話になって selenium ラップした何かを 使いがちなものの、結局日常的にはほぼ chromedriver しか使っていないとかあるので、最初から cypress 全力というのもそろそろありなのかなと思ったりしてきました。

Remix の技術選定は勉強になるので、遊びながら引き続き勉強させてもらおうかなと思います。