63 行
3.2 KiB
TypeScript
63 行
3.2 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const adminRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const conciergePagePath = path.join(adminRoot, 'src/pages/ai/concierge/index.tsx');
|
|
const conciergeLocalePath = path.join(adminRoot, 'src/pages/ai/concierge/locale/index.ts');
|
|
const omniTypesPath = path.join(adminRoot, 'src/types/omni.ts');
|
|
|
|
test('1. DeepSeek 大模型后台界面必须接入标准 API 与连通性测试端点', () => {
|
|
assert.ok(fs.existsSync(conciergePagePath), 'AI 页面文件必须存在');
|
|
const content = fs.readFileSync(conciergePagePath, 'utf-8');
|
|
|
|
assert.ok(
|
|
content.includes('/api/admin/ai/deepseek/config'),
|
|
'必须包含 /api/admin/ai/deepseek/config 配置端点'
|
|
);
|
|
assert.ok(
|
|
content.includes('/api/admin/ai/deepseek/test-connection'),
|
|
'必须包含 /api/admin/ai/deepseek/test-connection 连通性测试端点'
|
|
);
|
|
assert.ok(content.includes('deepseek-chat'), '必须支持 deepseek-chat (V3)');
|
|
assert.ok(content.includes('deepseek-reasoner'), '必须支持 deepseek-reasoner (R1)');
|
|
assert.ok(content.includes('handleTestDeepSeek'), '必须提供连通性测试处理函数');
|
|
assert.ok(content.includes('handleSaveDeepSeek'), '必须提供保存配置处理函数');
|
|
});
|
|
|
|
test('2. DeepSeek 大模型跨端类型契约必须在 admin/src/types/omni.ts 中严密定义', () => {
|
|
assert.ok(fs.existsSync(omniTypesPath), 'omni.ts 类型契约必须存在');
|
|
const content = fs.readFileSync(omniTypesPath, 'utf-8');
|
|
|
|
assert.ok(content.includes('DeepSeekModel'), '必须导出 DeepSeekModel 类型');
|
|
assert.ok(content.includes('DeepSeekConfig'), '必须导出 DeepSeekConfig 接口');
|
|
assert.ok(content.includes('DeepSeekChatMessage'), '必须导出 DeepSeekChatMessage 接口');
|
|
assert.ok(
|
|
content.includes('DeepSeekTestConnectionResult'),
|
|
'必须导出 DeepSeekTestConnectionResult 接口'
|
|
);
|
|
});
|
|
|
|
test('3. DeepSeek 多语言国际化必须覆盖中英阿且无 emoji 无 any', () => {
|
|
assert.ok(fs.existsSync(conciergeLocalePath), '语言包必须存在');
|
|
const localeContent = fs.readFileSync(conciergeLocalePath, 'utf-8');
|
|
|
|
assert.ok(localeContent.includes("'aiDeepSeek.card.title'"), '必须包含卡片标题词条');
|
|
assert.ok(localeContent.includes("'aiDeepSeek.form.apiKey'"), '必须包含 API Key 表单项');
|
|
assert.ok(localeContent.includes("'aiDeepSeek.form.model'"), '必须包含模型选择项');
|
|
assert.ok(localeContent.includes("'aiDeepSeek.action.test'"), '必须包含测试连通性按钮词条');
|
|
assert.ok(localeContent.includes("'aiDeepSeek.test.success'"), '必须包含测试成功提示');
|
|
|
|
// 三语检查
|
|
assert.ok(localeContent.includes("'en-US'"), '必须支持 en-US');
|
|
assert.ok(localeContent.includes("'zh-CN'"), '必须支持 zh-CN');
|
|
assert.ok(localeContent.includes("'ar-SA'"), '必须支持 ar-SA');
|
|
|
|
// 禁止 emoji
|
|
const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u;
|
|
assert.ok(!emojiRegex.test(localeContent), '语言包严禁使用 emoji');
|
|
assert.ok(!/\bany\b/.test(localeContent), '语言包严禁使用 any');
|
|
});
|