How would you move an existing Angular Karma and Jasmine suite to the unit-test builder with Vitest, and what does the migrate-karma-to-vitest migration leave for you?
answer
- application builder first
- an optional v22 update migration
- build options move to a configuration
- specs are rewritten separately
basics
~10 sEnsure the build uses @angular/build:application, run the optional migrate-karma-to-vitest migration to switch the test target to @angular/build:unit-test with Vitest, then install jsdom, run refactor-jasmine-vitest on the specs, and port custom Karma config by hand.
solid answer
~40 sThe prerequisite is the `@angular/build:application` build system; the migration skips projects without it, and libraries too. The optional v22 `migrate-karma-to-vitest` migration switches the `test` target to `@angular/build:unit-test` with `runner: "vitest"`, moves build options such as `polyfills`, `styles` and `assets` into a new `testing` build configuration, renames `codeCoverage` to `coverage`, maps a custom `main` to `setupFiles`, swaps `jasmine` for `vitest/globals` in tsconfig types, deletes a plain `karma.conf.js` or flags a customised one, and adds `vitest`. It does not touch spec files: that is the `refactor-jasmine-vitest` schematic. I would still install `jsdom`, port reporters and launchers, handle `fakeAsync` with the Zone.js Vitest patch or fake timers, and compare pass counts before removing Karma.
code
bash · 8 lines# 1. after the optional migrate-karma-to-vitest migration has rewritten angular.json
npm install --save-dev jsdom
# 2. rewrite Jasmine specs to Vitest APIs, one area at a time
ng g @schematics/angular:refactor-jasmine-vitest --include=src/app/profile
# 3. run the suite on the new builder and compare with the Karma baseline
ng test --watch=falsego deeper
Recall the two tools: the optional migrate-karma-to-vitest migration for configuration and the refactor-jasmine-vitest schematic for spec files.
Explain what the migration changes in angular.json, the testing build configuration, option renames and setupFiles, and what it leaves undone.
Run it as a staged project: baseline counts, application-builder prerequisite, folder-by-folder spec refactoring, isolation and fakeAsync fixes, then removal of Karma.
Decide whether and when each project migrates, weighing Karma plugin dependencies, CI time savings and the risk of silently skipped or weakened tests.
## The scenario An application created before v21 runs a few thousand Jasmine specs through a legacy **Karma builder** (`@angular-devkit/build-angular:karma` or `@angular/build:karma`) with a customised `karma.conf.js`. The team wants the **`@angular/build:unit-test`** builder with **Vitest**. The Angular docs still call migrating an existing project experimental, so plan it as a project with checkpoints, not a one-command upgrade. ## Prerequisites 1. The project's `build` target must already use **`@angular/build:application`**. The automated migration skips any project that does not, and the unit-test builder compiles specs through that build system. 2. Only **application** projects are migrated automatically; libraries are skipped and done by hand. 3. The suite should be green on Karma first, so every later failure is attributable to the move. ## What the optional `migrate-karma-to-vitest` migration does Since v22 the CLI ships an **optional** update migration, `migrate-karma-to-vitest`. For each eligible project whose `test` target uses a Karma builder, it: - sets the builder to `@angular/build:unit-test` and `runner` to `"vitest"`; - moves **build options** that the unit-test builder no longer accepts on the test target (`assets`, `styles`, `scripts`, `polyfills`, `inlineStyleLanguage`, `fileReplacements`, `aot` and others) into a new **`testing`** configuration of the `build` target, starting from `aot: false`, `optimization: false` and `extractLicenses: false` to match Karma's behaviour, and points the test target's `buildTarget` at it; - renames options: `codeCoverage` becomes `coverage`, `codeCoverageExclude` becomes `coverageExclude`; `sourceMap` is dropped because source maps are always on; - maps a custom `main` test entry to **`setupFiles`**, with a warning to remove `TestBed.initTestEnvironment` calls, since the builder initialises TestBed itself; - replaces `jasmine` with `vitest/globals` in the spec tsconfig's `types`; - deletes `karma.conf.js` when it holds nothing custom, and **lists it for manual migration** when it does; - adds `vitest` as a dev dependency, plus a coverage provider when coverage was enabled. ## What it does not do | Still your job | How | |---|---| | Rewrite spec files from Jasmine to Vitest APIs | the `refactor-jasmine-vitest` schematic, which the migration suggests at the end | | Install a DOM emulator | add `jsdom` or `happy-dom`; non-browser runs refuse to start without one | | Port custom Karma reporters, plugins and launchers | `reporters` in `angular.json`, a Vitest config via `runnerConfig`, `browsers` plus a browser provider | | Keep `fakeAsync` working | add `zone.js/plugins/vitest-patch` to the test polyfills, or convert to the runner's fake timers | ## A migration plan that holds up 1. **Branch and baseline**: record the Karma pass count and duration. 2. **Run the migration** through the CLI's update flow (or apply the manual steps from the docs), review the `angular.json` diff and the new `testing` build configuration. 3. **Install `jsdom`** and, if some specs truly need a browser, a browser provider with a separate `browsers` configuration. 4. **Refactor the specs** with `ng g @schematics/angular:refactor-jasmine-vitest`, one folder at a time with `--include` on a large suite, then review every TODO it leaves. 5. **Fix what differs**: layout-dependent specs that relied on a real Chrome, tests that leaked state between files (the builder's `isolate` option defaults to `false`, matching Karma's shared-context behaviour), and `fakeAsync` tests. 6. **Compare** pass counts, look for silently skipped specs, and delete the Karma packages only when the numbers match. ## Reading the migration's summary The migration ends by printing a summary, and each line is a to-do: - **Projects migrated**: these now use the unit-test builder; their specs still need refactoring. - **Projects skipped (non-applications)**: libraries, which you configure by hand. - **Projects skipped (missing application builder)**: move their `build` target to `@angular/build:application` first, then migrate their test target. - **Karma configuration files requiring manual migration**: customised `karma.conf.js` files it left in place; port their settings before deleting them. - **The suggested command** for `refactor-jasmine-vitest`, which is the next step for every migrated project. ## Staying on Karma is legitimate Karma remains supported. Keeping it, or switching to the unit-test builder with `"runner": "karma"` as an intermediate step, is reasonable when a suite depends on Karma plugins with no Vitest equivalent or when the migration cost is not yet justified.
- The migration logs that karma.conf.js requires manual migration. What usually lives there, and where does it go?Custom reporters, plugins and browser launchers. Reporters map to the unit-test builder's `reporters` option or a Vitest config file linked through `runnerConfig`; launchers become the `browsers` option plus a browser provider package; coverage is the builder's `coverage` options. Anything without an equivalent needs a Vitest plugin or a decision to drop it.
- After the move, a spec passes alone but fails in the full run. What builder option is involved?`isolate`, which defaults to `false` to match the shared-context behaviour of Karma and Jasmine. State leaking between spec files, such as a module-level variable or a global patched and never restored, therefore survives across files. Fix the leak in the spec, or enable `isolate` to run files separately at some speed cost.
saying these in an interview costs you the question
- The migration also rewrites spyOn calls in every spec file
- Projects still on the browser builder are migrated automatically
- The unit-test builder accepts polyfills and styles on the test target
- Karma must be removed because v22 no longer supports it
- jsdom is added by the migration, so nothing else needs installing