Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
const { persistCallRecordMock } = vi.hoisted(() => ({
persistCallRecordMock: vi.fn(),
}));
vi.mock("./store.js", () => ({
persistCallRecord: persistCallRecordMock,
}));
import {
clearMaxDurationTimer,
clearTranscriptWaiter,
rejectTranscriptWaiter,
resolveTranscriptWaiter,
startMaxDurationTimer,
waitForFinalTranscript,
} from "./timers.js";
describe("voice-call manager timers", () => {
beforeEach(() => {
vi.useFakeTimers();
vi.clearAllMocks();
});
afterEach(() => {
vi.useRealTimers();
});
it("starts and clears max duration timers, persisting timeout metadata before delegation", async () => {
const call = { id: "call-1", state: "active" };
const ctx = {
activeCalls: new Map([["call-1", call]]),
maxDurationTimers: new Map(),
config: { maxDurationSeconds: 5 },
storePath: "/tmp/voice-call",
};
const onTimeout = vi.fn(async () => {});
startMaxDurationTimer({
ctx: ctx as never,
callId: "call-1",
onTimeout,
});
expect(ctx.maxDurationTimers.has("call-1")).toBe(true);
await vi.advanceTimersByTimeAsync(5_000);
expect(call).toEqual({ id: "call-1", state: "active", endReason: "timeout" });
expect(persistCallRecordMock).toHaveBeenCalledWith("/tmp/voice-call", call);
expect(onTimeout).toHaveBeenCalledWith("call-1");
expect(ctx.maxDurationTimers.has("call-1")).toBe(false);
startMaxDurationTimer({
ctx: ctx as never,
callId: "call-1",
onTimeout,
});
clearMaxDurationTimer(ctx as never, "call-1");
expect(ctx.maxDurationTimers.has("call-1")).toBe(false);
});
it("does not time out terminal calls", async () => {
const ctx = {
activeCalls: new Map([["call-1", { id: "call-1", state: "completed" }]]),
maxDurationTimers: new Map(),
config: { maxDurationSeconds: 5 },
storePath: "/tmp/voice-call",
};
const onTimeout = vi.fn(async () => {});
startMaxDurationTimer({
ctx: ctx as never,
callId: "call-1",
onTimeout,
});
await vi.advanceTimersByTimeAsync(5_000);
expect(persistCallRecordMock).not.toHaveBeenCalled();
expect(onTimeout).not.toHaveBeenCalled();
});
it("waits for transcripts, resolves matching tokens, rejects mismatches and timeouts", async () => {
const ctx = {
transcriptWaiters: new Map(),
config: { transcriptTimeoutMs: 1_000 },
};
const pending = waitForFinalTranscript(ctx as never, "call-1", "turn-1");
expect(resolveTranscriptWaiter(ctx as never, "call-1", "ignored", "turn-2")).toBe(false);
expect(resolveTranscriptWaiter(ctx as never, "call-1", "final transcript", "turn-1")).toBe(
true,
);
await expect(pending).resolves.toBe("final transcript");
const another = waitForFinalTranscript(ctx as never, "call-2");
rejectTranscriptWaiter(ctx as never, "call-2", "provider failed");
await expect(another).rejects.toThrow("provider failed");
const timedOut = waitForFinalTranscript(ctx as never, "call-3").catch((error) => error);
await vi.advanceTimersByTimeAsync(1_000);
await expect(timedOut).resolves.toEqual(
expect.objectContaining({
message: "Timed out waiting for transcript after 1000ms",
}),
);
const toClear = waitForFinalTranscript(ctx as never, "call-4");
clearTranscriptWaiter(ctx as never, "call-4");
expect(ctx.transcriptWaiters.has("call-4")).toBe(false);
void toClear.catch(() => {});
});
it("rejects duplicate transcript waiters for the same call", async () => {
const ctx = {
transcriptWaiters: new Map(),
config: { transcriptTimeoutMs: 1_000 },
};
const pending = waitForFinalTranscript(ctx as never, "call-1");
await expect(waitForFinalTranscript(ctx as never, "call-1")).rejects.toThrow(
"Already waiting for transcript",
);
rejectTranscriptWaiter(ctx as never, "call-1", "done");
await expect(pending).rejects.toThrow("done");
});
});
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-04-27)
¤
*© Formatika GbR, Deutschland
|
|