no-unsupported-project-options
Disallow documented root-only Vitest options inside project configs.
Rule catalog ID: R015
Targeted pattern scopeโ
vitest.config.*vitest.workspace.*vite.config.*when Vitest project arrays are defined theredefineProject({...})- inline project entries inside
defineWorkspace([...]) - inline project entries inside
test.projects: [...]
What this rule reportsโ
This rule reports documented root-only project options when they appear inside a project config:
test.coveragetest.reporterstest.resolveSnapshotPath
Why this rule existsโ
Vitest project configs do not support every root-level option.
The upstream docs call out coverage, reporters, and resolveSnapshotPath as important examples that only work at the root config level.
TypeScript users often catch this through defineProject(...) types, but JavaScript configs and mixed config setups benefit from a dedicated lint rule that fails earlier and more explicitly.
โ Incorrectโ
import { defineProject } from "vitest/config";
export default defineProject({
test: {
coverage: {
provider: "v8",
},
name: "unit",
},
});
โ Correctโ
import { defineConfig, defineProject } from "vitest/config";
export default defineConfig({
test: {
coverage: {
provider: "v8",
},
projects: [
defineProject({
test: {
environment: "node",
name: "unit",
},
}),
],
},
});
Behavior and migration notesโ
- move root-only options to the root Vitest config, not the individual project entry
- this rule intentionally focuses on the documented root-only options with the clearest static behavior
- top-level Vite options such as
resolve.aliasremain valid outside the nestedtestproject config object
ESLint flat config exampleโ
import vite from "@typpi/eslint-plugin-vite";
export default [vite.configs.recommended, vite.configs.vitest];
When not to use itโ
Disable this rule only if your repository deliberately keeps these unsupported settings in project configs for compatibility experiments and you accept that Vitest only respects them at the root level.