Skip to Content

Vitest

Vitest test source rules from @vitest/eslint-plugin.

Vitest reuses much of Jest’s testing surface but ships its own runner and configuration.

These rules mirror the ergonomic subset of eslint-plugin-jest adapted for Vitest semantics, including focused tests, identical titles, conditional logic, valid expect shape.

Source: @vitest/eslint-plugin (MIT).

Rule index

Each rule name links to the detailed section below.

Examples come from the checked lint corpus or package-level rule tests when project layout matters.

Rules

vitest/expect-expect

Require every Vitest test body to contain at least one expect(...) call. A test with no assertions still passes, giving a false-positive signal.

Example:

// reports: vitest/expect-expect (error) test("loads", () => { render(); });

vitest/no-conditional-expect

Reject expect(...) calls under if/try/catch or other conditional branches in Vitest tests.

A branch that never runs turns the assertion into a silent no-op rather than a failure.

Example:

const ready = true; const value = 1; it("checks conditionally", () => { if (ready) { // reports: vitest/no-conditional-expect (error) expect(value).toBe(1); } });

vitest/no-conditional-tests

Reject test(...)/it(...) declarations inside loops or if branches.

Vitest collects tests at module load, so a conditional declaration produces a different suite shape than the file appears to describe.

Example:

if (process.env.CI) { // reports: vitest/no-conditional-tests (error) test("ci only", () => expect(true).toBe(true)); }

vitest/no-disabled-tests

Reject test.skip, it.skip, describe.skip, and .todo variants.

Disabled tests rot in place and quietly drop coverage for the feature they were meant to pin.

Example:

// reports: vitest/no-disabled-tests (error) test.skip("temporarily ignored", () => { expect(value).toBe(1); });

vitest/no-done-callback

Reject done callback parameters in Vitest tests and lifecycle hooks.

The callback style predates async/await and makes failure propagation easy to miss; return a Promise or mark the body async instead.

Example:

// reports: vitest/no-done-callback (error) it("uses callback", (done) => { done(); });

vitest/no-focused-tests

Reject test.only, it.only, and describe.only.

A focused suite silently skips the rest of the file, so a stray .only left from debugging hides every other test in CI.

Example:

// reports: vitest/no-focused-tests (error) test.only("focused", () => { expect(value).toBe(1); });

vitest/no-identical-title

Reject duplicate Vitest test or describe titles within the same suite scope.

The runner cannot disambiguate two siblings with identical names in its error output or filter flags.

Example:

const add = (left: number, right: number) => left + right; describe("math", () => { test("adds", () => expect(add()).toBe(1)); // reports: vitest/no-identical-title (error) test("adds", () => expect(add()).toBe(2)); });

vitest/no-standalone-expect

Reject expect(...) calls outside Vitest tests and hooks.

Top-level assertions execute at module load before any test starts, so failures never attach to a named case.

Example:

// reports: vitest/no-standalone-expect (error) expect(value).toBe(1);

vitest/no-test-return-statement

Reject return statements that return non-Promise values from a Vitest test callback.

The runner ignores the value and following code is dead, which usually masks a missing await or stray early-exit.

Example:

const buildValue = () => 1; test("returns", () => { // reports: vitest/no-test-return-statement (error) return buildValue(); });

vitest/prefer-to-have-length

Prefer expect(value).toHaveLength(n) over asserting on value.length with toBe.

The dedicated matcher reports the actual length on failure instead of a bare number mismatch.

Example:

const items = [1, 2, 3]; test("length", () => { // reports: vitest/prefer-to-have-length (error) expect(items.length).toBe(3); });

vitest/valid-describe-callback

Validate the shape of Vitest describe callbacks.

The callback must be synchronous and take no arguments, the runner ignores returned Promises and done-style parameters at the describe level.

Example:

// reports: vitest/valid-describe-callback (error) describe("suite", async () => { test("case", () => expect(value).toBe(1)); });

vitest/valid-expect

Validate expect(...) arity and matcher chaining: exactly one argument, terminated by a matcher call, and async matchers properly awaited.

Malformed expects either throw at runtime or pass without asserting anything.

Example:

const value = 1; test("bare", () => { // reports: vitest/valid-expect (error) expect(value); });

vitest/valid-title

Require non-empty static Vitest test and describe titles.

Empty or dynamically-built titles produce unreadable failure output and break filter-by-name flags.

Example:

// reports: vitest/valid-title (error) test("", () => { expect(value).toBe(1); });
Last updated on