Skip to content

Migrate frontend test framework from Karma to Vitest #4861

@Yicong-Huang

Description

@Yicong-Huang

Task Summary

Replace Karma + Jasmine with Vitest for the Angular 21 frontend. Removes a deprecated runner, modernizes the test setup, and keeps texera on the path Angular's tooling team is investing in.

Why now, why Vitest

Karma is deprecated. npm-published deprecation since April 2023; Angular's official builder treats @angular-devkit/build-angular:karma as end-of-life. We are still on karma@6.4.4 + karma-jasmine@5.1.0.

Three options were considered:

  1. Stay on Karma. Increasingly broken on each Angular major (we have already shipped one workaround in karma.conf.js for the Angular --code-coverage injection). Defers the inevitable.
  2. Migrate to Jest. PR Migrate frontend test framework from Karma to Jest #2995 (Nov 2024, closed unmerged) attempted this. Path works, but Angular's Jest support is officially "experimental" and frozen — no further investment from the team. The PR's own checklist captured one pain point that never got resolved: "ignore transformation of ESM modules" — Jest needs transformIgnorePatterns per ESM dependency in node_modules, a recurring tax on every dependency bump.
  3. Migrate to Vitest. Angular's actively-developed test runner path (Angular 19+); ESM-native so the Jest pain point doesn't apply; Vite-powered for fast watch; expect API is Jest-compatible so most matcher / spy code reads identically.

We are choosing option 3 — Vitest — because picking Jest in 2026 inherits Karma's fate in 2-3 years.

Known friction points

  • frontend/custom-webpack.config.js is webpack-specific. Any test-time aliases / loaders / env-var injection there have to be re-expressed for Vite.
  • We use Nx (nx.json, @nx/angular) as a thin cache wrapper. The @nx/vitest executor is younger than @nx/jest. Worst case: bypass Nx for the test target and use ng test --use=vitest directly.
  • 73 *.spec.ts files to migrate. Most should be a near-mechanical sweep:
    • jasmine.createSpy / jasmine.Spyvi.fn() / Mock from vitest
    • spyOn(obj, 'method').and.returnValue(...)vi.spyOn(obj, 'method').mockReturnValue(...)
    • jasmine.clock()vi.useFakeTimers()
    • expect(x).toEqual(y) etc. unchanged
  • Coverage: switch karma-coverage (lcov via Karma) to Vitest's coverage (v8 by default). The Codecov upload glob already targets frontend/coverage/**/lcov.info, which Vitest's coverage reporter can produce when configured.

Recoverable from PR #2995

Most of #2995's 3,959 line diff is reusable: removing karma packages, fixing wrong test-file imports (e.g., HttpClient), deleting empty test files. Only the runner config and jest.fnvi.fn swap differ. Roughly 70–80% of the work transfers.

Plan

Land in stages, smallest first:

  1. Scaffolding PR (this issue's first deliverable): add Vitest deps + config, switch the ng test target, remove Karma deps and karma.conf.js. Goal: existing 73 spec files run under Vitest, even if some need shims.
  2. Mechanical migration sweeps: batch updates for jasmine.*vi.* patterns, in chunks small enough to review.
  3. Cleanup PR: delete empty / dead spec files surfaced during the sweep, fix the transformIgnorePatterns-equivalent ESM issues that PR Migrate frontend test framework from Karma to Jest #2995 left open.
  4. CI rewire: update frontend/karma.conf.js references in .github/workflows/build.yml and Codecov upload paths if needed.

References

Task Type

  • Refactor / Cleanup
  • DevOps / Deployment / CI
  • Testing / QA
  • Documentation
  • Performance
  • Other

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions