👋

Jest実行時のエラー、"SyntaxError: Unexpected token '<'"の解消法

2024/03/17に公開

表題のエラー解消に手間取ったので、
備忘として記事にしておきます。

やろうとしたこと

以下のような感じでコンポーネントのテストを書きましたが、
実行しようとした際に、表題のエラーで怒られました。

BookDisplay.test.tsx
/**
 * @jest-environment jsdom
 */

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

const mockBookInfo = {
  title: "テストの本",
  author: "テスト 著者",
  publisher: "テスト出版社",
  pubdate: "202302",
};

test("BookDisplayコンポーネントが正しくレンダリングされる", () => {
  // モックの関数を作成
  const mockHandleBuyButton = jest.fn();

  render(
    <BookDisplay
      bookInfo={mockBookInfo}
      handleBuyButton={() => mockHandleBuyButton(mockBookInfo)}
    />
  );

  // コンポーネントが正しく表示されているかをテスト
  expect(screen.getByText("以下の本が選ばれました!")).toBeInTheDocument();
  expect(screen.getByText("テストの本")).toBeInTheDocument();
  expect(
    screen.getByText("テスト 著者, テスト出版社, 2023/02")
  ).toBeInTheDocument();

  // ボタンをクリックしてモック関数が呼ばれるかをテスト
  fireEvent.click(screen.getByText("この本を購入"));
  expect(mockHandleBuyButton).toHaveBeenCalled();
});

解決法

結論から書くと、tsconfig.jsonのjsxが、
"react-jsx"ではなく、"preserve"となっていたからです。

Next.jsではtsconfig.jsonの該当項目はビルド時に自動的に"preserve"に書き換わる挙動をするようだったので、
テスト用の設定ファイルを別に作成し、以下のような形になりました。

tsconfig.test.json
{
  "extends": "./tsconfig.json",
  "include": ["./**/*"],
  "compilerOptions": {
    "jsx": "react-jsx"
  }
}
jest.config.js
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  globals: {
    'ts-jest': {
        tsconfig: '<rootDir>/tsconfig.test.json'
    }
  }
};

やっていることとしては、Jest用のconfigを別に作り、
jsxの値を別で定義したということです。

jsxというオプションについて

今回問題となったjsxオプションがどういったものなのかについても簡単に書いておきます。

TypeScriptの公式ドキュメントには、以下のように記載されています。

Controls how JSX constructs are emitted in JavaScript files. This only affects output of JS files that started in .tsx files.

簡単に言うと、コンパイルされた際にjsxファイルをどのように解釈するかが、
指定する値によって変わってくるということです。

※公式ドキュメントに、指定する値によってどのように解釈が変わるのかが記載されています。
Jestでテストを実行した際に、なぜpreserveでうまく解釈できなかったのかまでは、
この記事を書いている時点では答えに辿り着けていません、、、

参考にした記事

https://www.designcise.com/web/tutorial/how-to-fix-syntaxerror-unexpected-token-jest-error
jsxオプションを変更するという発想自体は、上記の英語の記事を参照した際に辿り着きました。
jsxオプションの指定の仕方についても、ケースごとに詳しく書かれています。

https://zenn.dev/no4_dev/articles/15ba046e245ba090a3a3-2
テスト用にtsconfig.jsonを上書きする際に目に留まった記事は上記です。
ありがとうございます🙇

Discussion