import { describe, expect, it } from "vitest"; import { isValidFishAudioVoiceId } from "./speech-provider.js"; describe("fish-audio speech provider", () => { describe("isValidFishAudioVoiceId", () => { it("accepts valid Fish Audio ref IDs (24-40 char hex)", () => { const valid = [ "8a2d42279389471993460b85340235c5", // 32 char - standard "0dad9e24630447cf97803f4beee10481", // 32 char "5796fe24630447cf97803f4beee10481", // 32 char "d8b0991f96b44e489422ca2ddf0bd31d", // 32 char - author id "aabbccddee112233445566778899", // 28 char "aabbccddee11223344556677", // 24 char (minimum) ]; for (const v of valid) { expect(isValidFishAudioVoiceId(v), `expected valid: ${v}`).toBe(true); } }); it("rejects invalid voice IDs", () => { const invalid = [ "", // empty "abc123", // too short "12345678901234567890123", // 23 chars - below minimum "a".repeat(41), // too long "8a2d4227-9389-4719-9346-0b85340235c5", // UUID with dashes "../../../etc/passwd", // path traversal "voice?param=value", // query string "pMsXgVXv3BLzUgSXRplE", // ElevenLabs-style (mixed case, 20 chars) "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", // non-hex chars ]; for (const v of invalid) { expect(isValidFishAudioVoiceId(v), `expected invalid: ${v}`).toBe( false, ); } }); }); });