evOo-local/packages/adapters/src/voice-http.test.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

66 lines
2.2 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import {
MAX_VOICE_JSON_BYTES,
readVoiceJson,
speechUploadName,
voiceDeadline,
} from "./voice-http.js";
describe("voiceDeadline", () => {
it("aborts when the client signal aborts", () => {
const client = new AbortController();
const combined = voiceDeadline(client.signal, 20_000);
expect(combined.aborted).toBe(false);
client.abort();
expect(combined.aborted).toBe(true);
});
it("aborts when the deadline elapses even if the client stays connected", async () => {
const combined = voiceDeadline(new AbortController().signal, 1);
await new Promise<void>((resolve, reject) => {
const guard = setTimeout(() => reject(new Error("deadline did not abort")), 1_000);
combined.addEventListener(
"abort",
() => {
clearTimeout(guard);
resolve();
},
{ once: true },
);
});
expect(combined.aborted).toBe(true);
});
});
describe("speechUploadName", () => {
it("keeps webm recordings as webm even when they name an opus codec", () => {
expect(speechUploadName("audio/webm;codecs=opus")).toBe("speech.webm");
});
it("maps Firefox ogg capture to an ogg filename", () => {
expect(speechUploadName("audio/ogg; codecs=opus")).toBe("speech.ogg");
});
});
describe("readVoiceJson", () => {
it("rejects an oversized provider response without waiting for cancellation", async () => {
const cancel = vi.fn(() => new Promise<void>(() => undefined));
const response = new Response(new ReadableStream({ cancel }), {
headers: { "content-length": String(MAX_VOICE_JSON_BYTES + 1) },
});
await expect(readVoiceJson(response)).rejects.toThrow("Voice response is too large.");
expect(cancel).toHaveBeenCalledOnce();
});
it("rejects malformed successful JSON when the caller requires a payload", async () => {
await expect(readVoiceJson(new Response("not json"), { requireValid: true })).rejects.toThrow(
"Voice provider returned invalid JSON.",
);
});
it("keeps malformed error bodies optional", async () => {
await expect(readVoiceJson(new Response("not json"))).resolves.toBeNull();
});
});