vitest

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vitest

Vitest

Use this skill to add, fix, or run Vitest tests without turning the task into a Vitest API reference lookup.
Helper Scripts Available:
  • scripts/inspect_vitest.py
    - Detects package manager, Vitest config, scripts, test files, framework hints, and likely run commands
  • scripts/run_vitest.py
    - Runs Vitest through the detected package manager with useful defaults
<skill>
means the path to this local skill folder. Run helper scripts with
--help
when usage is unclear or before first use in a session. Prefer using helper scripts as black-box tools. Read or modify their source only when debugging the skill itself or when behavior is unclear.
使用此技能可以添加、修复或运行Vitest测试,无需将任务变成查阅Vitest API参考文档的过程。
可用辅助脚本
  • scripts/inspect_vitest.py
    - 检测包管理器、Vitest配置、脚本、测试文件、框架提示以及可能的运行命令
  • scripts/run_vitest.py
    - 通过检测到的包管理器运行Vitest,并使用实用的默认配置
<skill>
指的是本地此技能文件夹的路径。当用法不明确或在会话中首次使用前,可使用
--help
运行辅助脚本。优先将辅助脚本作为黑盒工具使用。仅在调试技能本身或行为不明确时,才阅读或修改其源代码。

Decision Tree

决策树

User task -> Is this an existing project?
    - Yes -> Run: python <skill>/scripts/inspect_vitest.py --root <project>
             Use detected framework, config, aliases, and package manager.
    - No / new setup -> Inspect package.json manually if present, then create the
                        smallest Vitest setup that matches the runtime.

Next -> What is under test?
    - Node/library logic -> environment: node
    - React/Vue/Svelte component -> environment: jsdom or happy-dom
    - Nuxt/Vue app code -> prefer existing Nuxt/Vite test utilities and config
    - Edge/Workers code -> match the project's existing worker test setup
    - Browser-specific behavior -> consider Vitest browser mode only if already used

Then -> Write or fix one focused test, run it directly, then broaden only as needed.
用户任务 -> 是否为现有项目?
    - 是 -> 运行:python <skill>/scripts/inspect_vitest.py --root <project>
             使用检测到的框架、配置、别名和包管理器。
    - 否 / 新搭建项目 -> 若存在package.json则手动检查,然后创建与运行时匹配的最小化Vitest配置。

下一步 -> 测试对象是什么?
    - Node/库逻辑 -> 环境:node
    - React/Vue/Svelte组件 -> 环境:jsdom或happy-dom
    - Nuxt/Vue应用代码 -> 优先使用现有Nuxt/Vite测试工具和配置
    - Edge/Workers代码 -> 匹配项目现有的Worker测试配置
    - 浏览器特定行为 -> 仅当已使用Vitest浏览器模式时才考虑使用该模式

然后 -> 编写或修复一个聚焦的测试,直接运行它,仅在需要时再扩展范围。

Core Workflow

核心工作流程

  1. Inspect first: discover existing scripts, config files, setup files, aliases, and test conventions.
  2. Match the project: use its package manager, test naming, setup file, mock style, and import aliases.
  3. Keep tests behavioral: assert public outcomes instead of private implementation details.
  4. Isolate state: reset mocks, timers, DOM, environment variables, and module state when the test mutates them.
  5. Verify narrowly first: run one file or name pattern before running the whole suite.
  1. 先检查:发现现有脚本、配置文件、初始化文件、别名和测试约定。
  2. 匹配项目:使用项目的包管理器、测试命名规则、初始化文件、模拟风格和导入别名。
  3. 保持测试的行为性:断言公开的结果而非私有实现细节。
  4. 隔离状态:当测试改变状态时,重置模拟、定时器、DOM、环境变量和模块状态。
  5. 先窄范围验证:在运行整个测试套件前,先运行单个文件或指定名称模式的测试。

Running Tests

运行测试

Run helper help when needed:
bash
python <skill>/scripts/run_vitest.py --help
Common pattern:
bash
python <skill>/scripts/inspect_vitest.py --root .
python <skill>/scripts/run_vitest.py --root . -- tests/example.test.ts
python <skill>/scripts/run_vitest.py --root . --coverage -- tests/example.test.ts
python <skill>/scripts/run_vitest.py --root . --test-name "formats currency"
If the helper cannot infer the package manager or script, use the project's own command exactly as defined in
package.json
.
必要时查看辅助脚本帮助:
bash
python <skill>/scripts/run_vitest.py --help
常见模式:
bash
python <skill>/scripts/inspect_vitest.py --root .
python <skill>/scripts/run_vitest.py --root . -- tests/example.test.ts
python <skill>/scripts/run_vitest.py --root . --coverage -- tests/example.test.ts
python <skill>/scripts/run_vitest.py --root . --test-name "formats currency"
如果辅助脚本无法推断包管理器或脚本,请完全按照
package.json
中定义的项目自有命令执行。

CI-Only Failures

仅CI环境下的失败

When tests fail in CI but pass locally, check environment differences before rewriting tests:
  • Node version:
    node -v
    ,
    .nvmrc
    ,
    .node-version
    ,
    package.json#engines
  • Package manager and lockfile: use the same install command as CI
  • Case-sensitive paths: Linux CI may fail on imports that macOS accepts
  • Tracked files: verify that required fixtures/config files are committed
  • Exact filename case: use
    git ls-files
    to confirm tracked path casing
  • Environment variables: compare local
    .env*
    assumptions with CI config
Useful checks:
bash
node -v
cat .nvmrc 2>/dev/null || true
node -p "require('./package.json').engines?.node" 2>/dev/null || true
git ls-files | grep -i 'expected-file-name'
git ls-files | awk '{ print tolower($0) }' | sort | uniq -d
当测试在CI环境中失败但在本地通过时,在重写测试前先检查环境差异:
  • Node版本:
    node -v
    ,
    .nvmrc
    ,
    .node-version
    ,
    package.json#engines
  • 包管理器和锁定文件:使用与CI相同的安装命令
  • 区分大小写的路径:Linux CI可能会在macOS可接受的导入路径上失败
  • 已跟踪文件:验证所需的 fixture/配置文件已提交
  • 文件名大小写:使用
    git ls-files
    确认已跟踪路径的大小写
  • 环境变量:比较本地
    .env*
    的假设与CI配置
实用检查命令:
bash
node -v
cat .nvmrc 2>/dev/null || true
node -p "require('./package.json').engines?.node" 2>/dev/null || true
git ls-files | grep -i 'expected-file-name'
git ls-files | awk '{ print tolower($0) }' | sort | uniq -d

Project-Specific Adapters

项目特定适配器

Plain Node / Library

纯Node / 库

Use
environment: 'node'
. Avoid DOM dependencies unless code requires browser APIs.
使用
environment: 'node'
。除非代码需要浏览器API,否则避免依赖DOM。

Vue / Vite

Vue / Vite

Use Vue Test Utils or the project's existing Testing Library setup. Ensure
jsdom
or
happy-dom
exists before writing DOM/component tests.
使用Vue Test Utils或项目现有的Testing Library配置。在编写DOM/组件测试前,确保
jsdom
happy-dom
已存在。

Nuxt

Nuxt

Prefer
@nuxt/test-utils
when present. Check whether the project uses
environment: 'nuxt'
,
happy-dom
,
jsdom
, or plain
node
. Do not replace Nuxt-aware tests with plain Vue tests for code that depends on Nuxt auto-imports, runtime config, plugins, routes, Nitro/server APIs, or module setup.
若存在
@nuxt/test-utils
则优先使用。检查项目是否使用
environment: 'nuxt'
happy-dom
jsdom
或纯
node
环境。对于依赖Nuxt自动导入、运行时配置、插件、路由、Nitro/服务器API或模块设置的代码,不要用纯Vue测试替换支持Nuxt的测试。

Vue / Nuxt Gotchas

Vue / Nuxt 注意事项

For Pinia-dependent components/composables, use the project's existing Pinia testing setup instead of hand-rolled mocks. For async Vue rendering, await framework utilities such as
nextTick
/
flushPromises
or Testing Library
findBy*
queries; do not sleep. For Suspense, async components, Teleport, plugins, or provide/inject, prefer existing project test helpers before creating new wrappers.
对于依赖Pinia的组件/组合式函数,使用项目现有的Pinia测试配置而非手动编写的模拟。对于异步Vue渲染,等待框架工具如
nextTick
/
flushPromises
或Testing Library的
findBy*
查询;不要使用休眠。对于Suspense、异步组件、Teleport、插件或provide/inject,优先使用项目现有的测试助手,再考虑创建新的包装器。

React / Vite

React / Vite

Use React Testing Library when present. If using
toBeInTheDocument
, verify that
@testing-library/jest-dom/vitest
is imported in an existing setup file, or add it only when the dependency exists or is being installed.
若存在React Testing Library则使用。如果使用
toBeInTheDocument
,验证
@testing-library/jest-dom/vitest
是否已在现有初始化文件中导入,仅当依赖已存在或正在安装时才添加它。

Next.js / React

Next.js / React

For Next.js projects, prefer the existing project setup. Vitest is suitable for unit tests of client components and synchronous components, usually with React Testing Library and
jsdom
.
Do not assume Vitest can fully test async Server Components. For async Server Components, prefer the project's existing E2E setup, usually Playwright or another browser-level test runner.
对于Next.js项目,优先使用项目现有的配置。Vitest适用于客户端组件和同步组件的单元测试,通常搭配React Testing Library和
jsdom
不要假设Vitest可以完全测试异步Server Components。对于异步Server Components,优先使用项目现有的E2E配置,通常是Playwright或其他浏览器级测试运行器。

Monorepo / Multi-environment

单仓库 / 多环境

Check for Vitest test projects/workspace configuration before creating a new config. Preserve existing project boundaries and environment-specific settings.
在创建新配置前,检查是否存在Vitest测试项目/工作区配置。保留现有项目边界和特定环境的设置。

Writing Patterns

编写模式

  • Use
    describe
    ,
    it
    /
    test
    ,
    expect
    , and
    vi
    from
    vitest
    .
  • Use
    vi.fn()
    for function seams and
    vi.mock()
    for module boundaries.
  • Prefer deterministic inputs over snapshots. Use snapshots only for stable, intentional structures.
  • For dates and timers, use fake timers and restore real timers in teardown.
  • For async code, await observable outcomes instead of sleeping.
  • For components, render through the framework's testing library and assert accessible output.
  • For repeated setup, prefer small local helpers or Vitest fixtures/
    test.extend
    over copy-pasting large setup blocks.
  • For type-level assertions, use
    expectTypeOf
    or
    assertType
    only when the project already has type tests or the user explicitly asks.
  • For coverage, add thresholds only when the project already enforces them or the user asks.
  • When adding a sample test, pick a real existing source file. Do not invent fake modules just to demonstrate syntax.
  • 使用
    vitest
    提供的
    describe
    it
    /
    test
    expect
    vi
  • 使用
    vi.fn()
    作为函数接缝,使用
    vi.mock()
    作为模块边界。
  • 优先使用确定性输入而非快照。仅对稳定、有意设计的结构使用快照。
  • 对于日期和定时器,使用假定时器并在清理阶段恢复真实定时器。
  • 对于异步代码,等待可观察的结果而非休眠。
  • 对于组件,通过框架的测试库渲染并断言可访问的输出。
  • 对于重复的初始化,优先使用小型本地助手或Vitest fixtures/
    test.extend
    ,而非复制粘贴大型初始化块。
  • 对于类型级断言,仅当项目已有类型测试或用户明确要求时,才使用
    expectTypeOf
    assertType
  • 对于测试覆盖率,仅当项目已强制执行阈值或用户要求时,才添加阈值。
  • 添加示例测试时,选择真实存在的源文件。不要为了演示语法而虚构模块。

Migration Notes

迁移说明

Treat Jest migration as a focused refactor, not a blind full-suite rewrite. Migrate one file or repeated pattern first, then run narrow tests.
Map imports and globals deliberately:
  • jest.fn()
    ->
    vi.fn()
  • jest.mock()
    ->
    vi.mock()
  • jest.spyOn()
    ->
    vi.spyOn()
  • jest.useFakeTimers()
    ->
    vi.useFakeTimers()
  • jest.resetModules()
    ->
    vi.resetModules()
Also check timer behavior, fake timers, snapshots, config differences, setup files, aliases, and test environment. Do not enable Vitest globals just to avoid imports unless the existing project already uses global test APIs.
将Jest迁移视为聚焦的重构,而非盲目的全套件重写。先迁移一个文件或重复模式,然后运行窄范围测试。
有目的地映射导入和全局变量:
  • jest.fn()
    ->
    vi.fn()
  • jest.mock()
    ->
    vi.mock()
  • jest.spyOn()
    ->
    vi.spyOn()
  • jest.useFakeTimers()
    ->
    vi.useFakeTimers()
  • jest.resetModules()
    ->
    vi.resetModules()
同时检查定时器行为、假定时器、快照、配置差异、初始化文件、别名和测试环境。除非现有项目已使用全局测试API,否则不要为了避免导入而启用Vitest全局变量。

Common Failure Modes

常见失败模式

  • Aliases fail: make Vitest config reuse the same aliases as Vite/TS config.
  • DOM APIs missing: choose
    jsdom
    or
    happy-dom
    for component tests.
  • Mocks leak between tests: add
    afterEach(() => vi.restoreAllMocks())
    or project-equivalent cleanup.
  • Timer tests hang: restore real timers and advance timers explicitly.
  • ESM/CJS mismatch: follow the project module type and avoid mixing require/import patterns.
  • Flaky async tests: wait for specific state, DOM text, emitted events, or resolved promises.
  • 别名失效:让Vitest配置复用与Vite/TS配置相同的别名。
  • DOM API缺失:为组件测试选择
    jsdom
    happy-dom
  • 模拟在测试间泄漏:添加
    afterEach(() => vi.restoreAllMocks())
    或项目等效的清理代码。
  • 定时器测试挂起:恢复真实定时器并显式推进定时器。
  • ESM/CJS不匹配:遵循项目模块类型,避免混合require/import模式。
  • 不稳定的异步测试:等待特定状态、DOM文本、触发的事件或已解析的Promise。

Reference Examples

参考示例

  • examples/node_function.test.ts
    - Pure TypeScript/Node logic
  • examples/react_component.test.tsx
    - React Testing Library style
  • examples/vue_component.test.ts
    - Vue Test Utils style
  • examples/node_function.test.ts
    - 纯TypeScript/Node逻辑
  • examples/react_component.test.tsx
    - React Testing Library风格
  • examples/vue_component.test.ts
    - Vue Test Utils风格