How to Progressively Migrate to Vitest Browser Mode
In this recipe, you will find a step-by-step guide to progressively migrate your Angular tests to Vitest Browser Mode.
Vitest & Browser Mode are officially supported by Angular CLI starting from Angular v21.0.0 (Nov. 2025).
For older Angular versions or more advanced scenarios, you can use Angular Vite plugin by Analog.
Note that Nx added Angular Vitest support in Nx v20.1.0 (Nov. 28th 2024).
๐ฝ๏ธ Before You Startโ
๐๏ธ Browser Mode
The evolution of Angular browser testing and how to configure Vitest Browser Mode for both partial and full Playwright-powered testing.
1. Migrate to "Partial" Browser Modeโ
When using Vitest with the Angular CLI, the default behavior is to use an emulated environment. Either JSDOM or Happy DOM depending on the first dependency that is available.
To enable browser mode in Angular CLI, you have to update the browsers option to use the browser you want to use:
{
"test": {
"builder": "@angular/build:unit-test",
"options": {
"runner": "vitest",
"browsers": ["Chromium"]
}
}
}
You will then also have to add the required dependencies to your project.
npm install -D playwright vitest @vitest/browser-playwright
After enabling this, the tests will run in the browser. Angular CLI will automatically either use Playwright or WebdriverIO as the Vitest browser provider depending on which package is installed in your workspace.
At this stage, the tests are running in the browser but you are not leveraging the full power of the browser provider yet.
Cf. "Partial" Browser Mode.
2. [Optional] Migrate to "Full" Browser Mode with userEvent adapterโ
If you are already using the @testing-library/user-event library, you can easily enable the "Full" Browser Mode and features such as actionability checks.
Vitest provides a
userEventadapter that has the same API as@testing-library/user-eventbut is actually using the browser provider under the hood.
This adapter is meant to simplify the migration to "Full" Browser Mode.
To enable it, you just have to replace the import of @testing-library/user-event with vitest/browser and your tests will start interacting with the DOM through the browser provider:
import { expect, test } from 'vitest';
- import userEvent from '@testing-library/user-event';
+ import { userEvent } from 'vitest/browser';
test('turn on the stove', async () => {
TestBed.createComponent(Stove);
await userEvent.click(await screen.findByRole('button', { name: 'TURN ON' }));
await expect.poll(() => screen.getByRole('paragraph')).toHaveText('๐ฅ');
});
3. Migrate to "Full" Browser Mode with page APIโ
For a better testing experience, Vitest provides a page API that aligns with the Playwright API.\
You can switch to the page API by replacing DOM queries with the page API, and assertions with the expect.element API.
import { expect, test } from 'vitest';
import { userEvent } from 'vitest/browser';
test('turn on the stove', async () => {
TestBed.createComponent(Stove);
- await userEvent.click(await screen.findByRole('button', { name: 'TURN ON' }));
+ await page.getByRole('button', { name: 'TURN ON' }).click();
- await expect.poll(() => screen.getByRole('paragraph')).toHaveText('๐ฅ');
+ await expect.element(page.getByRole('paragraph')).toHaveText('๐ฅ');
});
The page API methods return a Locator object that does not need to be awaited.
The locator is not querying the DOM, it is the "recipe" of how to find that element in the DOM.
The DOM queries are only performed when:
- an action such as
clickis performed on the locator - an assertion is performed using
expect.elementon the locator
Thanks to this auto-waiting behavior, you will rarely have to worry about Angular testing APIs such as ComponentFixture#whenStable, nor the differences between Testing Library's getBy vs. queryBy vs. findBy etc... anymore.
Once you opt-in to Browser Mode by importing vitest/browsers, you will not be able to run these tests in an emulated environment.
Otherwise, you will get an error like this:
Error: vitest/browser can be imported only inside the Browser Mode.
4. Extending the Locator API with provider-specific featuresโ
Usually, when using a simple Vitest config file with plugins such as Analog's Vite plugin approach, Vitest automatically augments the Locator API with provider-specific features and options.
When using the Angular CLI, you will have to manually augment the types yourself. Cf. https://github.com/angular/angular-cli/issues/31656.
You can augment the Locator API by adding the provider's ambient typings in the types array of the tsconfig.spec.json file as such:
{
"compilerOptions": {
"types": [
...,
+ "@vitest/browser-playwright"
]
}
}
Want to go deeper? Join a full live workshopโ
Source Codeโ
๐ปย Angular Testing using a FakeAdditional Resourcesโ
- ๐ Locator API Docs
- ๐ Assertion API Docs
