Files
prop-ai-hr/mobile-uni/tests/realtime-practice.test.mjs
T

71 lines
3.4 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 realtimeVoiceRuntime = async () => {
const service = await source('../src/services/realtime-practice.ts');
const compiled = ts.transpileModule(service, {
compilerOptions: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2020
}
});
const runtimeModule = { exports: {} };
vm.runInNewContext(compiled.outputText, {
Date,
exports: runtimeModule.exports,
module: runtimeModule,
require: (specifier) => {
if (specifier === './api') return { apiRequest: async () => ({}) };
throw new Error(`Unexpected module: ${specifier}`);
}
});
return runtimeModule.exports;
};
test('实时陪练通过受认证 SDP 代理接入,前端不携带供应商密钥', async () => {
const [service, page, backendService] = await Promise.all([
source('../src/services/realtime-practice.ts'),
source('../src/pages/user/practice/index.vue'),
source('../../backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrRealtimePracticeService.java')
]);
assert.match(service, /\/api\/train\/practice\/realtime\/sdp/);
assert.match(service, /semantic_vad/);
assert.match(service, /conversation\.item\.input_audio_transcription\.completed/);
assert.match(service, /response\.audio_transcript\.done/);
assert.match(service, /session\.created/);
assert.match(service, /session\.updated/);
assert.match(service, /REALTIME_PRACTICE_VOICES/);
assert.match(service, /createRealtimePracticeSessionUpdate/);
assert.match(service, /activeAttempt/);
assert.match(service, /resumeAudio/);
assert.doesNotMatch(service, /DASHSCOPE_API_KEY|Authorization:\s*Bearer/);
assert.match(backendService, /实时陪练限流暂时不可用/);
assert.match(page, /实时陪练 Beta/);
assert.match(page, /实时陪练音色/);
assert.match(page, /<picker :range="realtimeVoiceOptions" range-key="label"/);
assert.match(page, /aihr_realtime_practice_voice/);
assert.match(page, /selectRealtimeVoice/);
assert.match(page, /createRealtimePracticeController/);
});
test('实时陪练音色白名单会写入会话配置,非法值回退默认音色', async () => {
const runtime = await realtimeVoiceRuntime();
const voices = Array.from(runtime.REALTIME_PRACTICE_VOICES);
assert.deepEqual(voices, [
'Tina', 'Cindy', 'Liora Mira', 'Sunnybobi', 'Raymond', 'Ethan', 'Theo Calm', 'Serena', 'Harvey', 'Maia', 'Evan', 'Qiao', 'Momo', 'Wil', 'Angel', 'Li Cassian', 'Mia', 'Joyner', 'Gold', 'Katerina', 'Ryan', 'Jennifer', 'Aiden', 'Mione', 'Sunny', 'Dylan', 'Eric', 'Peter', 'Joseph Chen', 'Marcus', 'Li', 'Kiki', 'Rocky', 'Sohee', 'Lenn', 'Ono Anna', 'Sonrisa', 'Bodega', 'Emilien', 'Andre', 'Radio Gol', 'Alek', 'Rizky', 'Roya', 'Arda', 'Hana', 'Dolce', 'Jakub', 'Griet', 'Eliška', 'Marina', 'Siiri', 'Ingrid', 'Sigga', 'Bea', 'Chloe'
]);
for (const voice of voices) {
assert.equal(runtime.normalizeRealtimePracticeVoice(voice), voice);
assert.equal(runtime.createRealtimePracticeSessionUpdate('测试', voice).session.voice, voice);
}
assert.equal(runtime.normalizeRealtimePracticeVoice('untrusted-voice'), 'Ethan');
assert.equal(runtime.createRealtimePracticeSessionUpdate('测试', 'untrusted-voice').session.voice, 'Ethan');
});