Skip to content

Vitest focused runs compile every tsconfig.spec root instead of only requested test filters #2325

Description

@NateRadebaugh

Please provide the environment you discovered this bug in.

Summary

When using @analogjs/vite-plugin-angular with Vitest, focused test runs still appear to build and emit from every root in tsconfig.spec.json, even when Vitest is invoked with explicit file or directory filters.

For large Angular workspaces, this makes small focused test runs much slower than expected. Vitest reports a short Duration, but the wall-clock time is much higher because the Angular Vite plugin does substantial TypeScript/Angular startup work before Vitest reaches its own Start at timestamp.

Environment

@analogjs/vite-plugin-angular: 2.4.10
Angular: 21.x
Vite: 8.x
Vitest: 4.x
Node: 22.x
Test environment: happy-dom

Which area/package is the issue in?

vitest-angular

Description

Current behavior

Given a broad tsconfig.spec.json like:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "noCheck": true,
    "outDir": "./out-tsc/spec",
    "types": ["vitest/globals", "node"]
  },
  "include": ["__test__/setup-tests.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
}

Running a focused command such as:

vitest run --mode production src/standard/ts/tryParseJson.test.ts src/standard/standard-alert/standard-alert.component.test.ts

still pays startup cost proportional to the full spec root set. In our workspace, CPU profiling showed the remaining startup cost dominated by TypeScript work in the Angular plugin path.

Expected behavior

For focused Vitest runs, the Angular Vite plugin should avoid building/emitting the entire tsconfig.spec.json root set when Vitest has already been given explicit file, folder, or glob filters.

Ideally, test mode would:

  • Preserve non-test/setup roots needed for the test environment.
  • Filter test/spec roots to the files matching Vitest’s requested filters.
  • Fall back to the full tsconfig.spec.json root list when no focused filters are supplied.
  • Preserve existing behavior for full-suite runs, watch mode, and app/library builds.

Please provide the exception or error you saw

Measurements

Before the local patch:

Focused representative sample:
234 tests passed
Wall time: 28.26s
Vitest Duration: 3.73s

After a local patch-package change that filters rootNames by the Vitest CLI file/folder/glob filters:

Focused representative sample:
234 tests passed
Wall time: 15.66s
Vitest Duration: 3.81s

CPU profiling also showed the main TypeScript startup bucket drop from about 16.5s to about 8.0s.

Other information

Local patch approach

The local experiment added a filter before the Angular program is created:

let rootNames = [...cached.rootNames];

if (isTest) {
  rootNames = filterTestRootNames(rootNames);
}

The filter derives requested test paths from Vitest CLI args, keeps the setup file, includes matching file/folder/glob roots, and falls back to the full root list if no focused filters are present.

This was intentionally a local proof of concept. An upstream implementation should probably avoid hardcoding project-specific setup paths and instead preserve non-test roots or use resolved Vitest setup/config data if available.

Why this matters

Focused Vitest runs are common during local development. In large Angular workspaces, compiling/emitting every spec root makes “run one test file” feel close to “start the whole test project,” even when the actual tests complete quickly.

This seems like a good upstream optimization because it preserves shared test configuration while making focused runs scale with the requested test scope.


AI disclosure: research and summary written with GPT-5.5 and tested+reviewed by human.

I would be willing to submit a PR to fix this issue

  • Yes
  • No

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions