テストフレームワークをJestからVitest に移管した手順と得た知見

# はじめに

以前こちらの記事で書いた github actions のパイプラインの高速化の検討について、高速テストフレームワークとして期待されている Vitest についても検証したと述べたのですが、
今回はその Vitest に関する移行検証記事です。

- [github actions の job を高速にするために取った対策](https://qiita.com/itouoti/items/37e0420b232a1c694288)
  - ※上の記事では vitest の方が遅かった記載をしていますが、今回テストを再実行してみたところ vitest の方が速度が速かったため、裏で何かしら別のプロセスが動いていたかもしれないです。

# Vitest とは

- [vitest.dev](https://vitest.dev/)
- Vite 環境のために開発された高速テストフレームワーク
- Jest と互換性がある
- まだメジャーバージョンではない(記事執筆時`v0.22.1`)

# 結論

- Vitest への移行結果
  Jest に比べて Vitest の方が 10%少しテスト実行速度が上昇していることが確認できました。

- 移行量

  | 項目           | 実績         |
  | -------------- | ------------ |
  | 修正ファイル数 | 388 ファイル |
  | 修正テスト数   | 2067 ケース  |

- テスト実行時間比較

  | Vitest  | Jest    |
  | ------- | ------- |
  | 280.07s | 317.90s |

- Vitest 実行結果
  ![vitest](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/2c39d479-3826-81a5-3cf8-ea6c73d68ceb.png)


- Jest 実行結果
  ![jest](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641313/255ec98f-6f68-777b-2325-2c84fa891d3b.png)

# 移行前環境

- React v17(CRA ベースで初期構築)
- Typescript
- npm ベース
- Sonarqube による静的解析を利用するため、`jest-sonar-reporter`を利用
- `styled-component`導入済
- `testing-library`を使ったテスト
- `Enzymeのshallow`を使った snapshot テスト
- `Enzymeのmount`を使った snapshot テスト

# 移行時の Vitest バージョン

```json
{
  "happy-dom": "^5.0.0",
  "vite": "^2.9.9",
  "vite-tsconfig-paths": "^3.5.0",
  "vitest": "^0.14.2",
  "vitest-sonar-reporter": "^0.2.1",
  "c8": "^7.11.3"
}
```

# 方針

- 既存で Success となるテストは移行後も全て Success となること
- 基本的には Vitest 公式の MigrationGuide に従って移行していく
  - [Migration Guide](https://vitest.dev/guide/migration.html)

# 手順

## ライブラリインストール

```sh
npm i -D vitest #vitest の core
npm i -D @vitejs/plugin-react #vitest の react 対応
npm i -D happy-dom #vitest に直接依存はないが、js-dom 互換で SSR にも対応、パフォーマンスも倍以上速い らしい happy-dom を導入してみる
npm i -D vite #setup.ts の defineConfig のためにインストール
npm i @testing-library/jest-dom/extend-expect -D
npm i vite-tsconfig-paths -D #read from tsconfig paths and baseUrl

```

## vite.config.ts の作成

- `vite.config.ts`

  ```vite.config.ts
  import { defineConfig } from "vitest/config";
  import react from "@vitejs/plugin-react";
  import tsconfigPaths from "vite-tsconfig-paths";
  export default defineConfig({
    plugins: [react(), tsconfigPaths()],
    test: {
      globals: true,
      environment: "happy-dom", // jsdomの代わりにhappy-domを設定した
      setupFiles: ["./src/setup.ts", "./src/setupTests.ts"], //Jestで使っていたテスト設定をセットアップ
    },
  });
  ```

## package.json に Vitest 起動用の script を入れる

- `vitest run`で Vitest を実行できます
- Vitest の場合は並列実行数(worker)はデフォルトだと、PC が許す限りのメモリ分並列実行させます

  - worker の数を制御したい場合は`VITEST_MIN_THREADS=6 VITEST_MAX_THREADS=6`で設定することができます
  - 今回は元々自分が Jest で設定していた worker の数と同じにしました（実行比較のため）

- before(cra ベースの Jest)

  ```package.json
  {
    "scripts": {
      "test": "react-scripts test --env=jsdom --maxWorkers=6 --watchAll=false"
    }
  }
  ```

- after

  ```package.json
  {
    "scripts": {
      "test": "VITEST_MIN_THREADS=6 VITEST_MAX_THREADS=6 vitest run"
    }
  }
  ```

これで基本的には Jest->Vitest への移行は完了です。
ピュアな Jest であれば Vitest でそのまま動くと思います。

# テスト実行方法について

## 単体での実行

- `npm run test hoge.test.ts`

- ※Jest のようにパス付きファイル指定はできないもよう
  以下実行できませんでした
  `npm run test ./src/pages/hoge/hoge.test.ts`

## ディレクトリ単位での実行

- `npm run test --dir ./src/pages/hoge/`

## ブランチ間の差分の実行

- `npm run test --changed origin/master`

話がちょっと逸れますがこの機能めちゃめちゃ重要だと思います。
CICD パイプラインのテスト実行 step で威力を発揮します。
例えば PullRequest での毎回のテスト実行の際、このオプションをつけるだけで修正差分に関連するテストだけを自動で選択して実行してくれるので、
テスト実行時間やパイプラインの時間消費の効率が上がります。

# vscode の設定

## vscode のデバッガ設定

- launch.json
  - node_modules の場所を指定するパスに注意
    ```launch.json
    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "vitest:Debug Current Test File",
          "type": "pwa-node",
          "request": "launch",
          "autoAttachChildProcesses": true,
          "skipFiles": ["<node_internals>/**", "**/node_modules/**"],
          "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
          "args": ["run", "${relativeFile}"],
          "smartStep": true,
          "console": "integratedTerminal"
        }
      ]
    }
    ```

## vscode の run 設定変更(settings.json)

- Jest
  - jest-Runner extension をインストールする
- Vitest
  - vitest-Runner extension をインストールする

# coverage 設定の移行

cra ベースの場合だと coverage の設定は package.json で記載していると思いますが、それを`vitest.config.ts`へ移行します

- Jest

  ```package.json
  {
    "jest": {
      "collectCoverageFrom": [
        "src/pages/**/*.{js,jsx,ts,tsx}",
        "src/common/**/*.{js,jsx,ts,tsx}",
        "src/index.tsx"
      ]
    }
  }
  ```

  - `coverage`フォルダの中にカバレッジファイルができる(`lcov`)

- Vitest
    
  - <del>Vitest での coverage 生成は c8 というライブラリ を使う
    `npm i --save-dev c8`</del>
  
  
  - <font color="#ff0000">[追記：20230130 vitest:0.28.3] Vitest での coverage 生成は @vitest/coverage-c8 というライブラリ を使う</font>
    `npm i --save-dev @vitest/coverage-c8`
  
    ```vite.config.ts
    export default defineConfig({
      plugins: [react(), tsconfigPaths()],
      test: {
        coverage: {
          reporter: ["text", "lcov"],
          reportsDirectory: "coverage",
          include: [
            "src/pages/**/*.{js,jsx,ts,tsx}",
            "src/common/**/*.{js,jsx,ts,tsx}",
            "src/index.tsx",
          ],
        },
      },
    });
    ```
    - `text`が標準出力、`lcov`が output ファイルを出力する

# sonar-reporter の設定

- Jest

  - 起動時の引数に`--coverage --testResultsProcessor jest-sonar-reporter`を入れる

    ```package.json
    {
      "scripts": {
        "test:ci": "react-scripts test --env=jsdom --maxWorkers=6 --watchAll=false --coverage --testResultsProcessor jest-sonar-reporter"
      }
    }
    ```

  - `jest-sonar-reporter`を使う
    ```package.json
    {
      "jestSonar": {
        "reportPath": "report",
        "reportFile": "test-report.xml",
        "reportedFilePath": "relative",
        "relativeRootDir": "<rootDir>/../",
        "indent": 4
      }
    }
    ```

- Vitest
  `vitest-sonar-reporter`を使う

  - [vitest-sonar-reporter](https://www.npmjs.com/package/vitest-sonar-reporter)
  - `npm install --save-dev vitest-sonar-reporter`
  - vite.config.ts
    ```vite.config.ts
    export default defineConfig({
      plugins: [react(), tsconfigPaths()],
      test: {
        reporters: ["default", "vitest-sonar-reporter"],
        outputFile: "report/test-report.xml",
      },
    });
    ```
    - `reporters: ["default"]`が標準出力を表す

# Jest との差分

## Mock の宣言

`jest.mock`を`vi.mock`に置き換える必要があります。

- Jest

  ```ts
  jest.mock(...)
  ```

- Vitest

  ```ts
  import { vi } from 'vitest';
  vi.mock(...)
  ```

## instance の型の明示的な設定

Typescript における mock の型の明示的な設定に違いがあります

- jest
  - `(MediaClient.getHoge as jest.Mock).mock.calls[0][0]`
- vitest
  - <del>`(MediaClient.getHoge as SpyInstanceFn).mock.calls[0][0]`</del>
  - <font color="#ff0000">[追記：20230130 vitest:0.28.3] `(MediaClient.getHoge as unknown as SpyInstance)`</font>

## automocking の未サポート

- jest における automocking `<root>/__mocks__`は現状サポートしていません

  - [We don't support automocking. You need to manually call vi.mock("path"). Or you can call it once in setupFiles.](https://github.com/vitest-dev/vitest/issues/552)
  - `setup.ts` で明示的に mock をすることによって、各テストの実行前に mock がされるようになるのでそれによって回避できます。

- `moment`を automocking していた例

  - before

    - `<root>/__mocks__/moment.ts`で mock していた

  - after

    - setup.ts

      ```setup.ts
      import "@testing-library/jest-dom/extend-expect";
      import { vi } from "vitest";
      import * as moment from "./__mocks__/moment";

      vi.doMock("moment", () => moment);
      ```

## default を spyon できない

- <font color="#ff0000">[追記：20230130 vitest:0.28.3] 新バージョンで解消済み</font>

- Jest での default spyon

  ```ts
  import * as getHogeApi from "../apicall/getHoge";

  const mockGetHogeApi = jest.spyOn(getHogeApi, "default");
  ```

  これを Vitest でそのまま実行すると以下のエラーになります

  ```
      TypeError: Cannot redefine property: default
     ❯ src/pages/hoge.test.tsx:18:39
         18| const mockGetHogeApi = vi.spyOn(getHogeApi, 'd…
           |                          ^
  ```

- Vitest での置き換え

  - `vi.mock`と`vi.mocked`を利用して置き換えます

    ```ts
    import { vi } from "vitest";
    vi.mock("../apicall/getHoge", async () => {
      const actual: any = await vi.importActual("../apicall/getHoge");
      const mocked = {};
      for (const key of Object.keys(actual)) {
        if (typeof actual[key] === "function") {
          mocked[key] = vi.fn(actual[key]);
        } else {
          mocked[key] = actual[key];
        }
      }
      return mocked;
    });

    import * as getReservePresetListApi from "../apicall/getHoge";

    const mockGetReservePresetListApi = vi.mocked(
      getReservePresetListApi
    ).default;
    ```

- 参考
  - [Cannot spyOn default export of module](https://github.com/vitest-dev/vitest/issues/855)
    - **最新だと`tinyspy`を使うことで回避できる模様(未検証)**

## mock のやり方

- `default`が必要なケースがあります

- Jest

  ```ts
  jest.mock("moment", () => () => ({
    format: () => "2019–09–30T10:11:59+09:00",
  }));
  ```

- Vitest

  ```ts
  vi.mock("moment", () => {
    return {
      default: () => ({
        format: () => "2019–09–30T10:11:59+09:00",
      }),
    };
  });
  ```

## Done callback が非推奨

- test 自体は通りますが、Vitest だとエラー判定されます。

  ```ts
  it(`test`, (done) => {
    // GIVEN
    // WHEN
    when();

    setTimeout(() => {
      try {
        // THEN
        expect();
        done(); // TypeError: An argument for 'value' was not provided.
      } catch (e) {
        done(e);
      }
    }, 300);
  });
  ```

  ```
  Serialized Error: {
    "errors": [
      [Error: done() callback is deprecated, use promise instead],
      [Error: done() callback is deprecated, use promise instead],
    ],
  }
  ```

- 回避策

  - [Done Callback](https://vitest.dev/guide/migration.html#migrating-from-jest)

    - 上のドキュメントの実装でも通せますが、Typescript では done の引数エラーが発生します

      ```ts
      it(`test`, () =>
        new Promise((done) => {
          // GIVEN
          // WHEN
          when();

          setTimeout(() => {
            try {
              // THEN
              expect();
              done(); // TypeError: An argument for 'value' was not provided.
            } catch (e) {
              done(e);
            }
          }, 300);
        }));
      ```

    - `new Promise`に型をつければエラーは消えますが、今度は引数ありのほうが逆にエラーとなります

      ```ts
      it(`test`, () =>
        new Promise<void>((done) => {
          // GIVEN
          // WHEN
          when();

          setTimeout(() => {
            try {
              // THEN
              expect();
              done(); // pass
            } catch (e) {
              done(e); // TypeError: An argument for 'value' was not provided.
            }
          }, 300);
        }));
      ```

    - 結論としては`done`とは別に`reject`を使用します

      ```ts
      it(`test`, () =>
        new Promise<void>((done, reject) => {
          // GIVEN
          // WHEN
          when();

          setTimeout(() => {
            try {
              // THEN
              expect();

              done();
            } catch (e) {
              reject(e);
            }
          }, 300);
        }));
      ```

## リテラル表記の`it.each`のエラー

- Jest での`it.each`テストにてエラーが発生

```ts
it.each`
  input        | expFromTime | expToTime
  ${"morning"} | ${"04:00"}  | ${"10:00"}
  ${"noon"}    | ${"10:00"}  | ${"17:00"}
  ${"night"}   | ${"17:00"}  | ${"03:59"}
  ${"all"}     | ${null}     | ${null}
  ${"hoge"}    | ${null}     | ${null}
`(
  `timePeriodテスト
    timePeriod:$inputのケース`,
  async ({ input, expFromTime, expToTime }) => {
    // GIVEN
    // WHEN
    // THEN
);
```

- [vitest-each](https://vitest.dev/api/#test-each)に沿って書き換える

  - 公式通り修正

    ```ts
    it.each([
      ['morning', '04:00', '10:00'],
      ['noon', '10:00', '17:00'],
      ['night', '17:00', '03:59'],
      ['all', null, null],
      ['hoge', null, null],
    ])
    (
      `timePeriodテスト
      timePeriod:$sのケース`,
      async ( input, expFromTime, expToTime ) => {
      // GIVEN
      // WHEN
      // THEN
    );
    ```

    - printf 形式のパラメータ指定

    ```
      %s: string
      %d: number
      %i: integer
      %f: floating point value
      %j: json
      %o: object
      %#: index of the test case
      %%: single percent sign ('%')
    ```

## require による import はサポート外

- `require`による import はサポート外としている
  - [Cannot require a module when using typescript #846](https://github.com/vitest-dev/vitest/issues/846)

## 試験的な導入による warning

メジャーバージョンではないため出ている

```
(node:46501) ExperimentalWarning: buffer.Blob is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46501) ExperimentalWarning: buffer.Blob is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
```

- 試験的な導入なので warning が出る。無視で OK です

# エラーの対処一覧

## 外部ライブラリの default モックでエラー

- 外部ライブラリである`superagent`をモックしていたのですがエラーになりました

  ```ts
  vi.mock("superagent", () => ({
    put: vi.fn().mockReturnValue({
      set: vi.fn().mockReturnValue({
        send: vi.fn().mockReturnValue({
          end: vi.fn().mockImplementation((cb) => {
            cb("", {});
          }),
        }),
      }),
    }),
  }));
  ```

  ```
      Error: Test timed out in 5000ms.
      If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

      Test Files  1 failed | 1 passed (2)
           Tests  1 failed | 2 passed (3)
            Time  9.58s (in thread 5.02s, 190.59%)

      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Errors ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

      Vitest caught 1 unhandled error during the test run. This might cause false positive tests.
      Please, resolve all the errors to make sure your tests are not affected.

      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
      TypeError: __vite_ssr_import_0__.default.put(...).set is not a function
       ❯ src/apicall/hoge.ts:56:9
           54|     if (isOK(result)) {
           55|       request.put(result.data.url)
           56|         .set('Content-Type', contentType)
             |         ^
           57|         .send(file)
           58|         .end((error, uploadResult) => {

      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
      error Command failed with exit code 1.
  ```

- 以下のように書き換える必要がある(default の下に設定する)

  ```ts
  vi.mock("superagent", () => {
    return {
      default: {
        put: vi.fn().mockReturnValue({
          set: vi.fn().mockReturnValue({
            send: vi.fn().mockReturnValue({
              end: vi.fn().mockImplementation((cb) => {
                cb("", {});
              }),
            }),
          }),
        }),
      },
    };
  });
  ```

- [vi.mock](https://vitest.dev/api/#vi-mock)

## vite.config.ts にて`environment: happy-dom`を指定すると以下のエラーが発生する

- styled-componentsとの併用で発生
- happy-dom 側の問題みたいでした 5/24 時点

  - [Missing "options" property on <select> elements ](https://github.com/capricorn86/happy-dom/issues/428)

  - **`happy-dom:5.1.0`で解消された模様（未検証）**

  ```
  The above error occurred in the <select> component:

      at select
      at div
      at div
      at I (/.../node_modules/styled-components/dist/styled-components.cjs.js:1:19220)
      at div
      at I (/.../node_modules/styled-components/dist/styled-components.cjs.js:1:19220)
      at div
      at div
      at div
      at ModalPortal (/.../node_modules/react-modal/lib/components/ModalPortal.js:70:5)
      at Modal (/.../node_modules/react-modal/lib/components/Modal.js:73:5)
      at PresetDialogLayout (/.../src/pages/Hoge/index.tsx:17:3)
      at LoadPresetDialog (/.../src/pages/Puga.tsx:19:3)
      at WrapperComponent (/.../node_modules/@wojtekmaj/enzyme-adapter-utils/build/createMountWrapper.js:112:7)

  Consider adding an error boundary to your tree to customize error handling behavior.
  Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.


  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Errors ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

  Vitest caught 1 unhandled error during the test run. This might cause false positive tests.
  Please, resolve all the errors to make sure your tests are not affected.

  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
  TypeError: Cannot read properties of undefined (reading 'length')
   ❯ updateOptions node_modules/react-dom/cjs/react-dom.development.js:1880:37
   ❯ postMountWrapper$2 node_modules/react-dom/cjs/react-dom.development.js:1950:5
   ❯ setInitialProperties node_modules/react-dom/cjs/react-dom.development.js:9157:7
   ❯ finalizeInitialChildren node_modules/react-dom/cjs/react-dom.development.js:10201:3
   ❯ completeWork node_modules/react-dom/cjs/react-dom.development.js:19470:17
   ❯ completeUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:22812:16
   ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:22787:5
   ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:22707:5
   ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:22670:7
   ❯ performSyncWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:22293:18

  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
  error Command failed with exit code 1.
  ```

- `vitest.config.ts`で`environment:jsdom`にすると解消されました

## mapbox-gl のモックでエラー

- jest で特に問題は出ていませんでしたが、vitest でエラーが発生しました

```
TypeError: The "obj" argument must be an instance of Blob. Received an instance of Blob
 ❯ define node_modules/mapbox-gl/dist/mapbox-gl.js:25:41
 ❯ node_modules/mapbox-gl/dist/mapbox-gl.js:35:1
 ❯ node_modules/mapbox-gl/dist/mapbox-gl.js:3:81
 ❯ Object.<anonymous> node_modules/mapbox-gl/dist/mapbox-gl.js:6:2

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: {
  "code": "ERR_INVALID_ARG_TYPE",
}
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

```

- [window.URL.createObjectURL Blob ERR_INVALID_ARG_TYPE](https://github.com/vitest-dev/vitest/issues/1377)

- globalThis に Blob を追加してあげると回避できます

  - `setup.ts`

    ```ts
    import { Blob } from "buffer";

    (globalThis.Blob as any) = Blob;
    ```
- <font color="#ff0000">[追記：20230130 vitest:0.28.3] Blob is not a constructor</font>
    - 上記の設定をしてテスト実行すると`TypeError: Blob is not a constructor`というエラーが発生した
    - 解決
        - setup.tsのBlobの設定を戻し、createObjectURLのモックを設定する
          ```typescript
            // import { Blob } from 'buffer'
            // (globalThis.Blob as any) = Blob;
            function noOp () { }

            if (typeof window.URL.createObjectURL === 'undefined') {
              Object.defineProperty(window.URL, 'createObjectURL', { value: noOp})
            }

          ```

## global の`__mocks__`を使うために setup.ts で mock しようとしたらエラー

- ある一定以上の数をsetup.tsで mock しようとするとエラーになりました

  ```
  ReferenceError: Cannot access '__vite_ssr_import_5__' before initialization
   ❯ src/setup.ts:3:48
        2| import { vi } from 'vitest';
        3| import * as moment from './__mocks__/moment';
        4| import * as momentTimezone from './__mocks__/moment-timezone.js';
         |  ^
        5| import * as superagent from './__mocks__/superagent';
        6| import * as leaflet from './__mocks__/leaflet.js';
   ❯ async src/__mocks__/leaflet.js:5:31
   ❯ async src/setup.ts:16:31
  ```

- [ReferenceError: Cannot access '**vite_ssr_import_0**' before initialization when using mocks](https://github.com/vitest-dev/vitest/issues/1084)

  - `mock`ではなく`doMock`で回避できます

    - 修正前

      ```setup.ts
      import "@testing-library/jest-dom/extend-expect";
      import { vi } from "vitest";
      import * as moment from "./__mocks__/moment";
      import * as momentTimezone from "./__mocks__/moment-timezone";
      import * as superagent from "./__mocks__/superagent";

      vi.mock("moment", () => moment);
      vi.mock("moment-timezone", () => momentTimezone);
      vi.mock("superagent", () => superagent);
      ```

    - 修正後

      ```setup.ts
      import "@testing-library/jest-dom/extend-expect";
      import { vi } from "vitest";
      import * as moment from "./__mocks__/moment";
      import * as momentTimezone from "./__mocks__/moment-timezone";
      import * as superagent from "./__mocks__/superagent";
      import * as leaflet from "./__mocks__/leaflet";
      import { Blob } from "buffer";

      (globalThis.Blob as any) = Blob;
      vi.doMock("moment", () => moment);
      vi.doMock("moment-timezone", () => momentTimezone);
      vi.doMock("superagent", () => superagent);
      vi.doMock("leaflet", () => leaflet);
      ```

## ArrayMove の mock エラー

- `TypeError: Cannot assign to read only property 'arrayMoveImmutable' of object '[object Module]'`

```ts
import * as ArrayMove from "array-move";
vi.spyOn(ArrayMove, "arrayMoveImmutable");
```

- [Cannot spyOn default export of module #855](https://github.com/vitest-dev/vitest/issues/855)

```ts
import * as ArrayMove from "array-move";
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
vi.mocked(ArrayMove).arrayMoveImmutable;
```

## jquery の import エラー(TypeError: default is not a function)

- `import $ from 'jquery';`

  - `TypeError: default is not a function`というエラーが発生

- Jest

```ts
jest.mock("jquery", () => {
  const m$ = {
    DataTable: jest.fn().mockReturnValue({
      on: jest.fn(),
      destroy: jest.fn(),
    }),
    parents: jest.fn().mockReturnValue([
      {
        classList: {
          add: jest.fn(),
        },
      },
    ]),
  };
  return jest.fn(() => m$);
});
```

- Vitest
  - default をつけてあげる

```ts
vi.mock("jquery", () => {
  const m$ = {
    DataTable: vi.fn().mockReturnValue({
      on: vi.fn(),
      destroy: vi.fn(),
    }),
    parents: vi.fn().mockReturnValue([
      {
        classList: {
          add: vi.fn(),
        },
      },
    ]),
  };
  return { default: vi.fn(() => m$) };
});
```

## snapshotSaved がタイムアウトエラーを起こす

```
Vitest caught 1 unhandled error during the test run. This might cause false positive tests.
Please, resolve all the errors to make sure your tests are not affected.

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Error: Errors occurred while running tests. For more information, see serialized error.
 ❯ Object.runTests file:/.../node_modules/vitest/dist/chunk-vite-node-externalize.0094db73.js:7191:17
 ❯ processTicksAndRejections node:internal/process/task_queues:96:5
 ❯ async file:/.../node_modules/vitest/dist/chunk-vite-node-externalize.0094db73.js:10442:9
 ❯ async Vitest.runFiles file:/.../node_modules/vitest/dist/chunk-vite-node-externalize.0094db73.js:10452:12
 ❯ async Vitest.start file:/.../node_modules/vitest/dist/chunk-vite-node-externalize.0094db73.js:10379:5
 ❯ async startVitest file:/.../node_modules/vitest/dist/chunk-vite-node-externalize.0094db73.js:11102:5
 ❯ async start file:/.../node_modules/vitest/dist/cli.js:665:9
 ❯ async CAC.run file:/.../node_modules/vitest/dist/cli.js:661:3

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: {
  "errors": [
    [Error: [birpc] timeout on calling "snapshotSaved"],
  ],
}
```

- 一つづつモックを外してみたら`global.Math`のモックが悪さをしていたっぽい

  ```ts
  vi.spyOn(global.Math, "random").mockReturnValue(0.123456789);
  ```

  - Math.random を使うのをやめ,`crypto`によるランダム値の取得に変更

- 実装自体を変更しています
※余談ですが、Math.random については SonarQube としても Security の項目でリスクがあると指摘しており、crypto でのランダム値取得が推奨されています。
  - [Don't use Math.random()](https://deepsource.io/blog/dont-use-math-random/)

# 個別に対応した移行ケース一覧

## jest である Mock機能 が vitest にない

```
TypeError: vi.genMockFromModule is not a function
 ❯ src/__mocks__/leaflet.ts:6:24
      4| import L from 'leaflet';
      5|
      6| const LeafletMock = vi.genMockFromModule('leaflet')
       |                        ^
      7|
      8| class ControlMock extends LeafletMock.Control {
 ❯ async src/setup.ts:11:31

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯
```

- `jest.createMockFromModule()/jest..getMockFromModule(moduleName) -> use vi.mock or vi.importMock`に変わっている
- [more mock APIs](https://github.com/vitest-dev/vitest/issues/186)

- Jest
  ```ts
  const LeafletMock = vi.genMockFromModule("leaflet");
  ```
- Vitest
  ```ts
  const LeafletMock = await vi.importMock("leaflet");
  ```

## enzyme snapshot

- Jest での Enzyme Snapshot テストを Vitest でそのまま実行すると `exports['test > snapshot'] = 'ShallowWrapper {}';` となってしまう
- どうやら jest.config.js で設定していた`snapshotSerializers: ['enzyme-to-json/serializer'],`が効かなくなっている模様
- 公式ドキュメント

  - enzyme の snapshot には対応していない
  - jest.snapshot は対応してる
  - [Jest Snapshot support](https://vitest.dev/guide/features.html#snapshot)

- **結論：enzyme-to-json を直接テストの中で使えばいける**

  - [enzyme-to-json の helper 参照](https://npm.io/package/enzyme-to-json)

- 修正前

  ```ts
  it("snapshot", () => {
    // GIVEN
    // WHEN
    target = shallow(<Hoge />);
    // THEN
    expect(target).toMatchSnapshot();
  });
  ```

- 修正後

  ```ts
  import toJson from "enzyme-to-json";
  it("snapshot", () => {
    // GIVEN
    // WHEN
    target = shallow(<Hoge />);
    // THEN
    expect(toJson(target)).toMatchSnapshot();
  });
  ```

- describe でテストケースをグルーピングしており、 その下で snapshot を使用している場合、snap ファイルのケース名も移行前と若干変わっているので合わせる必要があります
  - そうしないと既存のテストケースと同じ snapshot でテストが検証してくれない
    - 修正前
      ```
      exports[`snapshot testcase`] = `
      ```
    - 修正後
      ```
      exports[`snapshot > testcase`] = `
      ```
  - snap の内容も若干変わっていたりするので確認しながら直す必要があります
    - 修正が必要な例 1(型が変わっている)
      ```
        -         onClick={[MockFunction]}
        +         onClick={[Function]}
      ```
    - 修正が必要な例 2(Object がいらない)
      ```
                  style={
        -           Object {
        +           {
                      \"display\": \"none\",
                    }
                  }
      ```

## each + done callback パターン

each による繰り返しテストと、非同期の done テストを同時に適用したい

- Jest

```ts
 it.each`
     args1  | args2 | expected
    ${false} | ${0} | ${''}
 `('jest each done test',
 ({ args1, args2, expected }, done: any) => {
```

- Vitest

```ts
  it.each([
    [false,0,''],
  ])('vitest each done test',
  ( args1, args2, expected ) => new Promise<void>((done, reject) => {
```

## location の mock 設定

- Jest
  `window.history.pushState({}, '', '/pages/hoge');`

  - Jest で`window.location.pathname = '/hoge'`をしてもちゃんと反映されない

- Vitest
  `window.location.pathname = '/pages/hoge'`
    - <font color="#ff0000">[追記：20230130 vitest:0.28.3] </font>
      `vi.stubGlobal('location', { pathname: '/pages/hoge' });`

### sonar-reporter にて`RangeError: Maximum call stack size exceeded`が発生

- `"vitest-sonar-reporter": "^0.2.1"`で解消されました

```
Test Files  388 passed (388)
     Tests  2067 passed (2067)
      Time  506.92s (in thread 234.93s, 215.78%)


⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
RangeError: Maximum call stack size exceeded
 ❯ generateXml node_modules/vitest-sonar-reporter/dist/xml.js:58:12
 ❯ SonarReporter.onFinished node_modules/vitest-sonar-reporter/dist/sonar-reporter.js:37:35
 ❯ node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10640:51
 ❯ Vitest.report node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10638:38
 ❯ node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10475:18
 ❯ processTicksAndRejections node:internal/process/task_queues:96:5
 ❯ Vitest.runFiles node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10479:12
 ❯ Vitest.start node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10406:5
 ❯ startVitest node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:11140:5
```

- 調査の履歴
  - [RangeError: Maximum call stack size exceeded](https://github.com/vitest-dev/vitest/issues/1384)
    - `"vitest": "^0.13.0",`で発生
      - v0.14.2 で解消予定
        - 直ってない。。。
          - どうやら`vitest-sonar-reporter`のバグっぽい
            - issue 書いた
              - [RangeError: Maximum call stack size exceeded #12](https://github.com/AriPerkkio/vitest-sonar-reporter/issues/12)
                - `"vitest-sonar-reporter": "^0.2.1"`で解消
  - [Why does Jest error with Maximum Call Stack Size Exceeded](https://stackoverflow.com/questions/59171650/why-does-jest-error-with-maximum-call-stack-size-exceeded-when-i-import-knockout)
  - [Jest `toMatchSnapshot` causes "Maximum call stack size exceeded"](https://stackoverflow.com/questions/49305669/jest-tomatchsnapshot-causes-maximum-call-stack-size-exceeded)

### <font color="#ff0000">[追記：20230130 vitest:0.28.3] Request is not defined</font>

- 問題
  - Three.jsを使用しているコンポーネントのテストにて`ReferenceError: Request is not defined`エラーが発生

- 解決
  - [vitest-fetch-mock](https://www.npmjs.com/package/vitest-fetch-mock)をインストールする


### <font color="#ff0000">[追記：20230214 vitest:0.28.3] coverageにて[JavaScript heap out of memory]</font>

- 問題
  - c8を使ったcoverageオプションを付与したテストコマンド実行時にmemory heap errorが発生

- エラー
```
<--- Last few GCs --->

[2405:0x577a230]  1009664 ms: Scavenge (reduce) 4047.4 (4118.5) -> 4047.5 (4120.5) MB, 7.0 / 0.0 ms  (average mu = 0.245, current mu = 0.192) allocation failure 
[2405:0x577a230]  1009686 ms: Scavenge (reduce) 4052.4 (4124.0) -> 4052.4 (4124.5) MB, 7.7 / 0.0 ms  (average mu = 0.245, current mu = 0.192) allocation failure 
[2405:0x577a230]  1009728 ms: Scavenge (reduce) 4053.2 (4124.8) -> 4053.2 (4124.8) MB, 9.8 / 0.0 ms  (average mu = 0.245, current mu = 0.192) allocation failure 


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0xb08e80 node::Abort() [node]
 2: 0xa1b70e  [node]
 3: 0xce1890 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xce1c37 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xe992a5  [node]
 6: 0xe99d86  [node]
 7: 0xea82ae  [node]
 8: 0xea8cf0 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 9: 0xeabc6e v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0xe6d01f v8::internal::Factory::AllocateRawWithAllocationSite(v8::internal::Handle<v8::internal::Map>, v8::internal::AllocationType, v8::internal::Handle<v8::internal::AllocationSite>) [node]
11: 0xe7494c v8::internal::Factory::NewJSObjectFromMap(v8::internal::Handle<v8::internal::Map>, v8::internal::AllocationType, v8::internal::Handle<v8::internal::AllocationSite>) [node]
12: 0xe74f75 v8::internal::Factory::NewJSArrayWithUnverifiedElements(v8::internal::Handle<v8::internal::FixedArrayBase>, v8::internal::ElementsKind, int, v8::internal::AllocationType) [node]
13: 0xe751e2 v8::internal::Factory::NewJSArray(v8::internal::ElementsKind, int, int, v8::internal::ArrayStorageAllocationMode, v8::internal::AllocationType) [node]
14: 0xf851b1 v8::internal::JsonParser<unsigned short>::BuildJsonArray(v8::internal::JsonParser<unsigned short>::JsonContinuation const&, v8::base::SmallVector<v8::internal::Handle<v8::internal::Object>, 16ul> const&) [node]
15: 0xf8cdf4 v8::internal::JsonParser<unsigned short>::ParseJsonValue() [node]
16: 0xf8dbef v8::internal::JsonParser<unsigned short>::ParseJson() [node]
17: 0xd637bb v8::internal::Builtin_JsonParse(int, unsigned long*, v8::internal::Isolate*) [node]
18: 0x15d9cf9  [node]
Aborted (core dumped)
Error: Process completed with exit code 134.
```

- 解決
  - coverage providerをc8からistanbulに変更する
  - [公式:coverage-providers](https://vitest.dev/guide/coverage.html#coverage-providers)



# まとめ

今回の検証で Jest から Vitest への色々なテストケースやライブラリ利用のケースでも移行ができることがわかりました。
主に移行時の苦しんで調べて回避してきた内容を書いてきましたが、Vitestへ 移行中のエンジニアの方々に役立てば幸いです。