文件
OmniCard/admin/tests/ai-concierge.test.ts
wikiboss eec259a3a7 feat: 完成全系统30个功能点开发与E2E全链路验收 (8轮调度32个子代理闭环)
- 模块一: 出海案例作品集、博客动态发布、人名发音语音条、RTL阿语多语言切换
- 模块二: AI顾问人设配置、行业术语库润色、RAG切片沙盒调试、流式会话与意向留资卡片
- 模块三: 全球访客雷达大屏、多维加权意向算分、外部CRM对接推送、团队公海池流转
- 模块四: 移动端NFC安全挂失、NFC动态路由规则配置、动态防伪验签、展会制卡Zip批量导出
- 模块五: 组织架构与名片分配、移动端个人中心设置、离职交接与历史线索迁移、安全审计日志
- 模块六: Stripe国际信用卡订阅Webhook、独立二级域名与SSL检测、坐席配额预警、多币种发票
- 模块七: 纸质名片OCR解析入库、国际商务日程RFC 5545 ICS日历、微官网离线SWR预加载、展会实时排行榜大屏
- 模块八: 全球出海SEO OpenGraph元标签注入与社交爬虫探测、30点端到端全链路业务流集成测试套件
2026-09-20 23:47:47 +08:00

94 行
4.6 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';
import defaultI18n from '../src/locale/index.ts';
import { routes } from '../src/routes.ts';
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');
test('1. ai/concierge 页面必须使用 Arco Form/Select/Slider/Switch/Card/Radio 并接入 API', () => {
assert.ok(fs.existsSync(conciergePagePath), 'AI 顾问配置页面必须存在');
const content = fs.readFileSync(conciergePagePath, 'utf-8');
assert.ok(
content.includes('admin/ai/concierge'),
'必须请求 /api/admin/ai/concierge 相关接口'
);
assert.ok(content.includes('Form'), '必须使用 Arco Form');
assert.ok(content.includes('Select'), '必须使用 Arco Select');
assert.ok(content.includes('Slider'), '必须使用 Arco Slider');
assert.ok(content.includes('Switch'), '必须使用 Arco Switch');
assert.ok(content.includes('Card'), '必须使用 Arco Card');
assert.ok(content.includes('Radio'), '必须使用 Arco Radio');
assert.ok(
content.includes("from '@arco-design/web-react'"),
'必须从 @arco-design/web-react 引入组件'
);
assert.ok(
content.includes('code === 1000') || content.includes('code ===1000'),
'必须按 Cool-Admin code === 1000 判断成功'
);
assert.ok(content.includes('Message.error'), '失败必须使用 Arco Message.error');
assert.ok(!content.includes('Mock.js') && !content.includes("from 'mockjs'"), '禁止使用 Mock.js');
assert.ok(!/\bany\b/.test(content), '禁止使用 any');
});
test('2. ai/concierge 必须遵循设计 Token,禁止 emoji 与硬编码颜色,支持预设人设与阈值', () => {
const content = fs.readFileSync(conciergePagePath, 'utf-8');
assert.ok(content.includes("from '@/types/omni'"), '必须复用 admin/src/types/omni.ts');
assert.ok(content.includes('lightColors'), '颜色必须引用 lightColors token');
assert.ok(!/#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})\b/.test(content), '禁止硬编码十六进制颜色');
// 禁止 emoji
const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u;
assert.ok(!emojiRegex.test(content), '页面中严禁使用 emoji 图标或字符');
// 人设切换支持
assert.ok(content.includes('trade_expert'), '必须支持外贸专家预设 trade_expert');
assert.ok(content.includes('business_rep'), '必须支持商务代表预设 business_rep');
assert.ok(content.includes('tech_advisor'), '必须支持技术顾问预设 tech_advisor');
// 意向留资策略与欢迎语
assert.ok(content.includes('welcomeMsg'), '必须包含欢迎语 welcomeMsg 字段');
assert.ok(content.includes('triggerLeadThreshold'), '必须包含留资触发阈值 triggerLeadThreshold');
assert.ok(content.includes('promptTemplate'), '必须包含提示词模板 promptTemplate');
assert.ok(content.includes('toneStyle'), '必须包含语气风格 toneStyle');
assert.ok(content.includes('isEnabled'), '必须包含启停状态 isEnabled');
// 单一主 CTA
const primaryButtons = content.match(/type=["']primary["']/g) || [];
assert.equal(primaryButtons.length, 1, '一屏只允许 1 个主 CTA 按钮');
});
test('3. ai/concierge 路由与国际化配置必须齐备', () => {
// 检查 routes.ts 包含 ai/concierge
const aiRoute = routes.find(r => r.key === 'ai');
assert.ok(aiRoute, 'menu.ai 路由分组必须存在');
const conciergeRoute = aiRoute.children?.find(c => c.key === 'ai/concierge');
assert.ok(conciergeRoute, 'ai/concierge 路由项必须在 routes.ts 中注册');
assert.equal(conciergeRoute?.name, 'menu.ai.concierge');
// 检查语言包
assert.ok(fs.existsSync(conciergeLocalePath), '页面语言包必须存在');
const localeContent = fs.readFileSync(conciergeLocalePath, 'utf-8');
assert.ok(localeContent.includes("'en-US'"), '必须包含英文案');
assert.ok(localeContent.includes("'zh-CN'"), '必须包含中文案');
assert.ok(localeContent.includes("'menu.ai.concierge'"), '页面语言包必须包含 menu.ai.concierge');
assert.ok(!/\bany\b/.test(localeContent), 'locale 禁止使用 any');
// 检查全局语言包
assert.ok(
defaultI18n['en-US']['menu.ai.concierge'],
'src/locale/index.ts 必须包含 en-US menu.ai.concierge'
);
assert.ok(
defaultI18n['zh-CN']['menu.ai.concierge'],
'src/locale/index.ts 必须包含 zh-CN menu.ai.concierge'
);
});