【React】React Testing Library 導入躓きポイント

# テストを書こう！
みなさんはテスト書いてますか？自分はあまり書いてなかったので意識して書くよう心がけています。という訳で React のテストを書いていきます。

[Jest](https://jestjs.io/ja/)によるユニットテストは導入済み＆実行できる前提

まずは書いてある通り`npm install`しますが、`Create React App`で作成したプロジェクトの場合は不要だったりします。
[Testing Library](https://testing-library.com/docs/react-testing-library/intro)
# React Testing Libraryの導入時のエラー集

## `No tests found.`
ユニットテストの場合と異なるディレクトリにテストファイルを置いているため、`jest.config.js`の設定が誤っていた。`roots, testMatch`あたりの設定を見直しましょう。

```js:jest.confing.js
module.exports = {
  roots: [
    "<rootDir>/src"
  ],
  testMatch: [
    "**/*.test.(ts|tsx)"
  ],
}
```

## `SyntaxError: Invalid or unexpected token`
画像やCSSファイルを`import`する箇所で怒られます。
```bash
Test suite failed to run

Jest encountered an unexpected token
...
Details:
/path/to/img.png:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){�PNG
                                                                                      

    SyntaxError: Invalid or unexpected token

      1 | import { FC, useMemo } from "react"
      2 | import { CSSTransition } from "react-transition-group"
    > 3 | import img from "../img/img.png"
        | ^
```

Jestは画像やCSSをそのままJSファイルとして読み込もうとして失敗するそうです。適当にモックすることで解決できました。
[Qiita - 【Jest】画像ファイルやCSSのインポートに失敗する場合の対処法](https://qiita.com/Amsel/items/8a4859d06a8de551abf8)

## `ReferenceError: document is not defined`

```bash
 FAIL  src/components/YourComponent.test.tsx
  TestGroupName
    ✕ TestName (2 ms)

  ● TestGroupName › TestName

    The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string.
    Consider using the "jsdom" test environment.
    
    ReferenceError: document is not defined

       8 | describe("TestGroupName", () => {
       9 |   test("TestName", () => {
    > 10 |     render(<YourComponent />)
         |           ^
```

出力に書いてある通りテスト環境の設定が誤っています。

[JEST - testEnvironment](https://jestjs.io/docs/configuration#testenvironment-string)

デフォルトの`"node"`から`"jsdom"`に変更する必要があります。

### `jest.config.js`に追記

```diff:jest.confing.js
 module.exports = {
+  testEnvironment: "jsdom",
 }
```
### Docブロックの追記
`jest.config.js`に設定するとプロジェクト全体に影響してしまい、ユニットテストも含まれると不都合なので、`"jsdom"`に変更したい対象のテストファイル冒頭に追記：
```js
/**
 * @jest-environment jsdom
 */
```

## `TypeError: Cannot read properties of undefined (reading 'html')`

```bash
 FAIL  src/components/YourComponent.test.tsx
  ● Test suite failed to run

    TypeError: Cannot read properties of undefined (reading 'html')

      at new JSDOMEnvironment (node_modules/jest-environment-jsdom/build/index.js:72:44)
      at async TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:317:13)
      at async runJest (node_modules/@jest/core/build/runJest.js:407:19)
      at async _run10000 (node_modules/@jest/core/build/cli/index.js:338:7)
      at async runCLI (node_modules/@jest/core/build/cli/index.js:190:3)
```
v28以上のバージョンのJestで発生します
[Staskoverflow - TypeError: Cannot read properties of undefined (reading 'html')](https://stackoverflow.com/questions/72169503/typeerror-cannot-read-properties-of-undefined-reading-html)  
[Jest - From v27 to v28](https://jestjs.io/docs/upgrading-to-jest28#jsdom)

指示のある通り依存を追加します
```bash
npm install --save-dev jest-environment-jsdom
```

## `TypeError: expect(...).toBeInTheDocument is not a function`
```bash
 FAIL  src/components/YourComponent.test.tsx
  TestGroupName
    ✕ TestName (58 ms)

  ● TestGroupName › TestName

    TypeError: expect(...).toBeInTheDocument is not a function

      14 |   test("TestName", () => {
      15 |     render(<YourComponent />)
    > 16 |     expect(screen.getByText("text")).toBeInTheDocument()
         |                                   ^
```

関数`toBeInTheDocument`はReact Testing Libraryには含まれていないので、別途依存を追加する必要があります

[Stackoverflow - react-testing-library why is toBeInTheDocument() not a function](https://stackoverflow.com/questions/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function)

```bash
npm install --save-dev @testing-library/jest-dom
```