Slide 1

Slide 1 text

Vitest Highlights The New Era of Angular Testing Angular London Meetup, 21. January 2026 RainerHahnekamp

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

RainerHahnekamp Agenda ● Full Browser Mode ● Handling Asynchronous Tasks ● All-In with Analog ● Migrating from Jasmine/Jest

Slide 4

Slide 4 text

RainerHahnekamp Full-Browser Mode

Slide 5

Slide 5 text

RainerHahnekamp Browser Mode Delegates DOM Interaction Common API

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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();

Slide 8

Slide 8 text

RainerHahnekamp Handling Asynchronous Tasks

Slide 9

Slide 9 text

RainerHahnekamp 👑 expect.poll() 👑

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

RainerHahnekamp All-In with Analog.js

Slide 13

Slide 13 text

Build Execution Vite-Powered Build with Vitest Use Case Framework-specific Vite Plugins

Slide 14

Slide 14 text

Build Execution Angular Build with Vitest Use Case

Slide 15

Slide 15 text

Build Execution Vite-Powered Build with Vitest Use Case Angular as Vite Plugin

Slide 16

Slide 16 text

RainerHahnekamp "All-In" Features ● VSCode Support ● All Extensions ● Trace Viewer Support ● Debugging ● …

Slide 17

Slide 17 text

RainerHahnekamp Migrating to Vitest

Slide 18

Slide 18 text

RainerHahnekamp Why Vitest???

Slide 19

Slide 19 text

RainerHahnekamp A little bit of History Browser Browser Emulated Browser (jsdom)

Slide 20

Slide 20 text

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)

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

RainerHahnekamp Have we reached perfection?

Slide 24

Slide 24 text

RainerHahnekamp testronaut.dev Stay tuned…

Slide 25

Slide 25 text

RainerHahnekamp https://www.angulararchitects.io/en/training/ professional-angular-testing-playwright-edition/ Related Workshops