ng new writes a project with no zone.js,

so the ticks never get to run.

fakeAsync + tick  FAILS TO COLLECT
// nothing else to set up
it('debounces', fakeAsync(() => {
  box.query.setValue('ang');
  tick(299);
  expect(search).not.toHaveBeenCalled();
  tick(1);
  expect(search).toHaveBeenCalledTimes(1);
}));
NG TEST
Error: zone-testing.js is needed for the
fakeAsync() test helper but could not be found.

 Test Files  1 failed (1)
      Tests  no tests
Vitest fake timers  PASSES
// vi.useFakeTimers() in beforeEach, real ones in afterEach
it('debounces', async () => {
  box.query.setValue('ang');
  await vi.advanceTimersByTimeAsync(299);
  expect(search).not.toHaveBeenCalled();
  await vi.advanceTimersByTimeAsync(1);
  expect(search).toHaveBeenCalledTimes(1);
});
NG TEST
 Test Files  3 passed (3)
      Tests  17 passed (17)
   Duration  860ms
the trap after the rewrite zoneless change detection schedules its render on a setTimeout racing a requestAnimationFrame, and the fake clock fakes both, so fixture.whenStable() needs the clock moved past the debounce, not up to it
Angular 22.2.0 · Vitest 5.0.2 · @angular/build:unit-test · jsdom 30.1.1 · both test bodies and both run summaries copied from the demo
gdhami.net