Files
integrations/test/marytts/test.marytts.client_runtime.node.ts
T

91 lines
4.1 KiB
TypeScript

import { expect, tap } from '@git.zone/tstest/tapbundle';
import { MaryttsClient, MaryttsIntegration, type IMaryttsAudioResult } from '../../ts/integrations/marytts/index.js';
tap.test('posts MaryTTS /process form data and returns audio bytes', async () => {
const originalFetch = globalThis.fetch;
const calls: Array<{ url: string; method?: string; body: string; contentType?: string }> = [];
globalThis.fetch = (async (inputArg: RequestInfo | URL, initArg?: RequestInit) => {
calls.push({
url: String(inputArg),
method: initArg?.method,
body: String(initArg?.body || ''),
contentType: (initArg?.headers as Record<string, string> | undefined)?.['content-type'],
});
return new Response(Buffer.from([0x52, 0x49, 0x46, 0x46]), { status: 200, headers: { 'content-type': 'audio/wav' } });
}) as typeof globalThis.fetch;
try {
const client = new MaryttsClient({ host: '127.0.0.1', port: 59126, effect: { Robot: 'amount:100.0;' } });
const result = await client.speak('Hello world', { codec: 'WAVE_FILE', language: 'en_US', effects: { Volume: 'amount:2.0;' } });
const params = new URLSearchParams(calls[0].body);
expect(calls[0].url).toEqual('http://127.0.0.1:59126/process');
expect(calls[0].method).toEqual('POST');
expect(calls[0].contentType).toEqual('application/x-www-form-urlencoded');
expect(params.get('INPUT_TEXT')).toEqual('Hello world');
expect(params.get('OUTPUT_TYPE')).toEqual('AUDIO');
expect(params.get('INPUT_TYPE')).toEqual('TEXT');
expect(params.get('LOCALE')).toEqual('en_US');
expect(params.get('AUDIO')).toEqual('WAVE_FILE');
expect(params.get('VOICE')).toEqual('cmu-slt-hsmm');
expect(params.get('effect_Robot_selected')).toEqual('on');
expect(params.get('effect_Robot_parameters')).toEqual('amount:100.0;');
expect(params.get('effect_Volume_selected')).toEqual('on');
expect(result.format).toEqual('wav');
expect(result.contentType).toEqual('audio/wav');
expect(Buffer.isBuffer(result.audio)).toBeTrue();
expect(result.audio.toString('ascii')).toEqual('RIFF');
} finally {
globalThis.fetch = originalFetch;
}
});
tap.test('routes tts.speak through the MaryTTS runtime and reports HTTP failures', async () => {
const originalFetch = globalThis.fetch;
const calls: string[] = [];
globalThis.fetch = (async (inputArg: RequestInfo | URL, initArg?: RequestInit) => {
calls.push(`${initArg?.method || 'GET'} ${String(inputArg)}`);
if (String(inputArg).endsWith('/process')) {
return new Response(Buffer.from([1, 2, 3]), { status: 200, headers: { 'content-type': 'audio/aiff' } });
}
return new Response('MaryTTS demo', { status: 200 });
}) as typeof globalThis.fetch;
try {
const runtime = await new MaryttsIntegration().setup({ url: 'http://mary.test/base', codec: 'AIFF_FILE' }, {});
const result = await runtime.callService?.({
domain: 'tts',
service: 'speak',
target: {},
data: { message: 'Runtime hello', options: { effect: { Robot: 'amount:100.0;' } } },
});
const audio = (result?.data as IMaryttsAudioResult).audio;
expect(result?.success).toBeTrue();
expect((result?.data as IMaryttsAudioResult).format).toEqual('aiff');
expect(Buffer.isBuffer(audio)).toBeTrue();
expect(calls.includes('POST http://mary.test/base/process')).toBeTrue();
await runtime.destroy();
} finally {
globalThis.fetch = originalFetch;
}
});
tap.test('does not report MaryTTS synthesis success on non-2xx response', async () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = (async () => new Response('boom', { status: 500 })) as typeof globalThis.fetch;
try {
const runtime = await new MaryttsIntegration().setup({ host: '127.0.0.1', port: 59126 }, {});
const result = await runtime.callService?.({ domain: 'tts', service: 'speak', target: {}, data: { message: 'fail' } });
expect(result?.success).toBeFalse();
expect(result?.error?.includes('HTTP 500')).toBeTrue();
await runtime.destroy();
} finally {
globalThis.fetch = originalFetch;
}
});
export default tap.start();