本文へ移動
cccskills
無料GitHub で公開

web-testing-vitest

Vitest test runner - configuration, assertions, mocking (vi.fn, vi.mock, vi.spyOn), fake timers, snapshot testing, coverage, workspace projects

インストール方法を見る

含まれるファイル(6)

  • SKILL.md9.5 KB
  • examples/anti-patterns.md2.7 KB
  • examples/core.md7.9 KB
  • examples/integration.md4.8 KB
  • metadata.yaml359 B
  • reference.md7.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Vitest Test Runner Patterns

Quick Guide: Vitest runs tests through the same transform pipeline and config the app is built with, so aliases, plugins and TypeScript work without a second toolchain. describe/it/expect for structure, vi.fn() and vi.spyOn() for test doubles, vi.mock() for whole modules, and vi.useFakeTimers() for anything clock-driven. Vitest 4 is current stable (Vite 6+, Node 20+) and changed several mock defaults — vi.restoreAllMocks() no longer resets automocks, and poolOptions is gone.

Detailed Resources:


Which path applies

  • Pure logic, no DOM — the default environment: "node", no setup file; follow examples/core.md.
  • Code that touches document or window — set environment: "jsdom" (or happy-dom) and a setup file; follow examples/integration.md.
  • Several suites with different environments in one repo — one projects entry each, so a single run covers all of them; see reference.md.

<critical_requirements>

Before writing Vitest code

Pass test options as the second argument — test("name", { timeout: 10_000 }, () => {}). The trailing-options form was removed after v2, and mixing an options object with a trailing timeout is rejected outright.

Return every export the file under test imports from a vi.mock() factory. The factory replaces the whole module, so anything it omits is undefined at import time; reach for importOriginal() to keep the rest, and remember the call is hoisted above every import in the file.

Reset mock state between tests — restoreMocks: true in config, or an explicit vi.resetAllMocks() in afterEach. In v4 vi.restoreAllMocks() touches only manual spies, so automocked modules keep their state without it.

Mock at the boundary the code crosses. A module mock binds the test to the import graph and breaks on any refactor that moves a function; intercepting HTTP leaves the import graph free and exercises serialisation.

</critical_requirements>


Auto-detection: Vitest, vitest.config, vi.fn, vi.mock, vi.spyOn, vi.hoisted, vi.mockObject, vi.useFakeTimers, vi.advanceTimersByTime, mockResolvedValue, mockRejectedValue, importOriginal, toMatchInlineSnapshot, expect.schemaMatching, defineConfig test block, projects, coverage provider

Applies to:

  • Running and configuring the test runner — environments, setup files, projects, coverage
  • Test doubles: spies, stubs, module mocks, mocked timers and mocked globals
  • Assertions, async assertions and snapshots
  • Deciding what to cover with a test at all, and at which level

Handled elsewhere:

  • Rendering components and querying the result — the runner supplies the environment; what mounts inside it is settled by whatever owns component testing
  • Defining HTTP handlers and running an interception server — this skill covers where in the test lifecycle they start and reset, not how they are written
  • Driving a real browser through a user journey — a different tool and a different feedback loop

<philosophy>

Vitest reads the project's own Vite config, so a test resolves imports, aliases and plugins exactly as the application does. That is the whole reason it needs so little configuration of its own — and the reason a failure is usually a config question ("which environment is this suite running in?") rather than a runner question.

</philosophy>

<decision_framework>

Which kind of test double:

  • The collaborator is a function you already own a reference to → vi.spyOn(obj, "method"), which keeps the original for restore.
  • The collaborator is passed in → vi.fn() with mockReturnValue / mockResolvedValue; no module machinery needed.
  • The collaborator is reached over HTTP → intercept the request rather than the module, so the test covers serialisation and survives refactors.
  • The collaborator is a module with no seam at all (filesystem, clock, crypto) → vi.mock() for the module, vi.useFakeTimers() for the clock, vi.stubGlobal() for a global.

</decision_framework>


<patterns>

Core patterns

Pattern 1: Test structure and options

Options are the second argument. test.each covers table-driven cases without a loop, and it.concurrent runs siblings in parallel inside one file.

describe("formatCurrency", () => {
  it("formats the default currency", () => {
    expect(formatCurrency(1234.56)).toBe("$1,234.56");
  });

  it("retries a known-flaky path", { retry: 2, timeout: 10_000 }, async () => {
    await expect(fetchRate()).resolves.toBeGreaterThan(0);
  });

  it.each([
    [0, "$0.00"],
    [-1, "-$1.00"],
  ])("formats %d as %s", (input, expected) => {
    expect(formatCurrency(input)).toBe(expected);
  });
});

Full code: examples/core.md

Pattern 2: Spies and stubs

vi.fn() creates a standalone double; vi.spyOn() wraps an existing method and can be restored. Both record calls on .mock.

const onSave = vi.fn().mockResolvedValue({ id: "1" });
await submit({ onSave });
expect(onSave).toHaveBeenCalledWith({ title: "Draft" });

const spy = vi.spyOn(clock, "now").mockReturnValue(0);
stampEvent("saved");
expect(spy).toHaveBeenCalledTimes(1);
spy.mockRestore();

Full code: examples/core.md

Pattern 3: Module mocking

vi.mock() is hoisted above the imports, so its factory sees nothing from the file body unless the value comes from vi.hoisted(). importOriginal keeps the exports the test does not replace.

const { readConfig } = vi.hoisted(() => ({ readConfig: vi.fn() }));

vi.mock("./config", async (importOriginal) => ({
  ...(await importOriginal<typeof import("./config")>()),
  readConfig,
}));

readConfig.mockReturnValue({ locale: "en-US" });

Full code: examples/core.md

Pattern 4: Fake timers

Install fake timers, advance them explicitly, and return to real timers afterwards so later suites are unaffected.

beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());

it("fires the debounced callback once", () => {
  const onIdle = vi.fn();
  watchIdle(onIdle, 300);
  vi.advanceTimersByTime(300);
  expect(onIdle).toHaveBeenCalledOnce();
});

Full code: examples/core.md

Pattern 5: Assertions and snapshots

toStrictEqual compares shape as well as value; resolves / rejects keep async assertions in one expression; inline snapshots keep the expected value beside the test.

await expect(loadUser("missing")).rejects.toThrowError(/not found/);
expect(toSummary(order)).toStrictEqual({ total: 118, items: 2 });
expect(parseArgs(["--json"]).json).toMatchInlineSnapshot(`true`);

Full code: examples/core.md

Pattern 6: Configuration and environments

The test block lives in the project's own config file. environment decides what globals a suite gets, setupFiles runs before each test file, and projects gives one run several of each.

import { defineConfig } from "vitest/config"; // not "vite" — that one has no `test` key

export default defineConfig({
  test: {
    environment: "node",
    setupFiles: ["./tests/setup.ts"],
    restoreMocks: true,
    coverage: { provider: "v8", include: ["src/**/*.ts"] },
  },
});

Full code: examples/integration.md — lookup table in reference.md

</patterns>

<red_flags>

Red flags

Breaks at runtime:

  • Options passed after the test body — test("x", fn, { retry: 2 }) — removed after v2; put them in the second argument.
  • A vi.mock() factory referencing a const from the file body — the call is hoisted, so the binding is in its temporal dead zone; take the value from vi.hoisted().
  • A factory that returns only the export under test — every other export becomes undefined; spread await importOriginal() first.
  • A default export replaced without the default key — the factory's return shape is the module's shape, so default: vi.fn() is required.
  • poolOptions in a v4 config — removed; maxWorkers and isolate are top-level.
  • coverage.all in a v4 config — removed; coverage.include is now required for anything to be reported.

Surprising behaviour:

  • vi.restoreAllMocks() in v4 restores manual spies only; automocked modules need vi.resetAllMocks().
  • vi.fn().mock.invocationCallOrder starts at 1 in v4, where it started at 0 before.
  • vi.fn().getMockName() answers "vi.fn()" rather than "spy", which changes snapshots that captured it.
  • Automocked getters return undefined instead of calling the original.
  • Fake timers left installed leak into later files in the same worker — pair every useFakeTimers() with useRealTimers().
  • An interception server's handlers are process-global; reset them after each test or one test's override answers the next one's request.

</red_flags>

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints

日本語の概要は準備中です。原文の説明を表示しています。

agents-inc/skills242026年9月8日 更新

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment

日本語の概要は準備中です。原文の説明を表示しています。

agents-inc/skills242026年9月8日 更新

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns

日本語の概要は準備中です。原文の説明を表示しています。

agents-inc/skills242026年9月8日 更新

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint

日本語の概要は準備中です。原文の説明を表示しています。

agents-inc/skills242026年9月8日 更新

Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training

日本語の概要は準備中です。原文の説明を表示しています。

agents-inc/skills242026年9月8日 更新

Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints

日本語の概要は準備中です。原文の説明を表示しています。

agents-inc/skills242026年9月8日 更新

agents-inc のスキルをすべて見る

このスキルの問題を報告する