DEV Community

Cover image for Faster testing with Angular and Vitest ⚡️
Brandon Roberts
Brandon Roberts

Posted on

Faster testing with Angular and Vitest ⚡️

In the Angular ecosystem, there are a few recommended tools used to run unit tests including Karma, Jasmine, and Jest. Karma and Jasmine have been the recommended tools for Angular projects out of the box, with official support for Jest underway.

In addition to those tools, a new testing framework has emerged named Vitest. Vitest is built on top of Vite and has many exciting features to keep improving the overall developer experience for writing tests. This post shows you how to set up Vitest in your existing Angular project.

Vitest Features

Vitest has many modern testing features that make it a great experience to run tests.

  • Jest-compatible API
  • Fast
  • ESM ready
  • TypeScript support out of the box
  • Mocks
  • Snapshot testing
  • And more ...

Check out the features page to see the full list.

While Jest does have experimental support for ESM, it's not a first-class feature and requires workarounds to support it correctly. Tomas Trajan wrote a very detailed blog post on all the scenarios to get Jest and ESM working for Angular tests.

Setup for Running tests in a Node environment

As Vitest is built on top of Vite, support for web frameworks can be done through plugins. AnalogJS provides a Vite plugin to enable using Vitest with any Angular application.

Setting up Vitest with an existing Angular project can be done in a couple of steps.

First, install the @analogjs/platform package.

npm install @analogjs/platform --save-dev
Enter fullscreen mode Exit fullscreen mode

Next, run the command with the name of your project:

ng g @analogjs/platform:setup-vitest --project [your-project-name]
Enter fullscreen mode Exit fullscreen mode

This is supported in both Angular CLI and Nx workspaces.

This automates a few steps:

  • Installs the necessary packages to run tests with Vitest.
  • Adds a vite.config.ts file to the project to configure Vitest.
  • Adds a src/test-setup.ts file to the project for setting up the TestBed environment.
  • Updates the test target configuration to use @analogjs/platform:vitest as the builder.
  • Updates the tsconfig.spec.json with the appropriate target and files settings.

You can also see steps for manual installation in the documentation.

After the command finishes, you're able to run tests the same way you did before with ng test, but now using Vitest as the testing framework.

ng test
Enter fullscreen mode Exit fullscreen mode

With Vitest, by default, tests are run in a node environment with simulated browser APIs using jsdom. If you're already using Jest-specific testing APIs, you can migrate most of them to Vitest with minimal effort.

Snapshot testing

Vitest also supports snapshot testing with the toMatchSnapshot() method.

import { TestBed } from '@angular/core/testing';

import { MyComponent } from './my.component';

describe('MyComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [MyComponent],
    }).compileComponents();
  });

  it('should match the snapshot', () => {
    const fixture = TestBed.createComponent(MyComponent);

    expect(fixture).toMatchSnapshot();
  });
});
Enter fullscreen mode Exit fullscreen mode

Setup for Running tests in the Browser

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

First, follow the steps for running tests in a node environment.

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

npm install @vitest/browser playwright --save-dev
Enter fullscreen mode Exit fullscreen mode

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}'],
    // Vitest browser config
    browser: {
      enabled: true,
      name: 'chromium',
      headless: false, // set to true in CI
      provider: 'playwright',
    },
  },
  define: {
    'import.meta.vitest': mode !== 'production',
  },
}));
Enter fullscreen mode Exit fullscreen mode

Run your tests

ng test
Enter fullscreen mode Exit fullscreen mode

This spins up a Chromium Browser to run your tests and can be run headless in your CI environments.

Vitest is a great addition to the testing frameworks available for Angular developers to use.

If you enjoyed this post, click the ❤️ so other people will see it. Follow me on Twitter/X and subscribe to my YouTube Channel for more content!

Top comments (16)

Collapse
 
jefftopia profile image
Jeff

Does your Angular application need to also be an Analog application to utilize the analogjs/vite-plugin-angular, or can any angular app use vitest with that plugin for testing?

Collapse
 
brandontroberts profile image
Brandon Roberts • Edited

Great question. Any Angular application can use the Vite plugin with Vitest for testing. It doesn't have to be an Analog application.

Collapse
 
codeofarmz profile image
codeOfArmz

That's great, but in this case - would it be possible to make a schematic for ng add?

Thread Thread
 
brandontroberts profile image
Brandon Roberts

Sure, its possible. It could do

ng add @analogjs/platform --project project-name
Enter fullscreen mode Exit fullscreen mode

And it could give you a prompt to setup Vitest support for you

Thread Thread
 
amosisaila profile image
Amos Isaila

In a normal Angular app do we have to install analog to be able to use vitest?

Thread Thread
 
brandontroberts profile image
Brandon Roberts

Currently, yes. There's no official support from the Angular team for Vitest. As previously commented, you can only use Analog for the testing integration if you prefer.

Thread Thread
 
amosisaila profile image
Amos Isaila

It won't increase my build?

Collapse
 
carniatto profile image
Mateus Carniatto

Hello Brandon, great content. Is there an option to use Cypress instead of Playwright?

Collapse
 
brandontroberts profile image
Brandon Roberts

Thanks Mateus. Currently, Cypress is not an option for browser testing. The list of currently supported options is here.

vitest.dev/guide/browser#cross-bro...

Collapse
 
andrs_vettori_145d6d61c3 profile image
Andrés Vettori • Edited

Hi, installed the NPM package without issues, but when trying to configure vitest with:

ng g @analogjs/platform:setup-vitest --project my-project-name

I get an error: Cannot read properties of undefined (reading 'root')

What I'm doing wrong? As "my-project-name" I'm using the value of the property "name" in the package.json file.

Thanks in advance,

Agv

Collapse
 
brandontroberts profile image
Brandon Roberts • Edited

You should use the name of your project from the angular.json file

{
  "projects": {
    "your-project-name-here": {..} 
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
timsar2 profile image
timsar2

How can I add vitest to nx multi app?
the command :
nx g @nx/angular:ng-add @analogjs/platform --project project-name
not working for me

Collapse
 
brandontroberts profile image
Brandon Roberts

The correct command after installing the package is

nx g @analogjs/platform:setup-vitest --project project-name
Enter fullscreen mode Exit fullscreen mode
Collapse
 
samkcfam_2b1ce78380ebb96f profile image
samkcfam

What about code coverage. How do you setup code coverage with ViteTest in Angular?

Collapse
 
aelbore profile image
Jay

Does this needs require rxjs version 7+?

Collapse
 
aelbore profile image
Jay • Edited

i just found out using jsdom and happy-dom it only works with rxjs 7+
using Playwright it works with rxjs 6.x

not sure if this is issue with analogjs or vite/vitest
with jsdom and happy-dom

Image description