// 已读取AGENTS.md import * as fs from 'fs'; import * as path from 'path'; describe('PC总后台管理端核心业务与闭环能力自动化测试 (Post Manage, Finance CSV Export, WeChat Template Config)', () => { const rootDir = path.resolve(__dirname, '../../'); const serverIndexPath = path.join(rootDir, 'server/src/index.ts'); const serverRepoPath = path.join(rootDir, 'server/src/db/repository.ts'); const serverMysqlPath = path.join(rootDir, 'server/src/db/mysql.ts'); const adminPostManageVuePath = path.join(rootDir, 'admin/arco-design-pro-vite/src/views/community/post-manage/index.vue'); const adminFinanceRecordsVuePath = path.join(rootDir, 'admin/arco-design-pro-vite/src/views/finance/records/index.vue'); const adminFinanceWithdrawVuePath = path.join(rootDir, 'admin/arco-design-pro-vite/src/views/finance/withdraw/index.vue'); const adminPlatformConfigVuePath = path.join(rootDir, 'admin/arco-design-pro-vite/src/views/safety/platform-config/index.vue'); const adminCommunityRouterPath = path.join(rootDir, 'admin/arco-design-pro-vite/src/router/routes/modules/community.ts'); describe('1. 友圈广场动态管理与置顶/状态流转/级联删除闭环验证', () => { it('数据库层必须扩展 posts 表结构并包含 is_top 与 status 字段', () => { const mysqlCode = fs.readFileSync(serverMysqlPath, 'utf-8'); expect(mysqlCode).toContain('ALTER TABLE posts ADD COLUMN is_top'); expect(mysqlCode).toContain('ALTER TABLE posts ADD COLUMN status'); }); it('仓储层 MysqlRepository 必须实现动态多维筛选、一键置顶、状态切换与评论管理', () => { const repoCode = fs.readFileSync(serverRepoPath, 'utf-8'); expect(repoCode).toContain('async getPosts('); expect(repoCode).toContain('ORDER BY is_top DESC, created_at DESC'); expect(repoCode).toContain('async togglePostTop('); expect(repoCode).toContain('async updatePostStatus('); expect(repoCode).toContain('async adminDeletePost('); expect(repoCode).toContain('async adminDeletePostComment('); }); it('后端服务 index.ts 必须注册动态管控的核心管理端 API 路由', () => { const serverCode = fs.readFileSync(serverIndexPath, 'utf-8'); expect(serverCode).toContain("app.get('/api/admin/posts'"); expect(serverCode).toContain("app.post('/api/admin/posts/:id/top'"); expect(serverCode).toContain("app.post('/api/admin/posts/:id/status'"); expect(serverCode).toContain("app.delete('/api/admin/posts/:id'"); expect(serverCode).toContain("app.delete('/api/admin/posts/comments/:commentId'"); }); it('动态管理前端视图 post-manage/index.vue 必须具备完整交互与多图预览', () => { const postManageCode = fs.readFileSync(adminPostManageVuePath, 'utf-8'); expect(postManageCode).toContain('handleToggleTop'); expect(postManageCode).toContain('handleToggleStatus'); expect(postManageCode).toContain('handleDeletePost'); expect(postManageCode).toContain('handleDeleteComment'); expect(postManageCode).toContain('a-image-preview-group'); expect(postManageCode).toContain('a-drawer'); expect(postManageCode).toContain('/api/admin/posts'); }); }); describe('2. 财务管理对账明细导出 CSV 规范校验', () => { it('资金交易流水导出必须包含 UTF-8 BOM 与标准字段', () => { const recordsFile = fs.readFileSync(adminFinanceRecordsVuePath, 'utf-8'); expect(recordsFile).toContain('exportCSV'); expect(recordsFile).toContain('\\uFEFF'); expect(recordsFile).toContain('流水号'); expect(recordsFile).toContain('交易类型'); expect(recordsFile).toContain('金额(元)'); expect(recordsFile).toContain('资金方向'); expect(recordsFile).toContain('交易对手方'); expect(recordsFile).toContain('关联业务ID'); expect(recordsFile).toContain('记账时间'); }); it('提现审核列表导出必须包含 UTF-8 BOM 与标准字段', () => { const withdrawFile = fs.readFileSync(adminFinanceWithdrawVuePath, 'utf-8'); expect(withdrawFile).toContain('exportCSV'); expect(withdrawFile).toContain('\\uFEFF'); expect(withdrawFile).toContain('提现单号'); expect(withdrawFile).toContain('申请大神'); expect(withdrawFile).toContain('大神ID'); expect(withdrawFile).toContain('提现金额(元)'); expect(withdrawFile).toContain('账户余额(元)'); expect(withdrawFile).toContain('结算渠道'); expect(withdrawFile).toContain('申请时间'); expect(withdrawFile).toContain('审核状态'); }); }); describe('3. 微信小程序订阅消息与服务通知管理配置及模拟推送', () => { it('平台配置种子与增量迁移中必须包含 message_template_rules', () => { const mysqlCode = fs.readFileSync(serverMysqlPath, 'utf-8'); expect(mysqlCode).toContain('message_template_rules'); expect(mysqlCode).toContain('orderStatusTemplateId'); expect(mysqlCode).toContain('activityJoinTemplateId'); expect(mysqlCode).toContain('withdrawSuccessTemplateId'); expect(mysqlCode).toContain('verifyCodeTemplateId'); }); it('后台平台配置面板已集成微信服务通知与模板消息 Tab 及测试推送控制台', () => { const configViewCode = fs.readFileSync(adminPlatformConfigVuePath, 'utf-8'); expect(configViewCode).toContain('message_template_rules'); expect(configViewCode).toContain('orderStatusTemplateId'); expect(configViewCode).toContain('activityJoinTemplateId'); expect(configViewCode).toContain('withdrawSuccessTemplateId'); expect(configViewCode).toContain('verifyCodeTemplateId'); expect(configViewCode).toContain('sendTestMessage'); expect(configViewCode).toContain('/api/admin/message/test-send'); }); it('后端必须提供模拟测试推送端点并正确返回结构化结果', () => { const serverCode = fs.readFileSync(serverIndexPath, 'utf-8'); expect(serverCode).toContain("app.post('/api/admin/message/test-send'"); expect(serverCode).toContain('wechatMsgId'); expect(serverCode).toContain('status'); expect(serverCode).toContain('sendTime'); }); it('管理后台路由正确注册 community 模块并挂载 post-manage', () => { expect(fs.existsSync(adminCommunityRouterPath)).toBe(true); const routerCode = fs.readFileSync(adminCommunityRouterPath, 'utf-8'); expect(routerCode).toContain('/community'); expect(routerCode).toContain('post-manage'); expect(routerCode).toContain('icon-message'); }); }); describe('4. 全流程无 Emoji 门禁合规校验', () => { it('新增的前后端代码中严禁包含任何系统 Emoji 图标字符', () => { const filesToCheck = [ adminCommunityRouterPath, adminPostManageVuePath, adminFinanceRecordsVuePath, adminFinanceWithdrawVuePath, adminPlatformConfigVuePath ]; const emojiRegex = /[\uD83C-\uDBFF\uDC00-\uDFFF\u2600-\u26FF\u2700-\u27BF]/; for (const file of filesToCheck) { const content = fs.readFileSync(file, 'utf-8'); expect(emojiRegex.test(content)).toBe(false); } }); }); });