Files
hermes-desktop/tests/client/use-voice-api-connections-mimo.test.ts
T
toor 01d9e301fc
Build / build (push) Canceled after 0s
Playwright / browser (push) Canceled after 0s
initialize Electron desktop app and remove unused files
2026-10-25 01:09:01 +08:00

111 lines
3.8 KiB
TypeScript

// @vitest-environment jsdom
import { beforeEach, describe, expect, it, vi } from 'vitest'
const ttsApiMock = vi.hoisted(() => ({
deleteTtsProvider: vi.fn(),
fetchTtsSettings: vi.fn(),
saveActiveTtsProvider: vi.fn(),
saveTtsSettings: vi.fn(),
}))
const sttApiMock = vi.hoisted(() => ({
deleteSttProvider: vi.fn(),
fetchSttSettings: vi.fn(),
saveActiveSttProvider: vi.fn(),
saveSttSettings: vi.fn(),
}))
const voiceSettingsMock = vi.hoisted(() => {
const state = {
provider: { value: 'mimo' },
edgeVoice: { value: 'zh-CN-XiaoxiaoNeural' },
edgeRate: { value: 1 },
edgePitchHz: { value: 0 },
mimoBaseUrl: { value: 'https://api.xiaomimimo.com/v1' },
mimoModel: { value: 'mimo-v2.5-tts' },
mimoVoice: { value: '冰糖' },
mimoVoiceCloneDataUri: { value: '' },
mimoVoiceCloneFileName: { value: '' },
mimoVoiceCloneFormat: { value: 'wav' },
}
return {
...state,
setProvider: vi.fn((value: string) => { state.provider.value = value }),
setMimoBaseUrl: vi.fn(),
setMimoModel: vi.fn(),
setMimoVoice: vi.fn(),
setMimoStylePrompt: vi.fn(),
setMimoVoiceDesignDesc: vi.fn(),
setMimoVoiceCloneDataUri: vi.fn((value: string) => { state.mimoVoiceCloneDataUri.value = value }),
setMimoVoiceCloneFileName: vi.fn((value: string) => { state.mimoVoiceCloneFileName.value = value }),
setMimoVoiceCloneFormat: vi.fn((value: string) => { state.mimoVoiceCloneFormat.value = value }),
}
})
vi.mock('@/api/hermes/tts-settings', () => ttsApiMock)
vi.mock('@/api/hermes/stt-settings', () => sttApiMock)
vi.mock('@/composables/useVoiceSettings', () => ({ useVoiceSettings: () => voiceSettingsMock }))
vi.mock('@/composables/useSttSettings', () => ({
useSttSettings: () => ({
provider: { value: 'browser' },
loadServerSttSettings: vi.fn(),
setProvider: vi.fn(),
}),
}))
vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (key: string) => key }) }))
import { useVoiceApiConnections } from '@/composables/useVoiceApiConnections'
describe('useVoiceApiConnections MiMo voice clone', () => {
beforeEach(() => {
vi.clearAllMocks()
voiceSettingsMock.mimoVoiceCloneDataUri.value = ''
voiceSettingsMock.mimoVoiceCloneFileName.value = ''
voiceSettingsMock.mimoVoiceCloneFormat.value = 'wav'
ttsApiMock.saveTtsSettings.mockResolvedValue({})
ttsApiMock.saveActiveTtsProvider.mockResolvedValue('mimo')
ttsApiMock.fetchTtsSettings.mockResolvedValue({
activeProvider: 'mimo',
providers: [{
provider: 'mimo',
settings: {
model: 'mimo-v2.5-tts-voiceclone',
voiceMode: 'voiceClone',
voiceCloneFormat: 'mp3',
},
secrets: { apiKey: '[stored]' },
updatedAt: 1,
}],
})
sttApiMock.fetchSttSettings.mockResolvedValue({ activeProvider: 'browser', providers: [] })
})
it('keeps clone audio client-side while saving the remaining settings', async () => {
const connections = useVoiceApiConnections()
const dataUri = 'data:audio/mp3;base64,ZmFrZQ=='
await connections.saveConnection('tts', 'mimo', {
settings: {
model: 'mimo-v2.5-tts-voiceclone',
voiceMode: 'voiceClone',
voiceCloneFormat: 'mp3',
voiceCloneDataUri: dataUri,
voiceCloneFileName: 'sample.mp3',
},
})
expect(ttsApiMock.saveTtsSettings).toHaveBeenCalledWith('mimo', {
settings: {
model: 'mimo-v2.5-tts-voiceclone',
voiceMode: 'voiceClone',
voiceCloneFormat: 'mp3',
},
secrets: undefined,
activeProvider: 'mimo',
})
expect(voiceSettingsMock.setMimoVoiceCloneDataUri).toHaveBeenCalledWith(dataUri)
expect(voiceSettingsMock.setMimoVoiceCloneFileName).toHaveBeenCalledWith('sample.mp3')
expect(voiceSettingsMock.setMimoVoiceCloneFormat).toHaveBeenCalledWith('mp3')
})
})