import { vi } from "vitest"; export function createDeterministicClock(start = 0) { let current = start; return Object.freeze({ now: () => current, sleep: async (milliseconds: number, signal?: AbortSignal) => { if (signal?.aborted) throw new DOMException("aborted", "AbortError"); current += Math.max(0, milliseconds); }, advance(milliseconds: number) { current += Math.max(0, milliseconds); }, }); } export function createSeededRandom(seed = 1) { let state = seed >>> 0; return () => { state = (state * 1_664_525 + 1_013_904_223) >>> 0; return state / 0x1_0000_0000; }; } export function createControlledScheduler() { const callbacks: Array<() => void> = []; return Object.freeze({ callbacks, setTimeout: vi.fn((callback: () => void) => { callbacks.push(callback); return callbacks.length - 1; }), clearTimeout: vi.fn(), runNext() { callbacks.shift()?.(); }, }); } export function createRecordingStorage() { const values = new Map(); const operations: Array< Readonly<{ operation: "get" | "set" | "remove"; key: string }> > = []; const storage: Storage = { getItem(key) { operations.push({ operation: "get", key }); return values.get(key) ?? null; }, setItem(key, value) { operations.push({ operation: "set", key }); values.set(key, value); }, removeItem(key) { operations.push({ operation: "remove", key }); values.delete(key); }, clear() { values.clear(); }, key(index) { return [...values.keys()][index] ?? null; }, get length() { return values.size; }, }; return Object.freeze({ storage, operations, values }); }