import { test, expect } from "bun:test"; // userbot.ts imports the runtime `config`, which requires DISCORD_GUILD_ID. process.env.DISCORD_GUILD_ID ||= "test-guild"; const { formatTurnMessage } = await import("./userbot.ts"); test("formatTurnMessage shows a per-stage timing breakdown with durations", () => { const msg = formatTurnMessage({ transcript: "안녕하세요", reply: "네, 안녕하세요", listenStartMs: 10_000, listenEndMs: 12_000, // 듣기 2.0s llmStartMs: 12_500, // STT/전송 gap 0.5s llmEndMs: 14_100, // LLM 1.6s ttsStartMs: 14_100, ttsEndMs: 15_000, // TTS 0.9s }); expect(msg).toContain('🗣️ "안녕하세요"'); expect(msg).toContain("🤖 답변: 네, 안녕하세요"); expect(msg).toContain("👂 듣기 2.0초"); expect(msg).toContain("🧠 LLM 1.6초"); expect(msg).toContain("(STT/전송 0.5초)"); expect(msg).toContain("🔊 TTS 0.9초"); // Total spans listening start -> TTS end. expect(msg).toContain("합계 5.0초"); }); test("formatTurnMessage omits the STT gap note when it is negligible", () => { const msg = formatTurnMessage({ transcript: "테스트", reply: "응답", listenStartMs: 0, listenEndMs: 1000, llmStartMs: 1000, // no gap llmEndMs: 2000, }); expect(msg).not.toContain("STT/전송"); expect(msg).toContain("🧠 LLM 1.0초"); }); test("formatTurnMessage reports a dropped turn with only the listening stage", () => { const msg = formatTurnMessage({ transcript: "", reply: "", note: "너무 짧음(<300ms)", listenStartMs: 0, listenEndMs: 200, }); expect(msg).toContain("❌ 너무 짧음(<300ms)"); expect(msg).toContain("👂 듣기 0.2초"); expect(msg).not.toContain("🧠 LLM"); expect(msg).not.toContain("🔊 TTS"); }); test("formatTurnMessage shows the speaker user ID when provided", () => { const answered = formatTurnMessage({ user: "12345", transcript: "안녕", reply: "하이" }); expect(answered).toContain("👤 12345"); const dropped = formatTurnMessage({ user: "67890", transcript: "", reply: "", note: "음성 아님(VAD 차단)" }); expect(dropped).toContain("👤 67890"); expect(dropped).toContain("❌ 음성 아님(VAD 차단)"); }); test("formatTurnMessage falls back to the plain line when no timing is present", () => { const msg = formatTurnMessage({ transcript: "안녕", reply: "하이" }); expect(msg).toBe('🎤 들음 → 🗣️ "안녕"\n🤖 답변: 하이'); expect(msg).not.toContain("⏱️"); }); test("formatTurnMessage drops out-of-order (negative) spans instead of showing junk", () => { const msg = formatTurnMessage({ transcript: "안녕", reply: "하이", listenStartMs: 5000, listenEndMs: 4000, // negative span -> omitted }); expect(msg).not.toContain("👂 듣기"); });