147 行
6.1 KiB
TypeScript
147 行
6.1 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { lightColors, darkColors, spacing, radius, typography, getCssVariables } from '../src/style/tokens.ts';
|
|
import { omniLocales, isRtl, getOmniText } from '../src/locale/omni.ts';
|
|
import defaultI18n from '../src/locale/index.ts';
|
|
|
|
test('1. admin/src/style/tokens.ts - 颜色 Token 校验 (Light & Dark)', () => {
|
|
// Light 模式颜色
|
|
assert.equal(lightColors.primary, '#0B5CFF');
|
|
assert.equal(lightColors.primarySoft, '#EAF1FF');
|
|
assert.equal(lightColors.ai, '#7C5CFF');
|
|
assert.equal(lightColors.bg, '#FFFFFF');
|
|
assert.equal(lightColors.surface, '#F7F8FA');
|
|
assert.equal(lightColors.border, '#E3E7ED');
|
|
assert.equal(lightColors.text, '#101828');
|
|
assert.equal(lightColors.text2, '#667085');
|
|
assert.equal(lightColors.success, '#12B76A');
|
|
assert.equal(lightColors.warning, '#F79009');
|
|
assert.equal(lightColors.error, '#F04438');
|
|
|
|
// Dark 模式颜色
|
|
assert.equal(darkColors.primary, '#4D8DFF');
|
|
assert.equal(darkColors.primarySoft, '#102A4D');
|
|
assert.equal(darkColors.ai, '#9B8CFF');
|
|
assert.equal(darkColors.bg, '#0B0D10');
|
|
assert.equal(darkColors.surface, '#12151A');
|
|
assert.equal(darkColors.border, '#262B33');
|
|
assert.equal(darkColors.text, '#F2F4F7');
|
|
assert.equal(darkColors.text2, '#98A2B3');
|
|
assert.equal(darkColors.success, '#32D583');
|
|
assert.equal(darkColors.warning, '#FDB022');
|
|
assert.equal(darkColors.error, '#F97066');
|
|
});
|
|
|
|
test('2. admin/src/style/tokens.ts - 间距、圆角与排版校验', () => {
|
|
// 间距 4, 8, 12, 16, 24, 32, 48, 64
|
|
assert.equal(spacing[4], '4px');
|
|
assert.equal(spacing[8], '8px');
|
|
assert.equal(spacing[12], '12px');
|
|
assert.equal(spacing[16], '16px');
|
|
assert.equal(spacing[24], '24px');
|
|
assert.equal(spacing[32], '32px');
|
|
assert.equal(spacing[48], '48px');
|
|
assert.equal(spacing[64], '64px');
|
|
|
|
// 圆角 button 12px, card 16px, modal 20px
|
|
assert.equal(radius.button, '12px');
|
|
assert.equal(radius.card, '16px');
|
|
assert.equal(radius.modal, '20px');
|
|
|
|
// 阴影与排版
|
|
assert.equal(typography.shadow, '0 1px 2px rgba(16,24,40,0.04)');
|
|
assert.equal(typography.lineHeight.body, 1.6);
|
|
assert.equal(typography.lineHeight.title, 1.25);
|
|
assert.equal(typography.lineHeight.arabic, 1.7);
|
|
});
|
|
|
|
test('3. admin/src/style/tokens.ts - CSS 变量生成辅助函数', () => {
|
|
const lightVars = getCssVariables('light');
|
|
assert.ok(lightVars['--omni-color-primary'] === '#0B5CFF');
|
|
assert.ok(lightVars['--omni-color-bg'] === '#FFFFFF');
|
|
assert.ok(lightVars['--omni-radius-card'] === '16px');
|
|
|
|
const darkVars = getCssVariables('dark');
|
|
assert.ok(darkVars['--omni-color-primary'] === '#4D8DFF');
|
|
assert.ok(darkVars['--omni-color-bg'] === '#0B0D10');
|
|
});
|
|
|
|
test('4. admin/src/locale/omni.ts - 多语言字典与 RTL 支持', () => {
|
|
const locales = ['zh-CN', 'en-US', 'ar-SA', 'es-ES', 'de-DE', 'fr-FR', 'ja-JP'] as const;
|
|
const requiredKeys = [
|
|
'common.confirm',
|
|
'common.cancel',
|
|
'card.save_contact',
|
|
'card.exchange',
|
|
'card.ai_chat',
|
|
'radar.online_visitor',
|
|
] as const;
|
|
for (const loc of locales) {
|
|
assert.ok(omniLocales[loc], `应当包含语言包: ${loc}`);
|
|
for (const key of requiredKeys) {
|
|
assert.ok(omniLocales[loc].messages[key], `语言 ${loc} 缺少词条 ${key}`);
|
|
}
|
|
}
|
|
|
|
// 阿拉伯语 RTL 校验
|
|
assert.equal(omniLocales['ar-SA'].dir, 'rtl');
|
|
assert.equal(isRtl('ar-SA'), true);
|
|
assert.equal(omniLocales['zh-CN'].dir, 'ltr');
|
|
assert.equal(isRtl('zh-CN'), false);
|
|
assert.equal(isRtl('en-US'), false);
|
|
assert.equal(omniLocales['es-ES'].dir, 'ltr');
|
|
assert.equal(omniLocales['de-DE'].dir, 'ltr');
|
|
assert.equal(omniLocales['fr-FR'].dir, 'ltr');
|
|
assert.equal(omniLocales['ja-JP'].dir, 'ltr');
|
|
|
|
// 获取文案辅助函数
|
|
assert.equal(getOmniText('zh-CN', 'card.save_contact'), '保存到通讯录');
|
|
assert.equal(getOmniText('en-US', 'card.save_contact'), 'Save Contact');
|
|
assert.equal(getOmniText('ar-SA', 'card.save_contact'), 'حفظ جهة الاتصال');
|
|
const jaSaveContact = getOmniText('ja-JP', 'card.save_contact');
|
|
assert.ok(jaSaveContact.length > 0);
|
|
assert.notEqual(jaSaveContact, '保存到通讯录');
|
|
|
|
// 禁止包含任何 emoji 校验
|
|
const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u;
|
|
for (const loc of locales) {
|
|
for (const [key, val] of Object.entries(omniLocales[loc].messages)) {
|
|
assert.ok(!emojiRegex.test(val), `语言 ${loc} 的词条 ${key} 严禁含有 emoji: ${val}`);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('5. mpuniapp/common/tokens.uts - uni-app x 跨端 Token 校验', () => {
|
|
const utsPath = path.resolve('m:/2026项目/CRMmp/mpuniapp/common/tokens.uts');
|
|
assert.ok(fs.existsSync(utsPath), 'tokens.uts 文件必须存在');
|
|
|
|
const content = fs.readFileSync(utsPath, 'utf-8');
|
|
|
|
// 必须导出 utsLightColors, utsDarkColors, utsSpacing, utsRadius, utsTypography
|
|
assert.ok(content.includes('export const utsLightColors: UtsColorTokens ='));
|
|
assert.ok(content.includes('export const utsDarkColors: UtsColorTokens ='));
|
|
assert.ok(content.includes('export const utsSpacing: UtsSpacing ='));
|
|
assert.ok(content.includes('export const utsRadius: UtsRadius ='));
|
|
assert.ok(content.includes('export const utsTypography: UtsTypography ='));
|
|
|
|
// 校验关键值 (严格遵守 AGENTS.md 权威 Design Token)
|
|
assert.ok(content.includes("'#0088FF'"));
|
|
assert.ok(content.includes("'#3894FF'"));
|
|
assert.ok(content.includes("button: '14px'"));
|
|
assert.ok(content.includes("card: '20px'"));
|
|
assert.ok(content.includes("modal: '24px'"));
|
|
assert.ok(content.includes("space16: '16px'"));
|
|
});
|
|
|
|
test('6. admin/src/locale/index.ts - 成功合并 omni 词条且支持 ar-SA', () => {
|
|
assert.ok(defaultI18n['zh-CN']['card.save_contact'] === '保存到通讯录');
|
|
assert.ok(defaultI18n['en-US']['card.save_contact'] === 'Save Contact');
|
|
assert.ok(defaultI18n['ar-SA']['card.save_contact'] === 'حفظ جهة الاتصال');
|
|
assert.ok(defaultI18n['ar-SA']['radar.online_visitor'] === 'الزوار الحاليون');
|
|
assert.equal(defaultI18n['zh-CN']['common.app_name'], 'OmniCard');
|
|
});
|
|
|
|
|