import assert from 'node:assert/strict' import { existsSync, readFileSync } from 'node:fs' import { resolve } from 'node:path' const root = resolve(import.meta.dirname, '..') const read = (path) => readFileSync(resolve(root, path), 'utf8') const app = JSON.parse(read('miniapp/app.json')) const corePages = [ 'index', 'discover', 'messages', 'activity', 'mine', 'matchmaker', 'counseling-intro', 'premarital-intro', 'content', 'anti-fraud', 'service-station', ] const quickEntryCodes = [ 'find_object', 'matchmaker', 'activities', 'counseling', 'classroom', 'premarital', 'anti_fraud', 'service_station', ] assert.deepEqual( app.tabBar.list.map((item) => item.text), ['首页', '找对象', '消息', '活动', '我的'], '五个 Tab 的顺序发生偏移', ) for (const page of corePages) { const base = `miniapp/pages/${page}/${page}` for (const extension of ['.json', '.wxml', '.wxss']) { assert.ok(existsSync(resolve(root, base + extension)), `${page}${extension} 不存在`) } const template = read(base + '.wxml') assert.match(template, /reference-page/, `${page} 未接入参考图页面骨架`) assert.doesNotMatch(template, /[\u{1F300}-\u{1FAFF}]/u, `${page} 含 Emoji`) } const homeLogic = read('miniapp/pages/index/index.ts') let previousIndex = -1 for (const code of quickEntryCodes) { const index = homeLogic.indexOf(code) assert.ok(index >= 0, `首页缺少入口 ${code}`) assert.ok(index > previousIndex, `首页入口 ${code} 顺序错误`) previousIndex = index } const discoverTemplate = read('miniapp/pages/discover/discover.wxml') assert.match(discoverTemplate, /discover-filter-chips/, '找对象页缺少参考图胶囊筛选区') assert.match(discoverTemplate, /candidate-list/, '找对象页缺少参考图候选人列表') assert.match(discoverTemplate, /\/assets\/icons\/ui\/search\.png/, '找对象页必须使用独立搜索图标') const messagesTemplate = read('miniapp/pages/messages/messages.wxml') const messagesLogic = read('miniapp/pages/messages/messages.js') assert.match(messagesTemplate, /message-shortcuts/, '消息页缺少四项快捷入口') assert.match(messagesTemplate, /conversation-list/, '消息页缺少会话列表容器') assert.match(messagesTemplate, /ui-conv__badge|unreadTotal/, '消息页缺少未读提示') assert.match(messagesTemplate, /互相喜欢后/, '消息页缺少无 Mutual 状态说明') assert.match(messagesLogic, /canSendMessage/, '消息页进入聊天前必须校验服务端会话能力') const activityTemplate = read('miniapp/pages/activity/activity.wxml') const activityCard = read('miniapp/components/activity-card/index.wxml') const activityLogic = read('miniapp/pages/activity/activity.js') assert.match(activityTemplate, /activity-categories/, '活动页缺少活动分类') assert.match(activityTemplate, /activity-calendar/, '活动页缺少日历入口') assert.match(activityCard, /ui-act__capacity/, '活动卡缺少人数和容量') assert.match(activityCard, /ui-act__status-action/, '活动卡缺少状态按钮') assert.doesNotMatch(activityLogic, /matchStore|to\.chat/, '活动列表不得直接创建 Match 或进入聊天') const mineTemplate = read('miniapp/pages/mine/mine.wxml') assert.match(mineTemplate, /profile-hero/, '我的页缺少个人头部') assert.match(mineTemplate, /profile-stats/, '我的页缺少四项统计') assert.match(mineTemplate, /我在善缘丹阳/, '我的页缺少公益身份卡') for (const label of ['我的红娘', '我的咨询', '我的活动', '我的预约', '账号设置']) { assert.ok(mineTemplate.includes(label), `我的页缺少入口 ${label}`) } const matchmakerTemplate = read('miniapp/pages/matchmaker/matchmaker.wxml') const matchmakerLogic = read('miniapp/pages/matchmaker/matchmaker.js') const counselingTemplate = read('miniapp/pages/counseling-intro/counseling-intro.wxml') const premaritalTemplate = read('miniapp/pages/premarital-intro/premarital-intro.wxml') for (const template of [matchmakerTemplate, counselingTemplate, premaritalTemplate]) { assert.match(template, /ui-service-hero/, 'B 组服务页必须统一使用 service-hero') } for (const label of ['公益免费', '真实匹配', '隐私保护']) { assert.ok(matchmakerTemplate.includes(label), `红娘页缺少服务承诺 ${label}`) } assert.match(matchmakerTemplate, /activeService|申请状态/, '红娘页缺少申请状态') assert.doesNotMatch(matchmakerLogic, /matchStore\.(?:like|pass)\s*\(/, '红娘不得替用户 Like 或 Pass') assert.match(counselingTemplate, /service-topics/, '咨询页缺少四项咨询主题') assert.match(counselingTemplate, /预约咨询/, '咨询页缺少预约按钮') assert.match(counselingTemplate, /服务状态/, '咨询页缺少服务状态') assert.match(premaritalTemplate, /service-topics/, '婚前辅导页缺少四项辅导主题') assert.match(premaritalTemplate, /预约辅导/, '婚前辅导页缺少预约按钮') assert.match(premaritalTemplate, /服务状态/, '婚前辅导页缺少服务状态') const theme = read('miniapp/app.wxss') for (const token of [ '--mini-night-start', '--mini-night-end', '--mini-accent-pink', '--mini-accent-coral', '--mini-card-bg', '--mini-card-radius', '--mini-shadow', ]) { assert.ok(theme.includes(token), `缺少全局 Token ${token}`) } console.log('Miniapp reference contracts passed')