Files
openmaic/OpenMAIC/tests/audio/voice-registration-client.test.ts
2026-08-16 14:58:47 +08:00

83 lines
2.8 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
// db is browser-only (Dexie); stub it so the client module loads in node.
vi.mock('@/lib/utils/database', () => ({
db: {
autoVoiceCache: {
get: vi.fn(async () => undefined),
put: vi.fn(async () => undefined),
},
},
}));
import { ensureRegisteredVoice } from '@/lib/audio/voice-registration-client';
function okFetch() {
const f = vi.fn(
async () => new Response(JSON.stringify({ voiceId: 'x', registered: true }), { status: 200 }),
);
vi.stubGlobal('fetch', f);
return f;
}
describe('ensureRegisteredVoice memoization', () => {
beforeEach(() => vi.unstubAllGlobals());
it('re-registers when the backend base URL changes (memo keyed by backend, not voiceId alone)', async () => {
const f = okFetch();
// Distinct descriptor per test so the module-level memo from other tests can't collide.
const voiceDesign = { identity: 'backend-switch teacher', texture: 'warm', delivery: 'calm' };
await ensureRegisteredVoice('voxcpm-tts', { voiceDesign }, { ttsBaseUrl: 'https://a.test/v1' });
// Same backend again → memoized, no second round-trip.
await ensureRegisteredVoice('voxcpm-tts', { voiceDesign }, { ttsBaseUrl: 'https://a.test/v1' });
expect(f).toHaveBeenCalledTimes(1);
// Different backend → must NOT be skipped by the memo; re-register there.
await ensureRegisteredVoice('voxcpm-tts', { voiceDesign }, { ttsBaseUrl: 'https://b.test/v1' });
expect(f).toHaveBeenCalledTimes(2);
});
it('coalesces concurrent calls for the same (voiceId, backend) into one request', async () => {
const f = okFetch();
const voiceDesign = { identity: 'concurrent teacher', texture: 'warm', delivery: 'calm' };
const req = { ttsBaseUrl: 'https://c.test/v1' };
await Promise.all([
ensureRegisteredVoice('voxcpm-tts', { voiceDesign }, req),
ensureRegisteredVoice('voxcpm-tts', { voiceDesign }, req),
ensureRegisteredVoice('voxcpm-tts', { voiceDesign }, req),
]);
expect(f).toHaveBeenCalledTimes(1);
});
it('re-registers when the API key changes on the same base URL (auth-scoped)', async () => {
const f = okFetch();
const voiceDesign = {
identity: 'credential-switch teacher',
texture: 'warm',
delivery: 'calm',
};
const base = 'https://d.test/v1';
await ensureRegisteredVoice(
'voxcpm-tts',
{ voiceDesign },
{ ttsBaseUrl: base, ttsApiKey: 'k1' },
);
await ensureRegisteredVoice(
'voxcpm-tts',
{ voiceDesign },
{ ttsBaseUrl: base, ttsApiKey: 'k1' },
);
expect(f).toHaveBeenCalledTimes(1); // same creds → memoized
await ensureRegisteredVoice(
'voxcpm-tts',
{ voiceDesign },
{ ttsBaseUrl: base, ttsApiKey: 'k2' },
);
expect(f).toHaveBeenCalledTimes(2); // different creds → re-validate
});
});