What does the Angular CLI's refactor-jasmine-vitest schematic rewrite in spec files, and what must you still check or fix by hand?
answer
- spec files, not configuration
- focus, skip and spy calls
- globals mean no imports
- TODO comments mark the gaps
basics
~20 srefactor-jasmine-vitest rewrites Jasmine APIs in spec files to Vitest (fit to it.only, spyOn to vi.spyOn, createSpy to vi.fn and more) and leaves TODOs; it installs nothing, changes no angular.json, and cannot handle every complex spy.
solid answer
~30 sIt is a schematic in `@schematics/angular`, run as `ng g @schematics/angular:refactor-jasmine-vitest` once the project is configured for Vitest. It rewrites Jasmine-specific code: `fit`/`fdescribe` to `.only`, `xit`/`xdescribe` to `.skip`, `spyOn` to `vi.spyOn`, `jasmine.createSpy` to `vi.fn`, `jasmine.objectContaining` and `jasmine.any` to their `expect` forms, `fail` to `vi.fail`, plus matcher and hook adjustments, and writes a report. Options include `--include` for slicing a large suite, `--add-imports` (off because the builder enables Vitest globals), `--browser-mode` and `--fake-async`. It does not install packages, edit `angular.json` or delete Karma files, and complex spies get TODO comments, so I review every change and compare executed-test counts.
go deeper
Recall that the schematic rewrites Jasmine APIs in spec files, such as spyOn to vi.spyOn and fit to it.only, and nothing else.
Explain its main transformations and options, why imports are off by default, and the list of things it leaves undone.
Run it in reviewable slices, resolve its TODOs, and verify executed-test counts and spy semantics rather than trusting a green run.
Plan the refactor across teams so large suites move incrementally, with review ownership and metrics that catch silently weakened tests.
## What the schematic is for Moving an Angular project from Karma to Vitest has two halves. The configuration half (`angular.json`, dependencies, tsconfig types) is handled by the optional `migrate-karma-to-vitest` update migration or by hand. The **spec files** are the other half: they are written against **Jasmine's** globals, and the Vitest runner does not provide Jasmine's spy API. The Angular CLI's **`refactor-jasmine-vitest`** schematic in `@schematics/angular` rewrites those files. The Angular docs label it experimental and ask you to review every change. Run it with `ng g @schematics/angular:refactor-jasmine-vitest`, once the project is already configured for Vitest. ## What it rewrites | Jasmine form | Rewritten to | |---|---| | `fit`, `fdescribe` | `it.only`, `describe.only` | | `xit`, `xdescribe` | `it.skip`, `describe.skip` | | `spyOn(obj, 'm')` | `vi.spyOn(obj, 'm')` | | `jasmine.createSpy()` | `vi.fn()` | | `jasmine.objectContaining(...)` | `expect.objectContaining(...)` | | `jasmine.any(Type)` | `expect.any(Type)` | | `fail(...)` | `vi.fail(...)` | Beyond the table it also adjusts expectation matchers to their Vitest equivalents, updates the setup and teardown hooks, and adds **TODO comments** where it cannot convert something automatically. By default it writes a summary report, `jasmine-vitest-<date>.md`, in the project root. ## Options worth knowing - `--project` picks the project in a multi-project workspace. - `--include` limits the run to one file or directory, which is how a large suite is refactored in reviewable slices. - `--file-suffix` handles suites named `.test.ts` instead of `.spec.ts`. - `--add-imports` adds explicit `vitest` imports. It defaults to `false` because the unit-test builder enables Vitest's **globals**, so `describe`, `it`, `expect` and `vi` need no import. - `--browser-mode` leaves `toHaveClass` assertions alone, because Vitest's browser mode provides that matcher; otherwise they are rewritten to an equivalent. - `--fake-async` converts `fakeAsync` tests to Vitest fake timers instead of leaving them on Zone.js. - `--verbose` logs every transformation. ## What it does not do 1. It does **not** install `vitest`, `jsdom` or any other dependency. 2. It does **not** change `angular.json` or move build options off the test target. 3. It does **not** delete `karma.conf.js` or `src/test.ts`. 4. It does **not** handle every complex or nested spy scenario; those need manual rewriting. 5. It does **not** prove semantic equivalence. Jasmine and Vitest spies differ in details, so passing tests after the rewrite still need a reviewer's eye. ## A worked slice For a large suite, one feature folder at a time keeps each change reviewable: 1. Run `ng g @schematics/angular:refactor-jasmine-vitest --include=src/app/profile --verbose`. 2. Read the generated `jasmine-vitest-<date>.md` report for that run. 3. Resolve every TODO the schematic left in the folder. 4. Run only those specs, for example with the unit-test builder's `include` or `filter` options, and compare the executed count with the Karma baseline for the folder. 5. Open a pull request for that folder alone, then move to the next one. ## Reviewing the output - **Search for the TODOs** it added and resolve each one; they mark code it did not convert. - **Check spy behaviour**: a bare Jasmine spy does not call through to the original method, and the conversion tries to keep that stub-by-default meaning. Confirm that tests which relied on call-through still exercise the real code. - **Look for accidental focus or skips**: a leftover `.only` makes the rest of a file silently not run. - **Compare counts** of executed tests before and after, not only the pass rate. - **Refactor in slices** with `--include`, so each pull request is small enough to review. The Angular testing APIs in those files (`TestBed`, fixtures, `HttpTestingController`, harnesses) are left as they are, because they do not depend on the runner.
- Why does the schematic not add import { describe, it, expect } from 'vitest' by default?The Angular unit-test builder turns on Vitest's globals option, so `describe`, `it`, `expect` and `vi` are available without imports, and the migration adds `vitest/globals` to the spec tsconfig types. `--add-imports` exists for projects that disabled globals in a custom Vitest configuration.
- After the refactor the suite is green, but 40 fewer tests ran. What do you look for?Leftover focus and skips first: a converted `fit` or `fdescribe` becomes `.only` and silently excludes the rest of its file. Then files the run did not include, for example a custom suffix the schematic or builder did not match, and TODO-marked tests someone commented out. Compare executed counts per file against the Karma baseline.
saying these in an interview costs you the question
- The schematic also switches the angular.json builder to Vitest
- It installs vitest and jsdom as part of the refactor
- Every spy scenario is converted, so no review is needed
- Vitest requires explicit imports, so --add-imports is mandatory
- It rewrites TestBed calls into Vitest equivalents