Files
next-tjwater-agent/tests/routes/chatTokenSmoother.test.ts
T
jiang 6336157ff4
Generic Container CI/CD / test-build-publish (push) Successful in 1m6s
Agent CI/CD / build-test-publish-and-deploy (push) Successful in 1m7s
feat: upgrade investigation and presentation runtime
2026-10-30 17:30:19 +08:00

115 lines
4.5 KiB
TypeScript

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("供水💧核查完成。");
});
});