import { afterEach, describe, expect, it, vi } from 'vitest'; const createDeferred = () => { const { promise, reject, resolve } = Promise.withResolvers(); return { promise, reject, resolve }; }; const loadWeiboUtils = async ({ pageReady = Promise.resolve() } = {}) => { vi.resetModules(); const store = new Map(); const cache = { get: vi.fn((key: string) => store.get(key) || null), has: vi.fn((key: string) => store.has(key)), set: vi.fn((key: string, value?: string | Record) => { store.set(key, typeof value === 'object' ? JSON.stringify(value) : value || ''); }), tryGet: vi.fn(async (key: string, getValue: () => Promise) => { const cached = store.get(key); if (cached) { return cached; } const value = await getValue(); store.set(key, JSON.stringify(value)); return value; }), }; const destroy = vi.fn(); const page = { route: vi.fn((_pattern: string, handler: (route: any) => void) => { for (const requestUrl of ['https://m.weibo.cn/', 'https://m.weibo.cn/']) { handler({ abort: vi.fn(), continue: vi.fn(), request: () => ({ resourceType: () => 'document', url: () => requestUrl, }), }); } }), setExtraHTTPHeaders: vi.fn(), url: vi.fn(() => 'https://m.weibo.cn/'), }; const getPlaywrightPage = vi.fn(async (_url: string, options: any) => { await pageReady; await options.onBeforeLoad(page); return { destroy, page }; }); const getCookies = vi.fn(() => Promise.resolve('SUB=mock')); vi.doMock('@/config', () => ({ config: { cache: { contentExpire: 3600, routeExpire: 300, }, weibo: {}, }, })); vi.doMock('@/utils/cache', () => ({ default: cache })); vi.doMock('@/utils/logger', () => ({ default: { info: vi.fn(), warn: vi.fn(), }, })); vi.doMock('@/utils/playwright', () => ({ getPlaywrightPage })); vi.doMock('@/utils/playwright-utils', () => ({ getCookies })); const { default: weiboUtils } = await import('./routes/weibo/utils'); return { cache, getCookies, getPlaywrightPage, weiboUtils, }; }; afterEach(() => { vi.useRealTimers(); vi.restoreAllMocks(); vi.resetModules(); }); describe('weibo utils', () => { it('shares an in-flight visitor cookie fetch across concurrent callers', async () => { vi.useFakeTimers(); const pageReady = createDeferred(); const { getPlaywrightPage, weiboUtils } = await loadWeiboUtils({ pageReady: pageReady.promise }); const first = weiboUtils.getCookies(); const second = weiboUtils.getCookies(); pageReady.resolve(); await expect(Promise.all([first, second])).resolves.toEqual(['SUB=mock', 'SUB=mock']); expect(getPlaywrightPage).toHaveBeenCalledTimes(1); }); });