import { describe, it, expect, vi } from "vitest"; import { PassThrough } from "node:stream"; vi.mock("node:child_process", async () => { const actual = await vi.importActual("node:child_process"); return { ...actual, spawn: (cmd: string, args: string[], opts: any) => { const stdout = new PassThrough(); const stderr = new PassThrough(); const listeners: Record = {}; const proc: any = { stdout, stderr, kill: vi.fn(() => { (listeners.exit || []).forEach((fn) => fn(0, "SIGKILL")); }), on: (ev: string, fn: Function) => { listeners[ev] = listeners[ev] || []; listeners[ev].push(fn); }, off: (ev: string, fn: Function) => { listeners[ev] = (listeners[ev] || []).filter((f) => f !== fn); }, stdoutWrite: (d: Buffer | string) => stdout.write(d), }; setTimeout(() => { (listeners.exit || []).forEach((fn) => fn(null, null)); }, 10); return proc; }, }; }); import { playTranscodedPreparedStream } from "../../src/streaming/index"; describe("playTranscodedPreparedStream", () => { it("pipes transcoder output to session and broadcasts to web", async () => { // mock global broadcast const broadcasts: Buffer[] = []; (globalThis as any).broadcastVideoToWeb = (chunk: Buffer) => broadcasts.push(Buffer.from(chunk)); const session = { connection: { channel: { id: "c" } }, stream: { playVideo: () => null, playAudio: () => null }, play: vi.fn().mockImplementation(async (readable) => { // consume a bit from readable to simulate playback readable.on("data", (d: Buffer) => {}); // resolve after a short delay await new Promise((r) => setTimeout(r, 5)); }), stop: vi.fn(), } as any; await playTranscodedPreparedStream("http://example.test/stream", session, { fps: 30 }); expect(session.play).toHaveBeenCalled(); expect(broadcasts.length).toBeGreaterThanOrEqual(0); }); });