Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vitest Highlights in Angular

Vitest Highlights in Angular

Vitest is finally supported out-of-the-box by the Angular CLI. But simply switching the test runner is just the beginning.
In this talk, we dive into the specific highlights that make the switch irresistible:

Full Browser Mode: Real rendering with built-in "auto-waiting." Say goodbye to manual detectChanges() or whenStable().
Better Asynchrony: Using modern tools like expect.poll and standard fake timers instead of the legacy waitForAsync() and fakeAsync().
Going All-In: While the CLI provides the foundation, we will look at Analog.js—the option that truly unlocks the full feature set.

Avatar for Rainer Hahnekamp

Rainer Hahnekamp

January 26, 2026
Tweet

More Decks by Rainer Hahnekamp

Other Decks in Technology

Transcript

  1. Vitest Highlights The New Era of Angular Testing Angular London

    Meetup, 21. January 2026 RainerHahnekamp
  2. About Me... https://www.youtube.com/ @RainerHahnekamp https://www.ng-news.com • Rainer Hahnekamp • ANGULARarchitects.io

    • NgRx Core Team • Developer / Trainer / Speaker @RainerHahnekamp Open Source Projects NgRx Toolkit Testronaut NgRx Sheriff
  3. RainerHahnekamp Agenda • Full Browser Mode • Handling Asynchronous Tasks

    • All-In with Analog • Migrating from Jasmine/Jest
  4. RainerHahnekamp Browser Mode in a Nutshell • Advantages of Testing

    Library ◦ Automatically deals with whenStable() and detectChanges() ◦ User Actions check elements ◦ Simple DOM queries via A11y selectors • Power of E2E (Playwright) ◦ Better asynchronous support because of real waiting ◦ Advanced User Actions Checks (Auto-Wait) ◦ Powerful locator pattern for Querying
  5. RainerHahnekamp Overview - Full Browser Mode • Proxies DOM Query

    and Actions to Playwright • Uses Locator pattern ◦ import { page } from 'vitest/browser'; • Upgraded Version of userEvents ◦ import { userEvent } from 'vitest/browser'; • Enhanced Matchers ◦ await expect.element(page.getByText("Address not found")).toBeVisible();
  6. RainerHahnekamp Angular-based Approaches • waitForAsync: automatic done callback • fakeAsync:

    transforms async to sync task ◦ flushMicrotasks: run all microtasks ◦ tick: move forward in time ◦ flush: run all asynchronous tasks (skips periodic timers) Doesn't work with zoneless
  7. RainerHahnekamp Fake Timers • Setup & Teardown ◦ vitest.useFakeTimers(); ◦

    vitest.useRealTimers(); • vitest.runAllTimersAsync() ◦ Runs all asynchronous triggered now and in the future ◦ Dangerous for intervals, etc. • vitest.runOnlyPendingTimersAsync(); ◦ Runs timers known at the time of execution ◦ Safer than runAllTimers() • vitest.advanceTimersByTimeAsync([time]); ◦ Like tick() Use async() to cover Promises
  8. RainerHahnekamp Why Browser? ✅ Real Browser Behavior • Rendering •

    User Events • Timings (Signals) • New Technologies (Shadow DOM, Hydration) ✅ Switch to "UI is the API" ✅ Performant Headless Browsers ✅ Visualization (DX)
  9. RainerHahnekamp Migrating to Vitest • Jest ◦ 100% Compatible •

    Jasmine ◦ Different Mocking API ◦ Different Timing API • Experimental Migrator available • No fakeAsync() or waitForAsync() ◦ Go zoneless ◦ Rewrite Tests with fakeTimers, expect.poll, etc. ◦ Rely on whenStable and PendingTasks