文件
OmniCard/mpuniapp/tests/cases-articles-ui.test.ts

94 行
4.4 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
const MP_ROOT = path.resolve('m:/2026项目/CRMmp/mpuniapp');
const casesPath = path.join(MP_ROOT, 'pages/owner/card/cases.uvue');
const articlesPath = path.join(MP_ROOT, 'pages/owner/card/articles.uvue');
test('1. cases.uvue 和 articles.uvue 文件必须存在', () => {
assert.ok(fs.existsSync(casesPath), '必须存在 cases.uvue');
assert.ok(fs.existsSync(articlesPath), '必须存在 articles.uvue');
});
test('2. 零 Emoji 违规审查 (严禁使用 Emoji 作为功能图标或排版内容)', () => {
const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u;
const casesContent = fs.readFileSync(casesPath, 'utf-8');
const articlesContent = fs.readFileSync(articlesPath, 'utf-8');
assert.equal(emojiRegex.test(casesContent), false, 'cases.uvue 严禁含有 Emoji');
assert.equal(emojiRegex.test(articlesContent), false, 'articles.uvue 严禁含有 Emoji');
});
test('3. 底部悬浮主 CTA 栏适配移动端视口安全区 (env(safe-area-inset-bottom))', () => {
const casesContent = fs.readFileSync(casesPath, 'utf-8');
const articlesContent = fs.readFileSync(articlesPath, 'utf-8');
assert.ok(
casesContent.includes('env(safe-area-inset-bottom)'),
'cases.uvue 必须适配 safe-area-inset-bottom'
);
assert.ok(
articlesContent.includes('env(safe-area-inset-bottom)'),
'articles.uvue 必须适配 safe-area-inset-bottom'
);
});
test('4. 表单输入框与多行文本框符合移动端 16px 防缩放规范', () => {
const casesContent = fs.readFileSync(casesPath, 'utf-8');
const articlesContent = fs.readFileSync(articlesPath, 'utf-8');
assert.ok(casesContent.includes('font-size: 16px;'), 'cases.uvue 输入框必须使用 16px');
assert.ok(articlesContent.includes('font-size: 16px;'), 'articles.uvue 输入框必须使用 16px');
});
test('5. 核心操作按钮触控热区保证 (min-height >= 44px 或 height >= 44px)', () => {
const casesContent = fs.readFileSync(casesPath, 'utf-8');
const articlesContent = fs.readFileSync(articlesPath, 'utf-8');
assert.ok(casesContent.includes('min-height: 44px;'), 'cases.uvue 按钮必须保证触控高度 >= 44px');
assert.ok(articlesContent.includes('min-height: 44px;'), 'articles.uvue 按钮必须保证触控高度 >= 44px');
});
test('6. 必须复用 components/image-uploader/image-uploader.uvue', () => {
const casesContent = fs.readFileSync(casesPath, 'utf-8');
const articlesContent = fs.readFileSync(articlesPath, 'utf-8');
assert.ok(
casesContent.includes("import ImageUploader from '../../../components/image-uploader/image-uploader.uvue'"),
'cases.uvue 必须复用 image-uploader 组件'
);
assert.ok(
articlesContent.includes("import ImageUploader from '../../../components/image-uploader/image-uploader.uvue'"),
'articles.uvue 必须复用 image-uploader 组件'
);
});
test('7. pages.json 中必须注册 cases 与 articles 路由', () => {
const pagesJsonPath = path.join(MP_ROOT, 'pages.json');
const pagesJson = JSON.parse(fs.readFileSync(pagesJsonPath, 'utf-8'));
const routes = pagesJson.pages.map((p: any) => p.path);
assert.ok(routes.includes('pages/owner/card/cases'), 'pages.json 必须注册 cases 页面');
assert.ok(routes.includes('pages/owner/card/articles'), 'pages.json 必须注册 articles 页面');
});
test('8. edit.uvue 中必须包含 cases 与 articles 的 Bento 导航入口', () => {
const editPath = path.join(MP_ROOT, 'pages/owner/card/edit.uvue');
const editContent = fs.readFileSync(editPath, 'utf-8');
assert.ok(editContent.includes('handleGoCases'), 'edit.uvue 必须提供 handleGoCases');
assert.ok(editContent.includes('handleGoArticles'), 'edit.uvue 必须提供 handleGoArticles');
assert.ok(editContent.includes('pages/owner/card/cases'), 'edit.uvue 必须跳转至 cases 页面');
assert.ok(editContent.includes('pages/owner/card/articles'), 'edit.uvue 必须跳转至 articles 页面');
});
test('9. index.uvue 中必须提供快捷管理入口', () => {
const indexPath = path.join(MP_ROOT, 'pages/owner/card/index.uvue');
const indexContent = fs.readFileSync(indexPath, 'utf-8');
assert.ok(indexContent.includes('handleOpenCases'), 'index.uvue 必须提供 handleOpenCases');
assert.ok(indexContent.includes('handleOpenArticles'), 'index.uvue 必须提供 handleOpenArticles');
});