78 lines
2.8 KiB
TypeScript
78 lines
2.8 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { ENUM_OPTIONS, FREE_INPUT_KEYS, SECTIONS } from './constants'
|
|
import { voiceProviderKeys } from './voice-provider-fields'
|
|
|
|
const voiceKeys = SECTIONS.find(s => s.id === 'voice')?.keys ?? []
|
|
|
|
describe('voiceProviderKeys', () => {
|
|
it('derives per-provider field keys from the curated Voice section', () => {
|
|
expect(voiceProviderKeys('tts', 'openai')).toEqual(['tts.openai.model', 'tts.openai.voice'])
|
|
expect(voiceProviderKeys('tts', 'elevenlabs')).toEqual(['tts.elevenlabs.voice_id', 'tts.elevenlabs.model_id'])
|
|
expect(voiceProviderKeys('tts', 'edge')).toEqual(['tts.edge.voice'])
|
|
})
|
|
|
|
it('covers every built-in TTS provider the Capabilities picker offers', () => {
|
|
// Every provider key the backend TOOL_CATEGORIES["tts"] rows can carry
|
|
// (tts_provider values) must resolve to at least one config field, so the
|
|
// Capabilities panel never renders a silently-empty settings block.
|
|
for (const provider of [
|
|
'edge',
|
|
'openai',
|
|
'xai',
|
|
'elevenlabs',
|
|
'mistral',
|
|
'gemini',
|
|
'kittentts',
|
|
'piper',
|
|
'deepinfra',
|
|
'minimax'
|
|
]) {
|
|
expect(voiceProviderKeys('tts', provider).length, provider).toBeGreaterThan(0)
|
|
}
|
|
})
|
|
|
|
it('scopes to the exact provider segment (no prefix bleed)', () => {
|
|
expect(voiceProviderKeys('tts', 'mini')).toEqual([])
|
|
expect(voiceProviderKeys('stt', 'openai')).toEqual(['stt.openai.model'])
|
|
})
|
|
})
|
|
|
|
describe('voice field option coverage', () => {
|
|
it('offers the current gpt-4o-mini-tts voice set, not just the tts-1 six', () => {
|
|
const voices = ENUM_OPTIONS['tts.openai.voice']
|
|
|
|
for (const voice of ['alloy', 'ash', 'ballad', 'cedar', 'coral', 'marin', 'sage', 'verse', 'shimmer']) {
|
|
expect(voices).toContain(voice)
|
|
}
|
|
})
|
|
|
|
it('keeps voice/model name fields free-input so custom IDs are typeable', () => {
|
|
for (const key of [
|
|
'tts.openai.voice',
|
|
'tts.openai.model',
|
|
'tts.elevenlabs.voice_id',
|
|
'tts.edge.voice',
|
|
'tts.xai.voice_id',
|
|
'tts.piper.voice'
|
|
]) {
|
|
expect(FREE_INPUT_KEYS.has(key), key).toBe(true)
|
|
}
|
|
})
|
|
|
|
it('keeps closed enums (devices, providers) out of the free-input set', () => {
|
|
expect(FREE_INPUT_KEYS.has('tts.provider')).toBe(false)
|
|
expect(FREE_INPUT_KEYS.has('tts.neutts.device')).toBe(false)
|
|
expect(FREE_INPUT_KEYS.has('stt.provider')).toBe(false)
|
|
})
|
|
|
|
it('every free-input voice key that lives in the Voice section has suggestions or is intentionally bare', () => {
|
|
// Free-input keys don't *require* ENUM_OPTIONS (an empty datalist is
|
|
// fine), but any that do declare options must be actual Voice-section
|
|
// fields — a typo'd key here would silently do nothing.
|
|
for (const key of FREE_INPUT_KEYS) {
|
|
expect(voiceKeys, key).toContain(key)
|
|
}
|
|
})
|
|
})
|