🙄

【Vitest】備忘のためのアウトプット

に公開

環境構築

Vite環境でvitestを動かせる状態まで持っていくための作業の備忘。

インストール

npm i -D vitest jsdom @types/jsdom @testing-library/dom @testing-library/react @testing-library/jest-dom @testing-library/user-event

セットアップファイル作成

vite.setup.tsはデフォルトのvite環境に存在しないので作成する

vitest.setup.ts
import "@testing-library/jest-dom/vitest";

テストをする際にjest-domを使えるようにするためのimport。

各種設定ファイルの構築

vite.config.ts
+ /// <reference types="vitest/config" />
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import viteTsconfigPaths from "vite-tsconfig-paths";

// https://vite.dev/config/
export default defineConfig({
  plugins: [react(), viteTsconfigPaths()],
+  test: {
+   environment: "jsdom",
+   globals: true,
+   setupFiles: "./vitest.setup.ts",
+ },
});
ts.config.json
{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2022",
    "useDefineForClassFields": true,
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
-   "types": ["vite/client"],
+    "types": ["vite/client", "vitest/globals"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "verbatimModuleSyntax": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "erasableSyntaxOnly": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true,

    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    }
  },
-  "include": ["src"]
+  "include": ["src", "./vitest.setup.ts"]
}

mock関連

vi.mockで一部関数のみをmock化する

vi.mock("react-router", async () => {
  const actual =
    await vi.importActual<typeof import("react-router")>("react-router");
  return {
    ...actual,
    useNavigate: () => vi.fn(),
  };
});
  • vi.importActualは非同期関数なので、await必須。
  • useNavigateは関数を返す関数。

typeof import(...)

モジュール全体の型を取得できる

import * as reactRouter from "react-router";
const a: typeof import("react-router") = reactRouter

react-routerのナビゲーションを含めてmock化

import {createRoutesStub } from "react-router";
const Stub = createRoutesStub([
  { path: '/', Component: App },
  { path: '/cards/register', Component: Register }]);
render(
  <ChakraProvider value={defaultSystem}>
    <Stub initialEntries={['/cards/register']} />
  </ChakraProvider>
);

initialEntriesプロパティにパスを指定することで、初期表示のコンポーネントを指定。useNavigate()の遷移をテストする場合は、その遷移先のパスとコンポーネントもここで記載する

自作クラスのmock化

Discussion