Milestone v1 (v2.0.0): Mokosh — Session Capture #1
67
tests/offscreen/handshake.test.ts
Normal file
67
tests/offscreen/handshake.test.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
interface PortStub {
|
||||
name: string;
|
||||
postMessage: ReturnType<typeof vi.fn>;
|
||||
onMessage: { addListener: ReturnType<typeof vi.fn> };
|
||||
onDisconnect: { addListener: ReturnType<typeof vi.fn> };
|
||||
disconnect: ReturnType<typeof vi.fn>;
|
||||
}
|
||||
|
||||
interface ChromeStub {
|
||||
runtime: {
|
||||
id: string;
|
||||
sendMessage: (m: unknown) => void;
|
||||
onMessage: { addListener: ReturnType<typeof vi.fn> };
|
||||
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);
|
||||
});
|
||||
});
|
||||
89
tests/offscreen/port.test.ts
Normal file
89
tests/offscreen/port.test.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
interface PortStub {
|
||||
name: string;
|
||||
postMessage: ReturnType<typeof vi.fn>;
|
||||
onMessage: { addListener: ReturnType<typeof vi.fn> };
|
||||
onDisconnect: { addListener: (fn: () => void) => void };
|
||||
disconnect: ReturnType<typeof vi.fn>;
|
||||
}
|
||||
|
||||
interface ChromeStub {
|
||||
runtime: {
|
||||
id: string;
|
||||
sendMessage: ReturnType<typeof vi.fn>;
|
||||
onMessage: { addListener: ReturnType<typeof vi.fn> };
|
||||
connect: () => PortStub;
|
||||
};
|
||||
}
|
||||
|
||||
interface GlobalWithChrome {
|
||||
chrome?: ChromeStub;
|
||||
MediaRecorder?: { isTypeSupported: (mime: string) => boolean };
|
||||
}
|
||||
|
||||
describe('port reconnect', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
(globalThis as unknown as GlobalWithChrome).MediaRecorder = {
|
||||
isTypeSupported: vi.fn().mockReturnValue(true),
|
||||
};
|
||||
});
|
||||
|
||||
it('connects on module load', async () => {
|
||||
let connectCount = 0;
|
||||
const disconnectListeners: Array<() => void> = [];
|
||||
const stub: ChromeStub = {
|
||||
runtime: {
|
||||
id: 'ext-id-test',
|
||||
sendMessage: vi.fn(),
|
||||
onMessage: { addListener: vi.fn() },
|
||||
connect: () => {
|
||||
connectCount++;
|
||||
return {
|
||||
name: 'video-keepalive',
|
||||
postMessage: vi.fn(),
|
||||
onMessage: { addListener: vi.fn() },
|
||||
onDisconnect: {
|
||||
addListener: (fn: () => void) => disconnectListeners.push(fn),
|
||||
},
|
||||
disconnect: vi.fn(),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
(globalThis as unknown as GlobalWithChrome).chrome = stub;
|
||||
await import('../../src/offscreen/recorder');
|
||||
expect(connectCount).toBe(1);
|
||||
});
|
||||
|
||||
it('reconnects when port disconnects', async () => {
|
||||
let connectCount = 0;
|
||||
const disconnectListeners: Array<() => void> = [];
|
||||
const stub: ChromeStub = {
|
||||
runtime: {
|
||||
id: 'ext-id-test',
|
||||
sendMessage: vi.fn(),
|
||||
onMessage: { addListener: vi.fn() },
|
||||
connect: () => {
|
||||
connectCount++;
|
||||
return {
|
||||
name: 'video-keepalive',
|
||||
postMessage: vi.fn(),
|
||||
onMessage: { addListener: vi.fn() },
|
||||
onDisconnect: {
|
||||
addListener: (fn: () => void) => disconnectListeners.push(fn),
|
||||
},
|
||||
disconnect: vi.fn(),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
(globalThis as unknown as GlobalWithChrome).chrome = stub;
|
||||
await import('../../src/offscreen/recorder');
|
||||
expect(connectCount).toBe(1);
|
||||
// Fire the disconnect — module should reconnect
|
||||
disconnectListeners.forEach((fn) => fn());
|
||||
expect(connectCount).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user