Skip to content

Replace Karma with Vitest - #57

Open
hupponen wants to merge 4 commits into
masterfrom
replace-karma-with-vitest
Open

Replace Karma with Vitest#57
hupponen wants to merge 4 commits into
masterfrom
replace-karma-with-vitest

Conversation

@hupponen

@hupponen hupponen commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Karma hasn't been usable for a long time, so the unit tests haven't been run either. Two independent reasons: karma.conf.js requires karma-coverage-istanbul-reporter, which isn't installed, and src/test.ts imports zone.js/dist/... paths that no longer exist in current zone.js.

Vitest runs the tests in Node without a browser, so they also work in containers and in CI, where Karma's Chrome isn't available. The whole suite takes about a second.

Changes

Add Vitest for unit tests (2ac8e348)

  • vitest.config.mts, and src/test-setup.ts which imports @angular/compiler so the JIT compiler is available as a fallback for the partially compiled declarations in the published Angular packages
  • Specs import describe/it/expect from vitest explicitly instead of relying on globals, which keeps them type-checked without any tsconfig changes
  • Delete the eight component specs that only asserted expect(component).toBeTruthy(). They were generated by the Angular CLI and were never given the services the components inject, so TestBed.createComponent() would have thrown. TestBed support comes with the Angular 20 unit-test builder, which also uses Vitest
  • Delete a disabled test that expected getItemsByIndexes() to throw for a non-array input: it asserted a return value instead, and lodash map() returns an empty array for undefined, so it could never pass

Remove unused Karma test setup (48e25747)

  • Remove karma.conf.js, src/test.ts, the Angular test target and the Karma and Jasmine dependencies. npm test now runs Vitest
  • test/unit-tests.html was an even older SystemJS and Jasmine runner, with test/liteserver-test-config.json only pointing at it
  • Fixes a real bug: removing Karma also removed lodash from node_modules, which revealed that session.resource.ts and datasetmodal.service.ts imported lodash even though only lodash-es is declared as a dependency. They had been resolving to the copy Karma happened to bring in, so the production build broke as soon as Karma was gone. They now import chunk() and cloneDeep() from lodash-es like the rest of the code

Remove unused Protractor e2e setup (e58991aa)

  • The e2e target pointed to e2e/protractor.conf.js, but that directory doesn't exist and protractor isn't a dependency. Angular CLI dropped Protractor support years ago

Type check the specs with the root tsconfig (f2c932fc)

  • Vitest only transpiles, it doesn't check types, so tsc -p tsconfig.json --noEmit is what type checks the specs. The root tsconfig has no include, so it already covers them
  • Vitest ships .d.ts files that reference exports-map subpaths, which moduleResolution: "node" cannot follow. Use "bundler" instead, which resolves them and is the default of new Angular projects. Unlike skipLibCheck, that keeps the type checking of dependencies on
  • Delete tsconfig.spec.json: the Angular test target that used it is gone and Vitest doesn't read it

Testing

  • npm test: 16 tests pass, no skipped tests, ~1.1 s
  • npx tsc -p tsconfig.json --noEmit: no errors, this is what type checks the specs
  • npx tsc -p tsconfig.app.json --noEmit: no errors
  • npm run build: production bundle builds

Reviewers need npm ci after checkout, because the lockfile changed.

Only unit tests are in scope here. Testing user flows, e.g. that dialogs close when navigating, needs a real browser and is left for a Playwright setup.

Vitest runs the tests in Node without a browser, so they can run in
containers and CI where Karma's Chrome is not available. Run them with
npm run test:unit.

Delete the eight component specs that only checked that the component can
be created. They were generated by the Angular CLI and never given the
services the components inject, so TestBed.createComponent() would have
thrown. Angular's TestBed support comes with the Angular 20 unit-test
builder, which also uses Vitest.

Also delete a disabled test that expected getItemsByIndexes() to throw for
a non-array input. It asserted a return value instead, and lodash map()
returns an empty array for undefined, so the test could never pass.
Karma hasn't been usable for a long time: karma.conf.js requires
karma-coverage-istanbul-reporter, which isn't installed, and src/test.ts
imports zone.js/dist paths that no longer exist. Tests run with Vitest now,
so remove the config, the entry point, the Angular test target and the
Karma and Jasmine dependencies. test/unit-tests.html was an even older
SystemJS and Jasmine runner, with test/liteserver-test-config.json only
pointing at it.

Removing Karma also removed lodash from node_modules, which revealed that
session.resource.ts and datasetmodal.service.ts imported 'lodash' even
though only 'lodash-es' is declared as a dependency. They resolved to the
copy that Karma happened to bring in. Import chunk() and cloneDeep() from
lodash-es like the rest of the code does.
The e2e target pointed to e2e/protractor.conf.js, but that directory
doesn't exist and protractor isn't a dependency, so 'ng e2e' could not
run. Angular CLI dropped Protractor support years ago.
@hupponen
hupponen requested a review from klemela August 28, 2026 11:10
Vitest only transpiles, it doesn't check types, so 'tsc -p tsconfig.json
--noEmit' is what type checks the specs. The root tsconfig has no include,
so it already covers them.

Vitest ships .d.ts files that reference exports-map subpaths, which the
'node' module resolution cannot follow. Use 'bundler' resolution instead,
which resolves them and is the default of new Angular projects. That keeps
the type checking of dependencies on, unlike skipLibCheck.

tsconfig.spec.json is not needed for this and nothing read it anymore: the
Angular test target that used it is gone and Vitest doesn't read it.
@hupponen
hupponen force-pushed the replace-karma-with-vitest branch from 9724c62 to f2c932f Compare August 28, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant