138 lines
3.6 KiB
TypeScript
138 lines
3.6 KiB
TypeScript
|
|
/**
|
||
|
|
* Vitest Test Setup
|
||
|
|
*
|
||
|
|
* This file runs before each test file to set up the testing environment.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/// <reference types="vitest/globals" />
|
||
|
|
|
||
|
|
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();
|
||
|
|
});
|