import { describe, it, expect, vi, beforeEach } from 'vitest'; interface PortStub { name: string; postMessage: ReturnType; onMessage: { addListener: ReturnType }; onDisconnect: { addListener: ReturnType }; disconnect: ReturnType; } interface ChromeStub { runtime: { id: string; sendMessage: (m: unknown) => void; onMessage: { addListener: ReturnType }; connect: () => PortStub; }; } interface GlobalWithChrome { chrome?: ChromeStub; MediaRecorder?: { isTypeSupported: (mime: string) => boolean }; } function buildChromeStub(calls: unknown[]): ChromeStub { return { runtime: { id: 'ext-id-test', sendMessage: (m: unknown) => { calls.push(m); }, onMessage: { addListener: vi.fn() }, connect: () => ({ name: 'video-keepalive', postMessage: vi.fn(), onMessage: { addListener: vi.fn() }, onDisconnect: { addListener: vi.fn() }, disconnect: vi.fn(), }), }, }; } describe('OFFSCREEN_READY handshake', () => { beforeEach(() => { vi.resetModules(); (globalThis as unknown as GlobalWithChrome).MediaRecorder = { isTypeSupported: vi.fn().mockReturnValue(true), }; }); it('sends OFFSCREEN_READY after listener registration', async () => { const calls: unknown[] = []; const stub = buildChromeStub(calls); (globalThis as unknown as GlobalWithChrome).chrome = stub; await import('../../src/offscreen/recorder'); expect(stub.runtime.onMessage.addListener).toHaveBeenCalled(); expect(calls).toEqual( expect.arrayContaining([expect.objectContaining({ type: 'OFFSCREEN_READY' })]) ); const readyCount = calls.filter( (m): m is { type: string } => typeof m === 'object' && m !== null && (m as { type?: unknown }).type === 'OFFSCREEN_READY' ).length; expect(readyCount).toBe(1); }); });