/** * Vitest Test Setup * * This file runs before each test file to set up the testing environment. */ /// import '@testing-library/jest-dom'; import { vi, beforeAll, afterAll, afterEach } from 'vitest'; // Type for global context declare const global: typeof globalThis; // ============================================================================ // Mock Browser APIs // ============================================================================ // Mock ResizeObserver (used by ReactFlow) global.ResizeObserver = vi.fn().mockImplementation(() => ({ observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn(), })); // Mock IntersectionObserver global.IntersectionObserver = vi.fn().mockImplementation(() => ({ observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn(), })); // Mock matchMedia Object.defineProperty(window, 'matchMedia', { writable: true, value: vi.fn().mockImplementation((query: string) => ({ matches: false, media: query, onchange: null, addListener: vi.fn(), removeListener: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), dispatchEvent: vi.fn(), })), }); // Mock scrollTo Element.prototype.scrollTo = vi.fn(); window.scrollTo = vi.fn(); // Mock fetch for API calls global.fetch = vi.fn(); // ============================================================================ // Mock localStorage // ============================================================================ const localStorageMock = { getItem: vi.fn(), setItem: vi.fn(), removeItem: vi.fn(), clear: vi.fn(), length: 0, key: vi.fn(), }; Object.defineProperty(window, 'localStorage', { value: localStorageMock }); // ============================================================================ // Mock WebSocket // ============================================================================ class MockWebSocket { static readonly CONNECTING = 0; static readonly OPEN = 1; static readonly CLOSING = 2; static readonly CLOSED = 3; readonly CONNECTING = 0; readonly OPEN = 1; readonly CLOSING = 2; readonly CLOSED = 3; url: string; readyState: number = MockWebSocket.CONNECTING; onopen: ((event: Event) => void) | null = null; onclose: ((event: CloseEvent) => void) | null = null; onmessage: ((event: MessageEvent) => void) | null = null; onerror: ((event: Event) => void) | null = null; constructor(url: string) { this.url = url; // Simulate connection after a tick setTimeout(() => { this.readyState = MockWebSocket.OPEN; this.onopen?.(new Event('open')); }, 0); } send = vi.fn(); close = vi.fn(() => { this.readyState = MockWebSocket.CLOSED; this.onclose?.(new CloseEvent('close')); }); } global.WebSocket = MockWebSocket as any; // ============================================================================ // Console Suppression (optional) // ============================================================================ // Suppress console.error for expected test warnings const originalError = console.error; beforeAll(() => { console.error = (...args: any[]) => { // Suppress React act() warnings if (typeof args[0] === 'string' && args[0].includes('Warning: An update to')) { return; } originalError.call(console, ...args); }; }); afterAll(() => { console.error = originalError; }); // ============================================================================ // Cleanup // ============================================================================ afterEach(() => { vi.clearAllMocks(); localStorageMock.getItem.mockReset(); localStorageMock.setItem.mockReset(); });