120 行
5.1 KiB
TypeScript
120 行
5.1 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
describe('ActivityListContent (TDD 测试套件: 活动大厅陪吃·陪唱·陪喝内容与零Emoji校验)', () => {
|
|
const rootDir = path.resolve(__dirname, '../../');
|
|
const mockFilePath = path.join(rootDir, 'pwuniapp', 'common', 'mock.js');
|
|
const listVuePath = path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'list.vue');
|
|
const emojiRegex = /(?:\p{Extended_Pictographic}|\p{Emoji_Presentation}|[\u2600-\u27BF])/u;
|
|
|
|
describe('1. mock.js 中 ACTIVITIES_LIST 内容规范校验', () => {
|
|
it('活动列表中陪吃·陪唱·陪喝三大核心品类应占主导地位 (>= 80%)', () => {
|
|
const mockContent = fs.readFileSync(mockFilePath, 'utf-8');
|
|
|
|
// 提取 ACTIVITIES_LIST 数组对象文本
|
|
const listMatch = mockContent.match(/export const ACTIVITIES_LIST\s*=\s*(\[[\s\S]*?\n\];)/);
|
|
expect(listMatch).not.toBeNull();
|
|
|
|
// 解析执行提取对象
|
|
const evalList = new Function(`return ${listMatch![1].replace(/;\s*$/, '')}`)();
|
|
expect(Array.isArray(evalList)).toBe(true);
|
|
expect(evalList.length).toBeGreaterThanOrEqual(4);
|
|
|
|
const mainCategories = ['美食陪吃', '同城陪唱', '下午茶陪喝', '同城微醺'];
|
|
const mainCategoryCount = evalList.filter((item: any) =>
|
|
mainCategories.includes(item.game || item.category)
|
|
).length;
|
|
|
|
const mainRatio = mainCategoryCount / evalList.length;
|
|
expect(mainRatio).toBeGreaterThanOrEqual(0.8);
|
|
});
|
|
|
|
it('所有活动必须包含合法公开场所、时间与发起人信息', () => {
|
|
const mockContent = fs.readFileSync(mockFilePath, 'utf-8');
|
|
const listMatch = mockContent.match(/export const ACTIVITIES_LIST\s*=\s*(\[[\s\S]*?\n\];)/);
|
|
const evalList = new Function(`return ${listMatch![1].replace(/;\s*$/, '')}`)();
|
|
|
|
for (const item of evalList) {
|
|
expect(item.id).toBeDefined();
|
|
expect(item.title).toBeDefined();
|
|
expect(item.location).toBeDefined();
|
|
expect(item.startTime).toBeDefined();
|
|
expect(item.creatorNickname).toBeDefined();
|
|
expect(item.creatorAvatar).toBeDefined();
|
|
expect(['AA', 'PROJECT']).toContain(item.payType);
|
|
|
|
// 验证地点均为公开合法商圈/门店,不能有私人住宅等违规词
|
|
expect(item.location).not.toMatch(/(酒店客房|私人住宅|私密公寓)/);
|
|
}
|
|
});
|
|
|
|
it('ACTIVITIES_LIST 数据中严禁包含任何系统 Emoji 字符', () => {
|
|
const mockContent = fs.readFileSync(mockFilePath, 'utf-8');
|
|
const listMatch = mockContent.match(/export const ACTIVITIES_LIST\s*=\s*(\[[\s\S]*?\n\];)/);
|
|
expect(listMatch).not.toBeNull();
|
|
|
|
const listContent = listMatch![1];
|
|
const lines = listContent.split('\n');
|
|
const violations: string[] = [];
|
|
|
|
lines.forEach((line, idx) => {
|
|
if (emojiRegex.test(line)) {
|
|
violations.push(`Line ${idx + 1}: ${line.trim()}`);
|
|
}
|
|
});
|
|
|
|
expect(violations).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('2. pages/activity/list.vue 页面规范校验', () => {
|
|
it('活动列表页面模板与样式中严禁包含任何 Emoji 字符', () => {
|
|
const content = fs.readFileSync(listVuePath, 'utf-8');
|
|
const lines = content.split('\n');
|
|
const violations: string[] = [];
|
|
|
|
lines.forEach((line, idx) => {
|
|
if (emojiRegex.test(line)) {
|
|
violations.push(`Line ${idx + 1}: ${line.trim()}`);
|
|
}
|
|
});
|
|
|
|
expect(violations).toEqual([]);
|
|
});
|
|
|
|
it('页面应包含陪吃·陪唱·陪喝相关的分类快捷切换或展示逻辑', () => {
|
|
const content = fs.readFileSync(listVuePath, 'utf-8');
|
|
// 验证包含美食陪吃、同城陪唱等核心品类关键词
|
|
expect(content).toMatch(/(美食陪吃|陪吃)/);
|
|
expect(content).toMatch(/(同城陪唱|陪唱)/);
|
|
expect(content).toMatch(/(下午茶陪喝|陪喝)/);
|
|
});
|
|
});
|
|
|
|
describe('3. 活动大厅综合搜索框功能与双主题规范门禁 (TDD)', () => {
|
|
it('页面必须包含顶部综合搜索框组件并支持关键词双向绑定', () => {
|
|
const content = fs.readFileSync(listVuePath, 'utf-8');
|
|
expect(content).toContain('header-search');
|
|
expect(content).toContain('search-input');
|
|
expect(content).toContain('searchKeyword');
|
|
});
|
|
|
|
it('搜索过滤逻辑必须同时支持标题、商圈地点、品类与局长多维度匹配', () => {
|
|
const content = fs.readFileSync(listVuePath, 'utf-8');
|
|
// 必须包含基于 searchKeyword 的模糊匹配逻辑
|
|
expect(content).toContain('matchKeyword');
|
|
expect(content).toMatch(/a\.title.*includes/);
|
|
expect(content).toMatch(/a\.location.*includes/);
|
|
expect(content).toMatch(/a\.creatorNickname.*includes/);
|
|
});
|
|
|
|
it('搜索框在 theme-warm 浅色暖阳晨曦模式下必须适配纯白背景与深色文本', () => {
|
|
const content = fs.readFileSync(listVuePath, 'utf-8');
|
|
const warmSection = content.split('.activity-container.theme-warm')[1] || '';
|
|
expect(warmSection).toContain('.header-search');
|
|
expect(warmSection).toContain('.search-box');
|
|
expect(warmSection).toContain('#FFFFFF');
|
|
});
|
|
});
|
|
});
|