// 已读取AGENTS.md import * as fs from 'fs'; import * as path from 'path'; /** * 列表分页闸门:订单 / 消息通知 / 组局 * 要求:服务端支持 page/pageSize 并返回 total/hasMore;不传 page 时保持旧数组格式兼容; * 小程序三页必须支持触底加载更多。 */ describe('列表分页(订单 / 通知 / 组局)', () => { const root = path.resolve(__dirname, '../../'); const read = (rel: string) => fs.readFileSync(path.join(root, rel), 'utf-8'); const repo = read('server/src/db/repository.ts'); const indexCode = read('server/src/index.ts'); const api = read('pwuniapp/common/api.js'); const orderList = read('pwuniapp/pages/order/list.vue'); const notifications = read('pwuniapp/pages/user/notifications.vue'); const activityList = read('pwuniapp/pages/activity/list.vue'); it('仓储层必须使用 LIMIT/OFFSET 分页,而不是一次拉全量', () => { expect(repo).toContain('LIMIT ${pageSize} OFFSET ${offset}'); expect(repo).toContain('LIMIT ${take} OFFSET ${skip}'); expect(repo).toContain('async countOrders('); expect(repo).toContain('async countOrdersForUser('); expect(repo).toContain('async countActivities('); expect(repo).toContain('async getUserNotificationTotal('); }); it('接口必须返回 total/hasMore,未传 page 时保持旧数组格式', () => { expect(indexCode).toContain("if (Number(req.query.page) > 0)"); expect(indexCode).toContain('hasMore: (page - 1) * pageSize'); // 旧调用(管理后台 / 工作台)不传 page 仍拿数组 expect(indexCode).toContain('const paged = Number(req.query.page) > 0;'); expect(indexCode).toContain('data: orders'); expect(indexCode).toContain('data: acts'); }); it('小程序 API 层传递分页参数并保持旧调用兼容', () => { expect(api).toContain('page=${Math.floor(Number(options.page))}'); expect(api).toContain('pageSize=${Math.floor(Number(options.pageSize) || 20)}'); expect(api).toContain("return paged ? { list: [], total: 0, page: 1, pageSize: 20, hasMore: false } : [];"); expect(api).toContain('if (Number(extra.page) > 0)'); }); it('订单 / 通知 / 组局页面必须支持触底加载更多', () => { expect(orderList).toContain('onReachBottom'); expect(orderList).toContain('loadLiveOrders(false)'); expect(notifications).toContain('@scrolltolower="loadMore"'); expect(notifications).toContain('loadData(false)'); expect(activityList).toContain('onReachBottom'); expect(activityList).toContain('fetchLiveActivities(false)'); }); it('筛选与搜索必须下推到服务端,避免只过滤当前页造成漏数据', () => { expect(orderList).toContain('status: currentTab.value'); expect(activityList).toContain('keyword: searchKeyword.value.trim()'); expect(activityList).toContain('payType: currentTab.value'); expect(activityList).toContain('creatorId: currentTab.value'); }); });