【Next.js】Jestで自動テストを行う

# はじめに

こんにちは、エンジニアのkeitaMaxです。

前回の続きです。

前回の記事

https://qiita.com/keitaMax/items/bdabc2b6f1435c503547

今回はJestを使ってコマンドをたたいてテストが通っているかの確認ができるようにしたいと思います。

Codecovを使用してコードカバレッジをとるには、Jestを使用してやるのがよさそうだったので、今回はその準備です。

以下のURLを参考に実装をしていきたいと思います。

https://qiita.com/k_kuroiwa/items/cdf9fdafb044a68eebb1



# Jest インストール


まずはJestを以下のコマンドでインストールします。

```
npm install --save-dev jest
```

https://testing-library.com/docs/react-testing-library/intro/
# その他のライブラリインストール

自動テストを作成するうえで、以下の3つのライブラリをインストールします。

### React Testing Library

```
npm install --save-dev @testing-library/react
```
https://testing-library.com/docs/react-testing-library/intro/

### ts-jest
```
npm i ts-jest
```
https://www.npmjs.com/package/ts-jest

### jest-environment-jsdom

```
npm i jest-environment-jsdom
```
https://www.npmjs.com/package/jest-environment-jsdom


# ファイルを修正する

ライブラリのインストールが完了したら、次はコードを追加・修正していきます。

まずは、Jestでテストをするために新しく`index.spec.tsx`を作成します。

これはこれまでに作成している`index.ts`と同じ階層に作成します。

```tsx:index.spec.tsx
import { composeStories } from "@storybook/react";
import "@testing-library/jest-dom";
import { render } from "@testing-library/react";
import * as stories from "./index.stories";
const { Test } = composeStories(stories);

describe("画面のテスト", () => {
  test("画面のテスト", async () => {
    const { container } = render(<Test />);
    await Test.play({ canvasElement: container }); 
  });
})
```

つぎに、'index.spec.tsx'で`index.stories.tsx`を読み込めるように`index.stories.tsx`を以下のように修正しました。


```tsx:index.stories.tsx
import { expect } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import { CountView } from '.';


const meta: Meta<typeof CountView> = {
  title: 'views/CountView',
  component: CountView,
  tags: ['autodocs'],
}
export default meta

type Story = StoryObj<typeof meta>

export const Test: Story = {
  play: async ({ canvasElement }) => {
    const button = await within(canvasElement).findByTestId('button');
    expect(button).toBeInTheDocument();
    expect(within(canvasElement).queryByTestId('countText')?.innerHTML).toBe("0");
    await userEvent.click(button);
    expect(within(canvasElement).queryByTestId('countText')?.innerHTML).toBe("1");
  },
};
```

次に`jest.config.js`ファイルを一番上のフォルダに作成します。中身は以下のようにします。


```js:jest.config.js
module.exports = {
    preset: 'ts-jest',
    testEnvironment: 'jsdom',
    moduleNameMapper: {
        '\\.(css|less|sass|scss)$': 'identity-obj-proxy',
    },
    transform: {
        '^.+\\.(ts|tsx)$': 'ts-jest',
        '^.+\\.(js|jsx)$': ['babel-jest', { presets: ['next/babel'] }],
    },
    globals: {
        'ts-jest': {
            tsconfig: {
                jsx: 'react-jsx',
            },
        },
    },
    testMatch: [
        "**/views/**/*.spec.[jt]s?(x)"
    ]
};
```

最後に、`package.json`の`scripts`の最後の行に以下を追加します。
```json
"test": "jest"
```

これで実行する準備はできました。



# 実装していて困ったこと

Jestを入れたときに、`describe is not defined when installing jest`とESLintでエラーが出てしまいました。

https://dukesoftware00.blogspot.com/2021/06/eslintdescribe-is-not-defined-when.html

上記のURLを参考に`.eslintrc.json`に以下を追記したらエラーが解消しました。

```json:.eslintrc.json
  "env": {
    "jest": true
  },
```


# 実行

さっそく以下のコマンドで実行します。

```
npm run test
```

```
PS C:\develop\next-example-app> npm run test     

> next-example-app@0.1.0 test
> jest

ts-jest[ts-jest-transformer] (WARN) Define `ts-jest` config under `globals` is deprecated. Please do
transform: {
    <transform_regex>: ['ts-jest', { /* ts-jest config goes here in Jest */ }],
},
 PASS  src/views/CountView/index.spec.tsx
  画面のテスト
    √ 画面のテスト (122 ms)                                                                                                                                                                                 
                                                                                                                                                                                                            
Test Suites: 1 passed, 1 total                                                                                                                                                                              
Tests:       1 passed, 1 total                                                                                                                                                                              
Snapshots:   0 total
Time:        3.214 s
Ran all test suites.
PS C:\develop\next-example-app> 
```

無事テストが走り、すべてのテストが問題なくパスすることができました。



# さいごに

次回はGitHubにコミットしたときにコードカバレッジをとる部分の作成を行っていくと思います。

やり方が違ったり、もっといいやり方があるというご指摘がある方はコメントしていただけると幸いです。

最後まで読んでいただきありがとうございました。


# 参考文献

https://qiita.com/k_kuroiwa/items/cdf9fdafb044a68eebb1

https://dukesoftware00.blogspot.com/2021/06/eslintdescribe-is-not-defined-when.html

https://testing-library.com/docs/react-testing-library/intro/

# 次の記事

https://qiita.com/keitaMax/items/bb33ef21ca0ae9c266d0