feat: expand intelligent investigation workspace
This commit is contained in:
@@ -7,6 +7,13 @@ import {
|
||||
type EdgeTtsMiddlewareOptions,
|
||||
type EdgeTtsSynthesizer
|
||||
} from "./edge-tts-service";
|
||||
import type { SpeechVoice } from "../src/shared/tts/voices";
|
||||
|
||||
const voices: SpeechVoice[] = [
|
||||
{ id: "zh-CN-XiaoxiaoNeural", name: "Xiaoxiao", locale: "zh-CN", gender: "Female" },
|
||||
{ id: "zh-CN-YunyangNeural", name: "Yunyang", locale: "zh-CN", gender: "Male" },
|
||||
{ id: "zh-CN-XiaoyiNeural", name: "Xiaoyi", locale: "zh-CN", gender: "Female" }
|
||||
];
|
||||
|
||||
const servers: ReturnType<typeof createServer>[] = [];
|
||||
|
||||
@@ -39,6 +46,52 @@ function postSpeech(baseUrl: string, body: unknown, headers = true) {
|
||||
}
|
||||
|
||||
describe("Edge TTS adapter", () => {
|
||||
it("falls back to Mandarin when a non-Mandarin default is configured", async () => {
|
||||
const synthesize = vi.fn<EdgeTtsSynthesizer>(async () => Uint8Array.from([1]));
|
||||
const baseUrl = await startServer({ defaultVoice: "en-US-AriaNeural", synthesize });
|
||||
expect((await postSpeech(baseUrl, { text: "测试" })).status).toBe(200);
|
||||
expect(synthesize).toHaveBeenCalledWith("测试", "zh-CN-XiaoxiaoNeural");
|
||||
});
|
||||
it("returns all voices and the default, sharing the catalog with selection validation", async () => {
|
||||
const listVoices = vi.fn(async () => voices);
|
||||
const synthesize = vi.fn<EdgeTtsSynthesizer>(async () => Uint8Array.from([1]));
|
||||
const baseUrl = await startServer({ listVoices, synthesize, defaultVoice: voices[0].id });
|
||||
const response = await fetch(`${baseUrl}/api/tts/edge/voices`);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("cache-control")).toBe("no-store");
|
||||
expect(await response.json()).toEqual({ voices, defaultVoice: voices[0].id });
|
||||
expect((await postSpeech(baseUrl, { text: "测试", voice: voices[1].id })).status).toBe(200);
|
||||
expect(synthesize).toHaveBeenLastCalledWith("测试", voices[1].id);
|
||||
expect((await postSpeech(baseUrl, { text: "test", voice: voices[2].id })).status).toBe(200);
|
||||
expect(synthesize).toHaveBeenLastCalledWith("test", voices[2].id);
|
||||
expect(listVoices).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("rejects unknown and malformed voice choices before synthesis", async () => {
|
||||
const synthesize = vi.fn<EdgeTtsSynthesizer>(async () => Uint8Array.from([1]));
|
||||
const baseUrl = await startServer({ listVoices: async () => voices, synthesize });
|
||||
for (const voice of ["zh-CN-UnknownNeural", "en-US-AriaNeural", "zh-TW-HsiaoChenNeural", "zh-CN-liaoning-XiaobeiNeural", "<voice name='bad'>", null, 12, {}]) {
|
||||
expect((await postSpeech(baseUrl, { text: "测试", voice })).status).toBe(400);
|
||||
}
|
||||
expect(synthesize).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("can use the default when the catalog is unavailable and retry a failed catalog load", async () => {
|
||||
const listVoices = vi.fn().mockRejectedValueOnce(new Error("offline")).mockResolvedValue(voices);
|
||||
const synthesize = vi.fn<EdgeTtsSynthesizer>(async () => Uint8Array.from([1]));
|
||||
const baseUrl = await startServer({ listVoices, synthesize });
|
||||
expect((await fetch(`${baseUrl}/api/tts/edge/voices`)).status).toBe(503);
|
||||
expect((await postSpeech(baseUrl, { text: "默认" })).status).toBe(200);
|
||||
expect((await fetch(`${baseUrl}/api/tts/edge/voices`)).status).toBe(200);
|
||||
expect(listVoices).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("refuses a chosen voice when its availability cannot be verified", async () => {
|
||||
const synthesize = vi.fn<EdgeTtsSynthesizer>(async () => Uint8Array.from([1]));
|
||||
const baseUrl = await startServer({ listVoices: async () => { throw new Error("offline"); }, synthesize });
|
||||
expect((await postSpeech(baseUrl, { text: "测试", voice: voices[1].id })).status).toBe(503);
|
||||
expect(synthesize).not.toHaveBeenCalled();
|
||||
});
|
||||
it("returns synthesized MP3 audio with the server-owned voice", async () => {
|
||||
const synthesize = vi.fn<EdgeTtsSynthesizer>(async () => Uint8Array.from([73, 68, 51]));
|
||||
const baseUrl = await startServer({ synthesize, defaultVoice: "zh-CN-XiaoxiaoNeural" });
|
||||
|
||||
Reference in New Issue
Block a user