Accéder au contenu principal

Using Vitest with An Angular Project

Vitest can be added to any existing Angular project with a few steps.

Automated Setup Using a Schematic/Generator

Vitest can be installed and setup using a schematic/generator for Angular CLI or Nx workspaces.

First, install the @analogjs/platform package:

npm install @analogjs/platform --save-dev

Next, run the schematic to set up the Vite config, test configuration files, and update the test configuration.

ng g @analogjs/platform:setup-vitest --project [your-project-name]

Next, go to running tests

Manual Installation

To add Vitest manually, install the necessary packages:

npm install @analogjs/vite-plugin-angular @analogjs/vitest-angular jsdom --save-dev

Setup for Running Tests for Node

To setup Vitest, create a vite.config.ts at the root of your project:

/// <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'],
},
define: {
'import.meta.vitest': mode !== 'production',
},
}));

Next, define a src/test-setup.ts file to setup the TestBed:

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.

import '@analogjs/vitest-angular/setup-zone';

import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { getTestBed } from '@angular/core/testing';

getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);

Zoneless setup

If you are using Zoneless change detection, only import the setup-snapshots script.

import '@analogjs/vitest-angular/setup-snapshots';

import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { getTestBed } from '@angular/core/testing';

getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);

Next, update the test target in the angular.json to use the @analogjs/vitest-angular:test builder:

{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"your-project": {
"projectType": "application",
"architect": {
"build": ...,
"serve": ...,
"extract-i18n": ...,
"test": {
"builder": "@analogjs/vitest-angular:test"
}
}
}
}
}

You can also add a new target and name it vitest to run alongside your test target.

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 es2016, and update the types.

{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"target": "es2016",
"types": ["vitest/globals", "node"]
},
"files": ["src/test-setup.ts"],
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

Next, go to running tests

Setup for Running Tests in the Browser

If you prefer to run your tests in a browser, Vitest has experimental support for browser testing also.

First, follow the steps for running tests in node.

Then, install the necessary packages for running tests in the browser:

npm install @vitest/browser playwright --save-dev

Update the test object in the vite.config.ts.

  • Remove the environment: 'jsdom' property.
  • Add a browser config for Vitest.
/// <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'],
// Vitest browser config
browser: {
enabled: true,
name: 'chromium',
headless: false, // set to true in CI
provider: 'playwright',
},
},
define: {
'import.meta.vitest': mode !== 'production',
},
}));

Next, add the @angular/compiler import to the src/test-setup.ts file.

import '@angular/compiler';
import '@analogjs/vitest-angular/setup-zone';

import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { getTestBed } from '@angular/core/testing';

getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);

Running Tests

To run unit tests, use the test command:

npm run test

The npx vitest command can also be used directly.

Snapshot Testing

For snapshot testing you can use toMatchSnapshot from expect API.

Below is a small example of how to write a snapshot test:

// 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:

// 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.

With Angular CLI

First, install the vite-tsconfig-paths package.

npm install vite-tsconfig-paths --save-dev

Next, add the plugin to the plugins array in the vite.config.ts with the root set as the relative path to the root of the project.

/// <reference types="vitest" />
import { defineConfig } from 'vite';

import angular from '@analogjs/vite-plugin-angular';
import viteTsConfigPaths from 'vite-tsconfig-paths';

export default defineConfig(({ mode }) => ({
plugins: [angular(), viteTsConfigPaths()],
}));

With Nx

For Nx workspaces, import and use the nxViteTsPaths plugin from the @nx/vite package.

/// <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()],
}));