Files
prop-ai-hr/mobile-uni/tests/tts-voice-preference.test.mjs
T

59 lines
2.7 KiB
JavaScript

import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';
import vm from 'node:vm';
import ts from 'typescript';
const source = (path) => readFile(new URL(path, import.meta.url), 'utf8');
const preferenceRuntime = async (storage = new Map()) => {
const service = await source('../src/services/tts-voice-preference.ts');
const compiled = ts.transpileModule(service, {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }
});
const runtimeModule = { exports: {} };
vm.runInNewContext(compiled.outputText, {
exports: runtimeModule.exports,
module: runtimeModule,
uni: {
getStorageSync: (key) => storage.get(key),
setStorageSync: (key, value) => storage.set(key, value)
}
});
return runtimeModule.exports;
};
test('播报音色按租户和账号隔离保存,非法值回退跟随场景', async () => {
const storage = new Map();
const runtime = await preferenceRuntime(storage);
const extendedVoice = 'qwen-audio-3.0-tts-flash-longyingmuyu';
assert.equal(runtime.getTtsVoicePreference('000000', '13800000000'), '');
assert.equal(runtime.setTtsVoicePreference('000000', '13800000000', extendedVoice), extendedVoice);
assert.equal(runtime.getTtsVoicePreference('000000', '13800000000'), extendedVoice);
assert.equal(runtime.getTtsVoicePreference('000000', '13900000000'), '');
assert.equal(runtime.setTtsVoicePreference('000000', '13800000000', 'untrusted-voice'), '');
assert.equal(runtime.setTtsDialectPreference('000000', '13800000000', 'shanghai'), 'shanghai');
assert.equal(runtime.getTtsDialectPreference('000000', '13800000000'), 'shanghai');
});
test('全局选择只覆盖 voice,保留场景角色、情绪、语速和方言', async () => {
const runtime = await preferenceRuntime();
const profile = { role: 'customer', emotion: 'intense', speed: 1.12, dialect: 'sichuanese' };
assert.deepEqual(
JSON.parse(JSON.stringify(runtime.applyTtsVoicePreference(profile, 'longanhuan_v3.6', 'shanghai'))),
{ ...profile, voice: 'longanhuan_v3.6', dialect: 'shanghai' }
);
assert.deepEqual(JSON.parse(JSON.stringify(runtime.applyTtsVoicePreference(profile, ''))), profile);
});
test('语音播放链路在合成前统一注入全局音色,且缓存键包含处理后的 profile', async () => {
const sourceText = await source('../src/services/speech.ts');
assert.match(sourceText, /applyTtsVoicePreference/);
assert.match(sourceText, /getTtsVoicePreference/);
assert.match(sourceText, /cacheKey\(value, effectiveProfile, practiceContext\)/);
assert.match(sourceText, /synthesizeSpeech\(value, effectiveProfile, practiceContext\)/);
});