|
| 1 | +# Migrating from Karma to Vitest |
| 2 | + |
| 3 | +The Angular CLI uses [Vitest](https://vitest.dev/) as the default unit test runner for new projects. This guide provides instructions for migrating an existing project from Karma and Jasmine to Vitest. |
| 4 | + |
| 5 | +IMPORTANT: Migrating an existing project to Vitest is considered experimental. This process also requires the use of the `application` build system, which is the default for all newly created projects. |
| 6 | + |
| 7 | +## Manual migration steps |
| 8 | + |
| 9 | +Before using the automated refactoring schematic, you must manually update your project to use the Vitest test runner. |
| 10 | + |
| 11 | +### 1. Install dependencies |
| 12 | + |
| 13 | +Install `vitest` and a DOM emulation library. While browser testing is still possible (see [step 5](#5-configure-browser-mode-optional)), Vitest uses a DOM emulation library by default to simulate a browser environment within Node.js for faster test execution. The CLI automatically detects and uses `happy-dom` if it's installed; otherwise, it falls back to `jsdom`. You must have one of these packages installed. |
| 14 | + |
| 15 | +<docs-tabs> |
| 16 | + <docs-tab title="npm"> |
| 17 | + <docs-code language="bash"> |
| 18 | +npm install vitest jsdom --save-dev |
| 19 | +# OR for happy-dom |
| 20 | +npm install vitest happy-dom --save-dev |
| 21 | + </docs-code> |
| 22 | + </docs-tab> |
| 23 | + <docs-tab title="yarn"> |
| 24 | + <docs-code language="bash"> |
| 25 | +yarn add vitest jsdom --dev |
| 26 | +# OR for happy-dom |
| 27 | +yarn add vitest happy-dom --dev |
| 28 | + </docs-code> |
| 29 | + </docs-tab> |
| 30 | + <docs-tab title="pnpm"> |
| 31 | + <docs-code language="bash"> |
| 32 | +pnpm add vitest jsdom --save-dev |
| 33 | +# OR for happy-dom |
| 34 | +pnpm add vitest happy-dom --save-dev |
| 35 | + </docs-code> |
| 36 | + </docs-tab> |
| 37 | +</docs-tabs> |
| 38 | + |
| 39 | +### 2. Update `angular.json` |
| 40 | + |
| 41 | +In your `angular.json` file, find the `test` target for your project and change the `builder` to `@angular/build:unit-test`. |
| 42 | + |
| 43 | +```json |
| 44 | +{ |
| 45 | + "projects": { |
| 46 | + "your-project-name": { |
| 47 | + "architect": { |
| 48 | + "test": { |
| 49 | + "builder": "@angular/build:unit-test" |
| 50 | + } |
| 51 | + } |
| 52 | + } |
| 53 | + } |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +The `unit-test` builder defaults to `"tsConfig": "tsconfig.spec.json"` and `"buildTarget": "::development"`. You can explicitly set these options if your project requires different values. For example, if the `development` build configuration is missing or you need different options for testing, you can create and use a `testing` or similarly named build configuration for `buildTarget`. |
| 58 | + |
| 59 | +The `@angular/build:karma` builder previously allowed build options (like `polyfills`, `assets`, or `styles`) to be configured directly within the `test` target. The new `@angular/build:unit-test` builder does not support this. If your test-specific build options differ from your existing `development` build configuration, you must move them to a dedicated build target configuration. If your test build options already match your `development` build configuration, no action is needed. |
| 60 | + |
| 61 | +### 3. Handle custom `karma.conf.js` configurations |
| 62 | + |
| 63 | +Custom configurations in `karma.conf.js` are not automatically migrated. Before deleting your `karma.conf.js` file, review it for any custom settings that need to be migrated. |
| 64 | + |
| 65 | +Many Karma options have equivalents in Vitest that can be set in a custom Vitest configuration file (e.g., `vitest.config.ts`) and linked to your `angular.json` via the `runnerConfig` option. |
| 66 | + |
| 67 | +Common migration paths include: |
| 68 | + |
| 69 | +- **Reporters**: Karma reporters must be replaced with Vitest-compatible reporters. These can often be configured directly in your `angular.json` under the `test.options.reporters` property. For more advanced configurations, use a custom `vitest.config.ts` file. |
| 70 | +- **Plugins**: Karma plugins may have Vitest equivalents that you will need to find and install. Note that code coverage is a first-class feature in the Angular CLI and can be enabled with `ng test --coverage`. |
| 71 | +- **Custom Browser Launchers**: These are replaced by the `browsers` option in `angular.json` and the installation of a browser provider like `@vitest/browser-playwright`. |
| 72 | + |
| 73 | +For other settings, consult the official [Vitest documentation](https://vitest.dev/config/). |
| 74 | + |
| 75 | +### 4. Remove Karma and `test.ts` files |
| 76 | + |
| 77 | +You can now delete `karma.conf.js` and `src/test.ts` from your project and uninstall the Karma-related packages. The following commands are based on the packages installed in a new Angular CLI project; your project may have other Karma-related packages to remove. |
| 78 | + |
| 79 | +<docs-tabs> |
| 80 | + <docs-tab title="npm"> |
| 81 | + <docs-code language="bash"> |
| 82 | +npm uninstall karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter |
| 83 | + </docs-code> |
| 84 | + </docs-tab> |
| 85 | + <docs-tab title="yarn"> |
| 86 | + <docs-code language="bash"> |
| 87 | +yarn remove karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter |
| 88 | + </docs-code> |
| 89 | + </docs-tab> |
| 90 | + <docs-tab title="pnpm"> |
| 91 | + <docs-code language="bash"> |
| 92 | +pnpm remove karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter |
| 93 | + </docs-code> |
| 94 | + </docs-tab> |
| 95 | +</docs-tabs> |
| 96 | + |
| 97 | +### 5. Configure browser mode (optional) |
| 98 | + |
| 99 | +If you need to run tests in a real browser, you must install a browser provider and configure your `angular.json`. |
| 100 | + |
| 101 | +**Install a browser provider:** |
| 102 | + |
| 103 | +<docs-tabs> |
| 104 | + <docs-tab title="npm"> |
| 105 | + <docs-code language="bash"> |
| 106 | +npm install -D @vitest/browser-playwright |
| 107 | +# OR for WebdriverIO |
| 108 | +npm install -D @vitest/browser-webdriverio |
| 109 | + </docs-code> |
| 110 | + </docs-tab> |
| 111 | + <docs-tab title="yarn"> |
| 112 | + <docs-code language="bash"> |
| 113 | +yarn add -D @vitest/browser-playwright |
| 114 | +# OR for WebdriverIO |
| 115 | +yarn add -D @vitest/browser-webdriverio |
| 116 | + </docs-code> |
| 117 | + </docs-tab> |
| 118 | + <docs-tab title="pnpm"> |
| 119 | + <docs-code language="bash"> |
| 120 | +pnpm add -D @vitest/browser-playwright |
| 121 | +# OR for WebdriverIO |
| 122 | +pnpm add -D @vitest/browser-webdriverio |
| 123 | + </docs-code> |
| 124 | + </docs-tab> |
| 125 | +</docs-tabs> |
| 126 | + |
| 127 | +**Update `angular.json` for browser mode:** |
| 128 | + |
| 129 | +Add the `browsers` option to your `test` target's options. The browser name depends on the provider you installed (e.g., `chromium` for Playwright, `chrome` for WebdriverIO). |
| 130 | + |
| 131 | +```json |
| 132 | +{ |
| 133 | + "projects": { |
| 134 | + "your-project-name": { |
| 135 | + "architect": { |
| 136 | + "test": { |
| 137 | + "builder": "@angular/build:unit-test", |
| 138 | + "options": { |
| 139 | + "browsers": ["chromium"] |
| 140 | + } |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + } |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +Headless mode is enabled automatically if the `CI` environment variable is set or if a browser name includes "Headless" (e.g., `ChromeHeadless`). Otherwise, tests will run in a headed browser. |
| 149 | + |
| 150 | +## Automated test refactoring with schematics |
| 151 | + |
| 152 | +IMPORTANT: The `refactor-jasmine-vitest` schematic is experimental and may not cover all possible test patterns. Always review the changes made by the schematic. |
| 153 | + |
| 154 | +The Angular CLI provides the `refactor-jasmine-vitest` schematic to automatically refactor your Jasmine tests to use Vitest. |
| 155 | + |
| 156 | +### Overview |
| 157 | + |
| 158 | +The schematic automates the following transformations in your test files (`.spec.ts`): |
| 159 | + |
| 160 | +- Converts `fit` and `fdescribe` to `it.only` and `describe.only`. |
| 161 | +- Converts `xit` and `xdescribe` to `it.skip` and `describe.skip`. |
| 162 | +- Converts `spyOn` calls to the equivalent `vi.spyOn`. |
| 163 | +- Replaces `jasmine.objectContaining` with `expect.objectContaining`. |
| 164 | +- Replaces `jasmine.any` with `expect.any`. |
| 165 | +- Replaces `jasmine.createSpy` with `vi.fn`. |
| 166 | +- Updates `beforeAll`, `beforeEach`, `afterAll`, and `afterEach` to their Vitest equivalents. |
| 167 | +- Converts `fail()` to Vitest's `vi.fail()`. |
| 168 | +- Adjusts expectations to match Vitest APIs |
| 169 | +- Adds TODO comments for code that cannot be automatically converted |
| 170 | + |
| 171 | +The schematic **does not** perform the following actions: |
| 172 | + |
| 173 | +- It does not install `vitest` or other related dependencies. |
| 174 | +- It does not change your `angular.json` to use the Vitest builder or migrate any build options (like `polyfills` or `styles`) from the `test` target. |
| 175 | +- It does not remove `karma.conf.js` or `test.ts` files. |
| 176 | +- It does not handle complex or nested spy scenarios, which may require manual refactoring. |
| 177 | + |
| 178 | +### Running the schematic |
| 179 | + |
| 180 | +Once your project is configured for Vitest, you can run the schematic to refactor your test files. |
| 181 | + |
| 182 | +To refactor **all** test files in your default project, run: |
| 183 | + |
| 184 | +```bash |
| 185 | +ng g @schematics/angular:refactor-jasmine-vitest |
| 186 | +``` |
| 187 | + |
| 188 | +### Options |
| 189 | + |
| 190 | +You can use the following options to customize the schematic's behavior: |
| 191 | + |
| 192 | +| Option | Description | |
| 193 | +| :---------------------- | :-------------------------------------------------------------------------------------------------------------------- | |
| 194 | +| `--project <name>` | Specify the project to refactor in a multi-project workspace. <br> Example: `--project=my-lib` | |
| 195 | +| `--include <path>` | Refactor only a specific file or directory. <br> Example: `--include=src/app/app.component.spec.ts` | |
| 196 | +| `--fileSuffix <suffix>` | Specify a different file suffix for test files. <br> Example: `--fileSuffix=.test.ts` | |
| 197 | +| `--addImports` | Add explicit `vitest` imports if you have disabled globals in your Vitest configuration. <br> Example: `--addImports` | |
| 198 | +| `--verbose` | See detailed logging of all transformations applied. <br> Example: `--verbose` | |
| 199 | + |
| 200 | +### After migrating |
| 201 | + |
| 202 | +After the schematic completes, it's a good practice to: |
| 203 | + |
| 204 | +1. **Run your tests**: Execute `ng test` to ensure that all tests still pass after the refactoring. |
| 205 | +2. **Review the changes**: Look over the changes made by the schematic, paying close attention to any complex tests, especially those with intricate spies or mocks, as they may require further manual adjustments. |
| 206 | + |
| 207 | +The `ng test` command builds the application in _watch mode_ and launches the configured runner. Watch mode is enabled by default when using an interactive terminal and not running on CI. |
| 208 | + |
| 209 | +## Configuration |
| 210 | + |
| 211 | +The Angular CLI takes care of the Vitest configuration for you, constructing the full configuration in memory based on options in `angular.json`. |
| 212 | + |
| 213 | +### Custom Vitest configuration |
| 214 | + |
| 215 | +IMPORTANT: While using a custom configuration enables advanced options, the Angular team does not provide direct support for the specific contents of the configuration file or for any third-party plugins used within it. The CLI will also override certain properties (`test.projects`, `test.include`) to ensure proper operation. |
| 216 | + |
| 217 | +You can provide a custom Vitest configuration file to override the default settings. For a full list of available options, see the official [Vitest documentation](https://vitest.dev/config/). |
| 218 | + |
| 219 | +**1. Direct path:** |
| 220 | +Provide a direct path to a Vitest configuration file in your `angular.json`: |
| 221 | + |
| 222 | +```json |
| 223 | +{ |
| 224 | + "projects": { |
| 225 | + "your-project-name": { |
| 226 | + "architect": { |
| 227 | + "test": { |
| 228 | + "builder": "@angular/build:unit-test", |
| 229 | + "options": { "runnerConfig": "vitest.config.ts" } |
| 230 | + } |
| 231 | + } |
| 232 | + } |
| 233 | + } |
| 234 | +} |
| 235 | +``` |
| 236 | + |
| 237 | +**2. Automatic search for base configuration:** |
| 238 | +If you set `runnerConfig` to `true`, the builder will automatically search for a shared `vitest-base.config.*` file in your project and workspace roots. |
| 239 | + |
| 240 | +## Bug reports |
| 241 | + |
| 242 | +Report issues and feature requests on [GitHub](https://github.com/angular/angular-cli/issues). |
| 243 | + |
| 244 | +Please provide a minimal reproduction where possible to aid the team in addressing issues. |
0 commit comments