/** * Vitest Test Setup * Global test configuration and mocks */ import { vi } from 'vitest'; import '@testing-library/jest-dom'; // Provide a minimal `electron` mock so tests that transitively import // main-process code (logger, store, etc.) don't blow up when the Electron // binary is not present (e.g. CI with ELECTRON_SKIP_BINARY_DOWNLOAD=1). // Individual test files can override with their own vi.mock('electron', ...). vi.mock('electron', () => ({ app: { getPath: vi.fn().mockReturnValue('/tmp/clawx-test'), getVersion: vi.fn().mockReturnValue('0.0.0-test'), getName: vi.fn().mockReturnValue('clawx-test'), isPackaged: false, isReady: vi.fn().mockResolvedValue(true), on: vi.fn(), off: vi.fn(), quit: vi.fn(), whenReady: vi.fn().mockResolvedValue(undefined), }, BrowserWindow: vi.fn(), ipcMain: { on: vi.fn(), handle: vi.fn(), removeHandler: vi.fn() }, dialog: { showOpenDialog: vi.fn(), showMessageBox: vi.fn() }, shell: { openExternal: vi.fn() }, session: { defaultSession: { webRequest: { onBeforeSendHeaders: vi.fn() } } }, utilityProcess: {}, })); // Mock window.electron API const mockElectron = { ipcRenderer: { invoke: vi.fn(), on: vi.fn(), once: vi.fn(), off: vi.fn(), }, openExternal: vi.fn(), getPathForFile: vi.fn((file: File) => (file as File & { path?: string }).path ?? ''), platform: 'darwin', isDev: true, }; if (typeof window !== 'undefined') { Object.defineProperty(window, 'electron', { value: mockElectron, writable: true, }); } // Vitest/jsdom can expose an opaque-origin window where localStorage is absent. // The renderer stores use it for small UI caches, so provide the browser shape // expected by unit tests when the environment does not. if (typeof window !== 'undefined') { let needsLocalStorageMock: boolean; try { needsLocalStorageMock = !window.localStorage; } catch { needsLocalStorageMock = true; } if (needsLocalStorageMock) { const storage = new Map(); const localStorageMock: Storage = { get length() { return storage.size; }, clear: vi.fn(() => storage.clear()), getItem: vi.fn((key: string) => storage.get(key) ?? null), key: vi.fn((index: number) => Array.from(storage.keys())[index] ?? null), removeItem: vi.fn((key: string) => { storage.delete(key); }), setItem: vi.fn((key: string, value: string) => { storage.set(key, String(value)); }), }; Object.defineProperty(window, 'localStorage', { value: localStorageMock, configurable: true, }); Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, configurable: true, }); } } // Mock matchMedia if (typeof window !== 'undefined') { Object.defineProperty(window, 'matchMedia', { writable: true, value: vi.fn().mockImplementation((query) => ({ matches: false, media: query, onchange: null, addListener: vi.fn(), removeListener: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), dispatchEvent: vi.fn(), })), }); } // Reset mocks after each test afterEach(() => { vi.clearAllMocks(); });