/** * 测试工具函数 * 提供测试中常用的辅助函数 */ import { vi } from 'vitest'; // 等待指定时间(和await一起用) export function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } // 等待下一个事件循环(和await一起用) export function nextTick(): Promise { return new Promise(resolve => setTimeout(resolve, 0)); } // 创建一个可控制的Promise(将promise的控制权提取到外部) export function createControlledPromise() { // 用闭包把内部函数暴露到外部 let resolve: (value: T) => void; let reject: (reason?: any) => void; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve: resolve!, reject: reject! }; } // 模拟localStorage(闭包) export function createMockLocalStorage() { let store: Record = {}; return { getItem: vi.fn((key: string) => store[key] || null), setItem: vi.fn((key: string, value: string) => { store[key] = value; }), removeItem: vi.fn((key: string) => { delete store[key]; }), clear: vi.fn(() => { store = {}; }), get length() { return Object.keys(store).length; }, key: vi.fn((index: number) => { const keys = Object.keys(store); return keys[index] || null; }) }; } // 模拟sessionStorage export function createMockSessionStorage() { return createMockLocalStorage(); } // 创建一个可读写的流 // 创建一个可读写的事件流 export function createMockStream() { const listeners: Record = {}; // 先创建对象引用 const stream = { on: vi.fn((event: string, callback: Function) => { if (!listeners[event]) { listeners[event] = []; } listeners[event].push(callback); return stream; // 使用对象引用而不是 this }), emit: vi.fn((event: string, ...args: any[]) => { if (listeners[event]) { listeners[event].forEach(callback => callback(...args)); } return stream; // 使用对象引用 }), once: vi.fn((event: string, callback: Function) => { const onceWrapper = (...args: any[]) => { callback(...args); // 移除监听器 if (listeners[event]) { listeners[event] = listeners[event].filter(cb => cb !== onceWrapper); } }; return stream.on(event, onceWrapper); // 使用对象引用 }), removeListener: vi.fn((event: string, callback: Function) => { if (listeners[event]) { listeners[event] = listeners[event].filter(cb => cb !== callback); } return stream; // 使用对象引用 }), removeAllListeners: vi.fn((event?: string) => { if (event) { delete listeners[event]; } else { Object.keys(listeners).forEach(key => { delete listeners[key]; }); } return stream; // 使用对象引用 }) }; return stream; } // 模拟IntersectionObserver export function createMockIntersectionObserver() { const callbacks: Function[] = []; return { observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn(), root: null, rootMargin: '', thresholds: [], constructor: vi.fn((callback: Function) => { callbacks.push(callback); return { observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn() }; }) }; } // 模拟ResizeObserver export function createMockResizeObserver() { const callbacks: Function[] = []; return { observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn(), constructor: vi.fn((callback: Function) => { callbacks.push(callback); return { observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn() }; }) }; }