diff --git a/app/test/setup.ts b/app/test/setup.ts index 255906e..f39c595 100644 --- a/app/test/setup.ts +++ b/app/test/setup.ts @@ -2,6 +2,22 @@ import '@testing-library/jest-dom'; import { cleanup } from '@testing-library/react'; import { afterEach, vi } from 'vitest'; +// Radix UI / @floating-ui calls requestAnimationFrame for layout and +// positioning on every render (Popover, DropdownMenu, Checkbox focus rings, +// etc.). In jsdom those callbacks are deferred to a future tick, landing +// outside the current act() boundary. React queues the resulting state +// updates, which schedule more microtasks, and the act() settlement loop +// keeps running until Vitest's 5000ms hard timeout kills the test. +// +// Making rAF synchronous keeps every callback inside the current act() cycle +// so there are no pending tasks when the test finishes. This fixes the whole +// class of flaky timeouts without touching individual test files. +global.requestAnimationFrame = (cb: FrameRequestCallback): number => { + cb(performance.now()); + return 0; +}; +global.cancelAnimationFrame = (_id: number): void => {}; + // Cleanup after each test afterEach(() => { cleanup();