vitestを導入してみた

# 前回までのおさらい

https://qiita.com/Qiitakumin/items/be97def5573d0b313b98

# vitest

>Vitest は、Vite を利用した次世代のテスト フレームワーク
```shell
npm install -D vitest
```
https://vitest.dev/guide/


## vitestの設定を行う
ここから先は、この記事を下記URLを参考に進めました

https://zenn.dev/longbridge/articles/9d9ec773cb3814

## vitest の設定
vitest の 設定は vite.config.ts で行います。
設定を共有するにはまず、冒頭に/// <reference types="vitest" />を追加してファイルに型情報を与えます。
これによってtestをキーとしたVitestの設定を記述することができるようになります。

```diff_tsx:vite.config.ts
+ /// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
．．．
```

## 動作確認として関数テストを実行する
動作確認として簡単な関数テストを実行してみます。
src フォルダ内に add.ts と add.test.ts を作成します。
``` add.ts
export const add = (a: number, b: number): number => a + b
```

```add.test.ts
import { describe, expect, it } from "vitest"
import { add } from "./add"

describe("add", () => {
  it("1 + 2 = 3", () => {
    const result = add(1, 2)

    expect(result).toBe(3)
  })
})
```

以下のコマンドでテストを実行します。
```shell
npx vitest
```
テスト成功です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329005/48c61481-30e9-70b4-7bb5-96a1265f2ef7.png)

よくみると、{ PASS  Waiting for file changes...}　監視しているみたい・・・
> vitest開発環境およびCI 環境 (存在する場合) ではwatch mode デフォルトでスマートに開始されます。
または runを使用して、目的のモードを明示的に指定できます。

watch モードなしで実行するには下記のコマンドでテストを実行します。

```shell
npx vitest run
```

## npm run testでテスト実行できるようにする
npm run testでテスト実行できるように package.json に追記します。
watch モードなしで実行する 'testrun' も追記しておきました。

```diff_json:package.json
"scripts": {
   "dev": "vite",
   ・・・
+    "test": "vitest",
+    "testrun": "vitest run"
 }
```

## vitest API をグローバルAPI として使用できるようにする
デフォルトでは `import { describe, expect, it } from "vitest"`と
明示的に import しないと vitest の APIが使えません。

jest のように import しなくても使用できるようにするには、
vite.config.ts と tsconfig.json を以下のように変更します。

```diff_tsx:vite.config.ts
// vite.config.ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
 test: {
+    globals: true,
 },
})
```
```diff_json:tsconfig.json
{
  "compilerOptions": {
+    "types": ["vitest/globals"]
  }
}
```
以上の設定で vitest の API をグローバルAPI が完了！！
add.test.ts ファイルの import を削除してもコンパイルエラーにならず、npm run testでテスト実行できるようになります。

```diff_tsx:add.test.ts
- // import { describe, expect, it } from "vitest"
import { add } from "./add"

describe("add", () => {
  it("1 + 2 = 3", () => {
    const result = add(1, 2)

    expect(result).toBe(3)
  })
})
```

:::note warn
片方のコードをコメンコメンアウトで動作確認するとうまくいかなかった
:::

## React コンポーネントのテスト
つづいて React コンポーネントのテストを実行してみます。
コンポーネントのテストを行うには、いくつか追加のライブラリのインストールが必要です.

### コンポーネントとそのテストコード

```MyComponent.tsx
import React from 'react'

const title = 'Hello Test'

export function MyComponent() {
  return <div>{title}</div>
}
```

```MyComponent.test.tsx
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { MyComponent } from './MyComponent'

test('「Hello Test」が描画されている', () => {
  render(<MyComponent />)
  screen.debug()
  //「MyComponent」をレンダリングして、その出力内容から「Hello Test」があるかをテスト
  expect(screen.getByText('Hello Test')).toBeInTheDocument()
})
```

### 上記のテストを実行するために、以下のライブラリをインストールする必要
#### jsdom
- jsdom とは DOM を JavaScript で実装したもの 
- Jest では jsdom が内包されていますが、vitest では別途インストールする必要
- jsdomはテストやスクレイピングを目的としている

```shell
npm i -D jsdom
```

```diff_tsx:vite.config.ts
  test: {
    globals: true,
+    environment: 'jsdom',
  },
```


#### @testing-library/react
- Reactコンポーネントをテストするためのライブラリ
- テストコードの render メソッドや screen メソッドなどを提供してくれる

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

```shell
npm i -D @testing-library/react
```


#### @testing-library/jest-dom
- DOM 要素のマッチャーを拡張するユーティリティライブラリ
- toBeInTheDocument は @testing-library/jest-dom ライブラリのメソッドなので追加する必要がある
- v6.0.0以降であれば @types/testing-library__jest-dom をインストールする必要はない
- テストコードの toBeInTheDocument メソッドなどを提供してくれる

https://testing-library.com/docs/ecosystem-jest-dom/

```shell
npm i -D @testing-library/jest-dom
```

## 動作確認
`npm run tes` でテスト実行し、コンポーネントのテストが成功することを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329005/82120ff5-79e9-49cf-85f8-ab2b9890da7b.png)

## 毎回`import '...'`を書かなくてもいいようにする

現状のままだと、テストファイルに毎回`import '@testing-library/jest-dom'`を書く必要があります。
この import を書かなくてもいいように設定します。

```diff_tsx:MyComponent.test.tsx
- import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { MyComponent } from './MyComponent'
...
```

設定ファイルを ルート直下に作成します。
ファイル名は何でもいいですが vitest.setup.ts という名前にしました。
vitest.setup.ts に下記コードを書きます。
EsLint が怒ってきますが後で設定するので今は無視しておきます。

```vitest.setup.ts
import '@testing-library/jest-dom'
```

vite.config.ts の setupFiles プロパティに先ほど作成した設定ファイルを指定します。
setupFiles プロパティは、各テストファイルが実行される直前に実行したいスクリプトファイルを指定するプロパティです。

```diff_tsx:vite.config.ts
・・・
export default defineConfig({
  ・・・
  test: {
    globals: true,
    environment: 'happy-dom',
+    setupFiles: ['./vitest.setup.ts']
  }
})
```

:::note warn
tsconfig.jsonに下記コードを追加しないと動かなかった
:::



```diff_json:tsconfig.json
{
  "compilerOptions": {
    ...
    /* vitest */
    "types": ["vitest/globals"]
  },
+  "include": ["src","./vitest.setup.ts"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
```


以上でテストファイルに`import '@testing-library/jest-dom'`を書かなくてもよくなります。


## 参考
https://zenn.dev/longbridge/articles/9d9ec773cb3814

https://qiita.com/KokiSakano/items/f23e979004f72d70165e

# 次回予告

https://qiita.com/Qiitakumin/items/4fdc24861c8795d9abcd