brackt/app/test/setup.ts
Claude 15097ddcf8
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 2m53s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Successful in 1m29s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
Fix flaky test timeouts: synchronous requestAnimationFrame in test setup
Radix UI and @floating-ui call requestAnimationFrame for layout/positioning
on every render — Popovers, DropdownMenus, Checkboxes, etc.  In jsdom those
callbacks are deferred outside the current act() boundary, leaving pending
state updates that keep the act() settlement loop running until Vitest's
5000ms hard timeout kills the test.  Under load (full suite) there is no
slack to absorb the deferral.

Overriding requestAnimationFrame/cancelAnimationFrame with synchronous
no-ops in the global test setup ensures every Radix UI callback completes
inside the current act() cycle.  This fixes the whole class of
Radix-UI-induced flaky timeouts without touching individual test files.

https://claude.ai/code/session_012ACmUs2vAwEF9jZu7Guos2
2026-06-10 04:15:03 +00:00

53 lines
1.6 KiB
TypeScript

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();
});
// Mock environment variables
process.env.NODE_ENV = 'test';
// jsdom does not implement scrollTo on elements
HTMLElement.prototype.scrollTo = vi.fn();
// Mock BetterAuth
vi.mock('~/lib/auth.server', () => ({
auth: {
api: {
getSession: vi.fn(() => Promise.resolve({
user: { id: 'test-user-id', email: 'test@example.com', name: 'Test User' },
session: { userId: 'test-user-id' },
})),
},
},
}));
// Mock database context
vi.mock('~/database/context', () => ({
database: vi.fn(() => ({
query: {},
insert: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
select: vi.fn(),
})),
}));