Rails 7 + ReactにおけるJestを使ったテストの書き方

はじめに

Rails 7とReactを使ったサンプルアプリがあったので勉強がてら実装してみました。

techracho.bpsinc.jp

コンパクトにまとまったいい記事なのですが、テストが書かれていなかったので実装してみることにしました。なお、ここに書いているのはいわゆるベストプラクティスではなく、こうしたらとりあえず動いたというレベルで見ていただけると幸いです。

セットアップ

Jestを含めた各種ライブラリをインストールすることから始めます。Jestのサイトに以下の記事があったのでそれを参考にします。

jestjs.io

package.jsonにて以下の記述を追加しておくとnpm run testでテストが実行できるので追記しておきます。

  "scripts": {
    // ↓を追記
    "test": "jest"
  },

自分はテストをapp/javascript/__tests__に置くことにしたので、package.jsonにjestの設定を記述します。

  "jest": {
    "roots": [
      "<rootDir>/app/javascript"
    ]
  }

package.jsonではなくjestの設定ファイルとしてjest.config.jsを作成しても良いかと思います。

テストの書き方

各componentsに対してテストを書きます。DOMを操作するもののテストについては、React Testing Libraryを使うようです。

testing-library.com

他にもJest 28からの仕様変更によりjest-environment-jsdomの設定が必要でした。

testing-library.com

React Testing Libraryを使ったテストを書く場合、以下のドキュメントに書かれているクエリを発行してtesting-library/jest-domでのマッチャーを使ってテストを実装するようです。

testing-library.com

github.com

一番簡単なテストとしては以下のような実装となりました。

/**
 * @jest-environment jsdom
 */
import {render, screen} from "@testing-library/react";
import EventNotFound from "../components/EventNotFound";
import '@testing-library/jest-dom/extend-expect';

describe('EventNotFound', () => {
  test('renders EventNotFound component', () => {
    render(<EventNotFound />);
    expect(screen.getByText('Event not found!')).toBeInTheDocument();
  })
});

テストが失敗する例

context of a componentが出る

上記のような書き方でテストを実装すると、context of a <Router> componentというエラーが出てしまうケースがあります。この時は、MemoryRouterというものを使ってテストを書きます。

reactrouter.com

以下のようなテストになりました。

/**
 * @jest-environment jsdom
 */
import Header from "../components/Header";
import {render, screen} from "@testing-library/react";
import { MemoryRouter as Router } from "react-router-dom";
import '@testing-library/jest-dom/extend-expect';

test('renders Header', () => {
  render(
    <Router>
      <Header />
    </Router>
  );
  expect(screen.getByText('Event Manager')).toBeInTheDocument();
})

cssのimportにてSyntaxErrorが出る

テスト対象のcomponentにてimport 'pikaday/css/pikaday.css';というようにCSSを読み込んでいるとSyntaxErrorが出ました。この事象に対してはstackoverflowに類似の記事があったので、それを参考に解決します。

stackoverflow.com

具体的には、package.jsonにてJestの設定を追記します。

  "jest": {
    "roots": [
      "<rootDir>/app/javascript"
    ],
    "moduleNameMapper": {
      "\\.(css|less|sass|scss)$": "<rootDir>/app/javascript/__mocks__/styleMock.js"
    }
  }

その後、app/javascript/__mocks__/styleMock.jsというファイルを作成します。中身は以下の通りほぼ空です。

module.exports = {};

これでSyntaxErrorは出なくなりました。