/* Copyright 2026 Lotus Guild SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ import { ConnectionQuality } from "livekit-client"; import { describe, expect, it } from "vitest"; import { CallQualityTracker } from "./lotusCallSummary"; const clock = (): { now: () => number; tick: (ms: number) => void } => { let t = 1_000_000; return { now: () => t, tick: (ms) => { t += ms; }, }; }; describe("CallQualityTracker", () => { it("reports unknown when nothing was sampled", () => { const c = clock(); const tr = new CallQualityTracker(c.now); tr.start(); c.tick(60_000); expect(tr.summary()).toEqual({ durationMs: 60_000, reconnects: 0, poorMs: 0, verdict: "unknown", }); }); it("is good when quality stayed fine", () => { const c = clock(); const tr = new CallQualityTracker(c.now); tr.start(); tr.setQuality(ConnectionQuality.Excellent); c.tick(30 * 60_000); expect(tr.summary().verdict).toBe("good"); }); it("accumulates poor time across episodes, including an open one", () => { const c = clock(); const tr = new CallQualityTracker(c.now); tr.start(); tr.setQuality(ConnectionQuality.Good); c.tick(60_000); tr.setQuality(ConnectionQuality.Poor); c.tick(10_000); tr.setQuality(ConnectionQuality.Good); c.tick(60_000); tr.setQuality(ConnectionQuality.Lost); c.tick(5_000); const s = tr.summary(); expect(s.poorMs).toBe(15_000); expect(s.durationMs).toBe(135_000); expect(s.verdict).toBe("fair"); }); it("is poor with many reconnects or mostly-poor quality", () => { const c = clock(); const tr = new CallQualityTracker(c.now); tr.start(); tr.setQuality(ConnectionQuality.Good); for (let i = 0; i < 4; i += 1) tr.reconnect(); c.tick(60_000); expect(tr.summary()).toMatchObject({ reconnects: 4, verdict: "poor" }); const tr2 = new CallQualityTracker(c.now); tr2.start(); tr2.setQuality(ConnectionQuality.Poor); c.tick(60_000); expect(tr2.summary().verdict).toBe("poor"); }); it("ignores unknown samples and only starts once", () => { const c = clock(); const tr = new CallQualityTracker(c.now); tr.start(); c.tick(1_000); tr.start(); tr.setQuality(ConnectionQuality.Unknown); c.tick(1_000); expect(tr.summary()).toMatchObject({ durationMs: 2_000, verdict: "unknown", }); }); });