import { describe, expect, it } from "bun:test"; import { createTokenSmoother } from "../../src/routes/chatTokenSmoother.js"; function createOutput(options: { enabled?: boolean; delayMs?: number; maxWaitMs?: number } = {}) { const chunks: string[] = []; const smoother = createTokenSmoother({ enabled: true, delayMs: 1, locale: "zh", sessionId: "s", ...options, write: (_event, data) => { chunks.push(String(data.content)); }, }); return { chunks, smoother }; } describe("token output lifecycle", () => { it("releases short Chinese narration during an upstream pause", async () => { const { chunks, smoother } = createOutput({ maxWaitMs: 25 }); try { smoother.writeToken("正在核查,请稍候。"); await Bun.sleep(60); expect(chunks.join("")).toBe("正在核查,请稍候。"); } finally { await smoother.flush(); } }); it("continues streaming after a stage flush", async () => { const { chunks, smoother } = createOutput(); smoother.writeToken("发布界面前。"); await smoother.flush(); smoother.writeToken("发布界面后继续解释。"); await smoother.flush(); expect(chunks).toEqual(["发布界面前。", "发布界面后继续解释。"]); }); it("keeps releasing a burst in bounded chunks beyond the short-tail deadline", async () => { const { chunks, smoother } = createOutput({ delayMs: 5, maxWaitMs: 25 }); const text = "核查管道压力与流量。".repeat(30); try { smoother.writeToken(text); await Bun.sleep(60); expect(chunks.length).toBeGreaterThan(1); expect(chunks.every((chunk) => Array.from(chunk).length <= 18)).toBe(true); } finally { await smoother.flush(); } expect(chunks.join("")).toBe(text); }); it("paces a stage flush instead of dumping the remaining paragraph", async () => { const chunks: string[] = []; const times: number[] = []; const smoother = createTokenSmoother({ enabled: true, delayMs: 10, locale: "zh", sessionId: "s", write: (_event, data) => { chunks.push(String(data.content)); times.push(performance.now()); }, }); const text = "核查管道压力与流量。".repeat(10); smoother.writeToken(text); await smoother.flush(); expect(chunks.length).toBeGreaterThan(2); expect(chunks.every((chunk) => Array.from(chunk).length <= 23)).toBe(true); expect(times.at(-1)! - times[0]).toBeGreaterThanOrEqual(30); expect(chunks.join("")).toBe(text); }); it("keeps later text behind an in-progress stage boundary", async () => { const { chunks, smoother } = createOutput({ delayMs: 5 }); const before = "管道压力核查。".repeat(8); smoother.writeToken(before); const boundary = smoother.flush(); smoother.writeToken("组件后的解释。"); await boundary; expect(chunks.join("")).toBe(before); await smoother.close(); expect(chunks.join("")).toBe(`${before}组件后的解释。`); }); it("interrupts a paced drain immediately without duplicate late output", async () => { const { chunks, smoother } = createOutput({ delayMs: 1000 }); const text = "管道压力核查。".repeat(8); smoother.writeToken(text); const draining = smoother.flush(); await smoother.close({ immediate: true }); await draining; await Bun.sleep(30); expect(chunks).toEqual([text]); }); it("does not postpone the first release when new Chinese text keeps arriving", async () => { const { chunks, smoother } = createOutput({ maxWaitMs: 25 }); try { for (let i = 0; i < 8; i++) { smoother.writeToken("核查"); await Bun.sleep(10); } expect(chunks.join("").length).toBeGreaterThan(0); } finally { await smoother.flush(); } expect(chunks.join("")).toBe("核查".repeat(8)); }); it.each([true, false])("closes once and ignores late writes with smoothing=%s", async (enabled) => { const { chunks, smoother } = createOutput({ enabled }); smoother.writeToken("已经收到的文字。"); await smoother.close(); smoother.writeToken("关闭后不能追加。"); await smoother.close(); await Bun.sleep(35); expect(chunks.join("")).toBe("已经收到的文字。"); }); it("preserves Unicode and order across repeated flushes without delayed duplicates", async () => { const { chunks, smoother } = createOutput({ maxWaitMs: 25 }); smoother.writeToken("供水💧"); await smoother.flush(); smoother.writeToken("核查完成。"); await smoother.flush(); await Bun.sleep(60); expect(chunks.join("")).toBe("供水💧核查完成。"); }); });