Files
openmaic/OpenMAIC/tests/audio/provider-enablement.test.ts
2026-08-16 14:58:47 +08:00

108 lines
4.9 KiB
TypeScript

/**
* Tests for the unified TTS provider-enablement model (#665).
*
* Covers the three layered concerns the model collapses:
* - availability (configured) — incl. dropping the registry defaultBaseUrl
* so a keyless local provider (Lemonade) is NOT force-shown;
* - per-provider user `enabled` flag being honored;
* - server/admin force-off taking precedence over the user toggle;
* - browser-native being opt-in (default OFF) and a first-class provider.
*/
import { describe, it, expect } from 'vitest';
import {
isTTSProviderConfigured,
isTTSProviderEnabled,
listEnabledTTSProviderIds,
hasAnyEnabledTTSProvider,
type TTSEnablementConfig,
} from '@/lib/audio/provider-enablement';
describe('isTTSProviderConfigured', () => {
it('key-requiring provider needs an API key', () => {
expect(isTTSProviderConfigured('openai-tts', {})).toBe(false);
expect(isTTSProviderConfigured('openai-tts', { apiKey: ' ' })).toBe(false);
expect(isTTSProviderConfigured('openai-tts', { apiKey: 'sk-x' })).toBe(true);
expect(isTTSProviderConfigured('openai-tts', { isServerConfigured: true })).toBe(true);
});
it('keyless local provider is NOT shown from the registry defaultBaseUrl alone (Lemonade fix)', () => {
// lemonade-tts has a registry defaultBaseUrl; with no explicit config it
// must be unavailable (symptom 1).
expect(isTTSProviderConfigured('lemonade-tts', {})).toBe(false);
expect(isTTSProviderConfigured('lemonade-tts', undefined)).toBe(false);
// Explicit base URL or server config makes it available.
expect(isTTSProviderConfigured('lemonade-tts', { baseUrl: 'http://localhost:13305/v1' })).toBe(
true,
);
expect(isTTSProviderConfigured('lemonade-tts', { isServerConfigured: true })).toBe(true);
});
it('VoxCPM requires an explicit base URL (or server config)', () => {
expect(isTTSProviderConfigured('voxcpm-tts', {})).toBe(false);
expect(isTTSProviderConfigured('voxcpm-tts', { baseUrl: 'http://127.0.0.1:8000' })).toBe(true);
});
it('browser-native is always configured (runs in-browser)', () => {
expect(isTTSProviderConfigured('browser-native-tts', undefined)).toBe(true);
expect(isTTSProviderConfigured('browser-native-tts', {})).toBe(true);
});
it('custom provider is configured once it has a credential path or voices', () => {
expect(isTTSProviderConfigured('custom-tts-foo', {})).toBe(false);
expect(isTTSProviderConfigured('custom-tts-foo', { apiKey: 'k' })).toBe(true);
expect(
isTTSProviderConfigured('custom-tts-foo', { customVoices: [{ id: 'v', name: 'V' }] }),
).toBe(true);
});
});
describe('isTTSProviderEnabled', () => {
it('honors the per-provider enabled flag (default on)', () => {
expect(isTTSProviderEnabled('openai-tts', { apiKey: 'k' })).toBe(true);
expect(isTTSProviderEnabled('openai-tts', { apiKey: 'k', enabled: true })).toBe(true);
expect(isTTSProviderEnabled('openai-tts', { apiKey: 'k', enabled: false })).toBe(false);
});
it('server-disable overrides the user toggle (server precedence)', () => {
expect(
isTTSProviderEnabled('openai-tts', { apiKey: 'k', enabled: true, serverDisabled: true }),
).toBe(false);
});
it('an unconfigured provider is never enabled', () => {
expect(isTTSProviderEnabled('openai-tts', { enabled: true })).toBe(false);
expect(isTTSProviderEnabled('lemonade-tts', { enabled: true })).toBe(false);
});
it('browser-native is opt-in: default OFF, on only when explicitly enabled', () => {
// Default persisted config flips browser-native to enabled:false (#665).
expect(isTTSProviderEnabled('browser-native-tts', { enabled: false })).toBe(false);
expect(isTTSProviderEnabled('browser-native-tts', { enabled: true })).toBe(true);
// Server can force it off even when the user enabled it.
expect(
isTTSProviderEnabled('browser-native-tts', { enabled: true, serverDisabled: true }),
).toBe(false);
});
});
describe('listEnabledTTSProviderIds / hasAnyEnabledTTSProvider', () => {
const config: Record<string, TTSEnablementConfig> = {
'openai-tts': { apiKey: 'k', enabled: true },
'qwen-tts': { apiKey: 'k', enabled: false }, // configured but user-disabled
'lemonade-tts': {}, // unconfigured (no explicit baseUrl)
'voxcpm-tts': { baseUrl: 'http://127.0.0.1:8000', serverDisabled: true }, // server off
'browser-native-tts': { enabled: false }, // opt-in, off
'custom-tts-foo': { customVoices: [{ id: 'v', name: 'V' }] },
};
it('lists only enabled providers in canonical registry order', () => {
expect(listEnabledTTSProviderIds(config)).toEqual(['openai-tts', 'custom-tts-foo']);
});
it('hasAny reflects emptiness', () => {
expect(hasAnyEnabledTTSProvider(config)).toBe(true);
expect(hasAnyEnabledTTSProvider({ 'browser-native-tts': { enabled: false } })).toBe(false);
expect(hasAnyEnabledTTSProvider({ 'browser-native-tts': { enabled: true } })).toBe(true);
});
});