Open-Source Wikis

/

Vue.js

/

How to contribute

/

Testing

vuejs/core

Testing

Vue uses Vitest for all of its tests. The configuration lives in vitest.config.ts, which defines several Vitest "projects" so different tests can run with different setups in a single command.

Running tests

# everything in watch mode (default vitest behavior)
pnpm test

# run once and exit (CI's mode)
pnpm test run

# all tests under a package
pnpm test runtime-core

# tests by file pattern (matches both filename and path)
pnpm test renderer
pnpm test reactivity/__tests__/effect

# a specific test name within matching files
pnpm test renderer -t "should mount component"

# only the unit project (skip e2e)
pnpm test-unit

# the e2e project (real browser via puppeteer)
pnpm test-e2e

# coverage report (writes to coverage/, mirrored at coverage.vuejs.org)
pnpm test-coverage

For type-level tests:

# build the .d.ts files first, then run dts-test
pnpm test-dts

# re-run only the dts-test project (assumes types are built)
pnpm test-dts-only

Project layout

Each package's tests live in packages/<pkg>/__tests__/ and are colocated with the source. There are 195 spec/test files across the public packages:

Package Test files
runtime-core 45
compiler-core 21
compiler-sfc 20
vue 20
server-renderer 18
compiler-ssr 16
reactivity 16
runtime-dom 16
compiler-dom 13
vue-compat 12
shared 6
runtime-test 1

packages-private/dts-test/ holds the type-level tests that run against the built .d.ts files.

vitest.config.ts configures three projects:

  • unit — runs against source code, fastest. The default for pnpm test. Includes setup file scripts/setup-vitest.ts which installs __DEV__, __TEST__, __BROWSER__, etc., as globals so source files behave consistently.
  • unit-jsdom — same as unit but runs in a jsdom environment for tests that need a window/document. Used by runtime-dom, vue, and server-renderer tests that exercise hydration.
  • e2e — boots a real Chromium via puppeteer against the built vue.global.js and runs the HTML examples under packages/vue/examples/__tests__/. Slow; only useful for verifying the global build works end-to-end.

The unit project is the right default. The setup file sets __DEV__ to true and stubs out other build flags so warning behavior is testable.

Writing a test

The contributing guide gives three rules:

  1. Use the minimal API needed. A test that doesn't need reactivity or a component shouldn't import them. Smaller surface area → fewer false failures when unrelated code changes.
  2. Use @vue/runtime-test for platform-agnostic behavior. Its nodeOps.ts mints plain JS objects instead of DOM nodes, so renderer/scheduler tests stay isolated from the DOM.
  3. Use platform runtimes only when testing platform behavior. Tests for v-model, focus events, or hydration mismatches need runtime-dom + jsdom.

Example skeleton from packages/runtime-test:

import { h, nodeOps, render, serializeInner } from '@vue/runtime-test';

test('mounts a div with text', () => {
  const root = nodeOps.createElement('div');
  render(h('div', 'hello'), root);
  expect(serializeInner(root)).toBe('<div>hello</div>');
});

packages/runtime-test/src/serialize.ts produces a stable string form of the node tree, which is the recommended way to assert renderer output.

Type tests

Type-level tests live in packages-private/dts-test/. They are TypeScript files containing expectType<T>(value) and expectError<T>(...) assertions that rely on the actual generated .d.ts files. To run:

pnpm test-dts        # builds dts then runs
pnpm test-dts-only   # runs against existing dts (faster)

The script checks packages-private/dts-test/tsconfig.test.json against the built *.d.ts files. A passing build means the public types still hold up.

What CI runs

.github/workflows/test.yml runs the matrix:

  • pnpm test run (unit + unit-jsdom + e2e + dts) on Node 20 across Linux/macOS/Windows.
  • pnpm test-coverage on Linux only, with the report uploaded.

.github/workflows/ci.yml separately runs pnpm check, pnpm lint, pnpm format-check. Failing any of these blocks merge.

Common pitfalls

  • Forgetting await nextTick() when mutating state in a test. Vue defers component updates to a microtask flush; expect(...) immediately after a mutation will see the pre-update DOM.
  • Mixing runtime-dom and runtime-test in the same suite leads to two separate copies of the renderer. Pick one and stick with it.
  • Tests that only improve coverage, not behavior, are explicitly discouraged. Coverage is a guidance metric, not a goal.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Testing – Vue.js wiki | Factory