UNPKG

@analogjs/vitest-angular

Version:

Vitest Builder for Angular

305 lines (214 loc) 8.09 kB
# @analogjs/vitest-angular A standalone builder for running tests with Vitest and Angular. ## Supporting Analog - Star the [GitHub Repo](https://github.com/analogjs/analog) - Join the [Discord](https://chat.analogjs.org) - Follow us on [Twitter](https://twitter.com/analogjs) - Become a [Sponsor](https://analogjs.org/docs/sponsoring) ## Installation Use your package manager of choice to install the necessary packages. With ng add: ```sh ng add @analogjs/vitest-angular ``` With npm: ```sh npm install @analogjs/vitest-angular vitest --save-dev ``` With pnpm: ```sh pnpm install -w @analogjs/vitest-angular vitest --dev ``` With Yarn: ```sh yarn install @analogjs/vitest-angular vitest --dev ``` ## Automated Setup Using a Schematic A schematic can be used to setup Vitest in an existing Angular project: Run the schematic to set up the Vite config, test configuration files, and update the test configuration. ```sh npx ng generate @analogjs/vitest-angular:setup --project [your-project-name] ``` ### Schematic Options | Option | Type | Default | Description | | ------------- | ------- | ------- | ----------------------------------------------------------- | | `project` | string | - | The name of the project to configure (required) | | `browserMode` | boolean | `false` | Configure Vitest to run tests in a browser using Playwright | To enable browser mode during setup: ```shell ng g @analogjs/vitest-angular:setup --project [your-project-name] --browserMode ``` This automatically installs Playwright dependencies and configures Vitest for browser testing. See [Setup for Running Tests in the Browser](#setup-for-running-tests-in-the-browser) for more details. If using browser mode, run `npx playwright install` after the schematic to ensure playwright is installed and configured. ## Manual Setup Vitest can be setup manually also using the steps below. ### Setup for Running Tests in Node To setup Vitest, create a `vite.config.mts` at the root of your project: ```ts /// <reference types="vitest" /> import { defineConfig } from 'vite'; import angular from '@analogjs/vite-plugin-angular'; export default defineConfig(({ mode }) => ({ plugins: [angular()], test: { globals: true, setupFiles: ['src/test-setup.ts'], environment: 'jsdom', include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], reporters: ['default'], }, })); ``` Next, define a `src/test-setup.ts` file to setup the `TestBed`: ### Zoneless setup As of Angular v21, `Zoneless` change detection is the default for new projects. Use the following setup: ```ts import '@angular/compiler'; import '@analogjs/vitest-angular/setup-snapshots'; import '@analogjs/vitest-angular/setup-serializers'; import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed'; setupTestBed(); ``` ### Zone.js setup If you are using `Zone.js` for change detection, import the `setup-zone` script. This script automatically includes support for setting up snapshot tests. ```ts import '@angular/compiler'; import '@analogjs/vitest-angular/setup-zone'; import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed'; setupTestBed({ zoneless: false, }); ``` ### Configuration Options The `setupTestBed()` function accepts an optional configuration object with the following properties: - `zoneless` (boolean): Whether to use zoneless change detection (default: `true`) - `providers` (`Type<any>[]`): Additional providers to include in the test environment (default: `[]`) - `teardown.destroyAfterEach` (boolean): Whether to destroy the test environment after each test. Set to `false` to keep the component rendered, allowing you to inspect its final state. (default: `true`) **Example with options:** ```ts setupTestBed({ zoneless: true, providers: [], teardown: { destroyAfterEach: false }, }); ``` Next, update the `test` target in the `angular.json` to use the `@analogjs/vitest-angular:test` builder: ```json { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "your-project": { "projectType": "application", "architect": { "test": { "builder": "@analogjs/vitest-angular:test" } } } } } ``` Lastly, add the `src/test-setup.ts` to `files` array in the `tsconfig.spec.json` in the root of your project, set the `target` to `es2022`, and update the `types`. ```json { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", "target": "es2022", "types": ["vitest/globals", "node"] }, "files": ["src/test-setup.ts"], "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] } ``` ## Running Tests To run unit tests, use the `test` command: ```shell npm run test ``` ```shell yarn test ``` ```shell pnpm test ``` > The `npx vitest` command can also be used directly. ## Snapshot Testing For snapshot testing you can use `toMatchSnapshot` from `expect` API. The provided snapshot setup also removes Angular-specific `_ng*` attributes and `<!--container-->` comments from DOM snapshots, which keeps diffs focused on the actual template output. The import of `setup-snapshots` and `setup-serializers` are complementary: - Use `setup-snapshots` to serialize Angular fixtures and component refs so Vitest snapshots print component markup instead of Angular testing internals. - Use `setup-serializers` to clean DOM snapshots by removing Angular runtime noise such as `_ngcontent-*`, `_nghost-*`, `ng-reflect-*`, generated ids and classes, and removes comments from DOM snapshots (e.g. `<!--container-->`). Below is a small example of how to write a snapshot test: ```ts // card.component.spec.ts import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CardComponent } from './card.component'; describe('CardComponent', () => { let fixture: ComponentFixture<CardComponent>; let component: CardComponent; beforeEach(() => TestBed.configureTestingModule({ imports: [CardComponent], }), ); beforeEach(() => { fixture = TestBed.createComponent(CardComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create the app', () => { expect(fixture).toMatchSnapshot(); }); }); ``` After you run the test, a `card.component.spec.ts.snap` file is created in the`__snapshots__` folder with the below content: ```ts // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`CardComponent > should create the app 1`] = ` <component-code> `; ``` The snapshots generated should be reviewed and added to version control. ## Using TypeScript Config Path Aliases If you are using `paths` in your `tsconfig.json`, support for those aliases can be added to the `vite.config.ts`. First, install the `vite-tsconfig-paths` package. With npm: ```shell npm install vite-tsconfig-paths --save-dev ``` With pnpm: ```shell pnpm install -w vite-tsconfig-paths --dev ``` With Yarn: ```shell yarn add vite-tsconfig-paths --dev ``` Next, add the plugin to the `plugins` array in the `vite.config.ts`. ```ts /// <reference types="vitest" /> import { defineConfig } from 'vite'; import angular from '@analogjs/vite-plugin-angular'; import viteTsConfigPaths from 'vite-tsconfig-paths'; export default defineConfig(({ mode }) => ({ // ...other config plugins: [angular(), viteTsConfigPaths()], })); ``` ### With Nx For Nx workspaces, import and use the `nxViteTsPaths` plugin from the `@nx/vite` package. ```ts /// <reference types="vitest" /> import { defineConfig } from 'vite'; import angular from '@analogjs/vite-plugin-angular'; import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig(({ mode }) => ({ plugins: [angular(), nxViteTsPaths()], })); ``` ## IDE Support Tests can also be run directly from your IDE using the Vitest [IDE integrations](https://vitest.dev/guide/ide) for VS Code or JetBrains IDEs.