|
|
@@ -1079,7 +1079,24 @@ async function testActivityFlow() {
|
|
|
r = await apiCall('POST', '/api/admin/activity/list', {}, t2);
|
|
|
record(F, 'admin', '管理端活动列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'admin activities OK' : r.raw);
|
|
|
|
|
|
- // 活动管理员:管家后台管理
|
|
|
+ // 活动会员价字段验证(需求:活动新增 memberPrice)
|
|
|
+ var actListData = (r.body && r.body.code === 200 && r.body.data) ? r.body.data : null;
|
|
|
+ var actList = actListData && actListData.records ? actListData.records : (actListData && Array.isArray(actListData) ? actListData : (actListData && actListData.list ? actListData.list : []));
|
|
|
+ var hasMemberPrice = actList.length > 0 && actList[0].memberPrice !== undefined;
|
|
|
+ record(F, 'admin', '活动会员价字段', hasMemberPrice,
|
|
|
+ hasMemberPrice ? 'memberPrice=' + actList[0].memberPrice : 'no activities or missing memberPrice');
|
|
|
+ // 活动详情验证 memberPrice
|
|
|
+ if (actList.length > 0 && actList[0].id) {
|
|
|
+ r = await apiCall('POST', '/api/admin/activity/detail', { id: actList[0].id }, t2);
|
|
|
+ var detailOk = r.status === 200 && r.body && r.body.code === 200 && r.body.data;
|
|
|
+ var hasDetailMemberPrice = detailOk && r.body.data.memberPrice !== undefined;
|
|
|
+ record(F, 'admin', '活动详情会员价', hasDetailMemberPrice,
|
|
|
+ hasDetailMemberPrice ? 'memberPrice=' + r.body.data.memberPrice : 'detail missing memberPrice');
|
|
|
+ } else {
|
|
|
+ skip(F, 'admin', '活动详情会员价', '无活动数据');
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
r = await apiCall('POST', '/api/admin/butler/list', {}, t2);
|
|
|
record(F, 'admin', '管家列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'butler list OK' : r.raw);
|
|
|
}
|
|
|
@@ -1108,10 +1125,39 @@ async function testContentFlow() {
|
|
|
r = await apiCall('POST', '/api/articles/daily-tip', {}, t);
|
|
|
record(F, 'parent', '每日贴士', r.status === 200 && r.body && r.body.code === 200, r.body ? 'daily tip OK' : r.raw);
|
|
|
|
|
|
+ // 文章详情 + 阅读时长字段(需求:阅读时长功能)
|
|
|
+ var artList = (r.body && r.body.code === 200 && r.body.data && r.body.data.records) ? r.body.data.records : [];
|
|
|
+ // 上面 r 是 daily-tip 的响应,重新取文章列表
|
|
|
+ var artListResp = await apiCall('POST', '/api/articles/list', {}, t);
|
|
|
+ var artData = (artListResp.body && artListResp.body.code === 200 && artListResp.body.data) ? artListResp.body.data : null;
|
|
|
+ var arts = artData && artData.records ? artData.records : (Array.isArray(artData) ? artData : []);
|
|
|
+ if (arts.length > 0 && arts[0].id) {
|
|
|
+ r = await apiCall('POST', '/api/articles/detail', { id: arts[0].id }, t);
|
|
|
+ var artDetailOk = r.status === 200 && r.body && r.body.code === 200 && r.body.data;
|
|
|
+ record(F, 'parent', '文章详情', artDetailOk, artDetailOk ? 'detail OK' : r.raw);
|
|
|
+ // readTime 字段(需求:阅读时长)
|
|
|
+ var hasReadTime = artDetailOk && r.body.data.readTime !== undefined;
|
|
|
+ record(F, 'parent', '文章阅读时长字段', hasReadTime,
|
|
|
+ hasReadTime ? 'readTime=' + r.body.data.readTime : 'missing readTime');
|
|
|
+
|
|
|
+ // 上报阅读时长(需求:阅读时长统计)
|
|
|
+ r = await apiCall('POST', '/api/articles/record-read', { id: arts[0].id, childId: 1003, durationSeconds: 30 }, t);
|
|
|
+ record(F, 'parent', '上报阅读时长', r.status === 200 && r.body && r.body.code === 200, r.body ? 'recorded' : r.raw);
|
|
|
+ } else {
|
|
|
+ skip(F, 'parent', '文章详情', '无文章数据');
|
|
|
+ skip(F, 'parent', '文章阅读时长字段', '无文章数据');
|
|
|
+ skip(F, 'parent', '上报阅读时长', '无文章数据');
|
|
|
+ }
|
|
|
+
|
|
|
// 分享
|
|
|
r = await apiCall('POST', '/api/share/my', {}, t);
|
|
|
record(F, 'parent', '我的分享', r.status === 200 && r.body && r.body.code === 200, r.body ? 'my shares OK' : r.raw);
|
|
|
|
|
|
+ // 分享海报 — 生成小程序码(需求 855a8df5)
|
|
|
+ r = await apiCall('POST', '/api/share/qrcode', { page: 'pages/activity/activity-detail/activity-detail', scene: 'id=1' }, t);
|
|
|
+ record(F, 'parent', '分享小程序码', r.status === 200 && r.body && r.body.code === 200,
|
|
|
+ (r.body && r.body.data) ? 'qrcode OK' : r.raw);
|
|
|
+
|
|
|
// 媒体(使用真实存在的taskId)
|
|
|
r = await apiCall('POST', '/api/media/upload-text', { taskId: 192, creatorId: 1002, content: 'Test media text' }, t);
|
|
|
record(F, 'parent', '保存文字记录', r.status === 200 && r.body && r.body.code === 200, r.body ? 'text upload OK' : r.body ? r.body.message : r.raw);
|
|
|
@@ -1121,6 +1167,18 @@ async function testContentFlow() {
|
|
|
if (tA) {
|
|
|
r = await apiCall('POST', '/api/admin/articles/list', {}, tA);
|
|
|
record(F, 'admin', '文章管理列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'admin articles OK' : r.raw);
|
|
|
+
|
|
|
+ // 文章审核状态过滤(需求 ab9f4a44:admin/articles/list 支持 auditStatus 参数)
|
|
|
+ r = await apiCall('POST', '/api/admin/articles/list', { auditStatus: 'approved' }, tA);
|
|
|
+ record(F, 'admin', '文章按审核状态过滤', r.status === 200 && r.body && r.body.code === 200,
|
|
|
+ r.body ? 'auditStatus filter OK' : r.raw);
|
|
|
+
|
|
|
+ // 图片上传端点存在性验证(需求 598e7601 + c697fb7b:图片上传+5M限制)
|
|
|
+ // 不发文件只验证端点可达(无文件应返回错误而非 404)
|
|
|
+ r = await apiCall('POST', '/api/admin/articles/upload/image', {}, tA);
|
|
|
+ var uploadEndpointExists = r.status === 200 && r.body && (r.body.code === 500 || r.body.code === 200);
|
|
|
+ record(F, 'admin', '图片上传端点', uploadEndpointExists,
|
|
|
+ r.body ? 'upload endpoint reachable: ' + (r.body.message || '') : r.raw);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1332,8 +1390,41 @@ async function testCircleFlow() {
|
|
|
record(F, 'parent', '联系人列表', r.status === 200 && r.body && r.body.code === 200, r.body && r.body.data ? 'contacts OK' : r.raw);
|
|
|
|
|
|
// 家庭挑战
|
|
|
- r = await apiCall('POST', '/api/health/challenge/list', {}, t);
|
|
|
- record(F, 'parent', '家庭挑战列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'challenges OK' : r.raw);
|
|
|
+ // 家庭挑战 — 双目标模式字段验证
|
|
|
+ // 先从 /api/family/user/info 获取 familyId
|
|
|
+ var familyId = null;
|
|
|
+ var infoResp = await apiCall('POST', '/api/family/user/info', {}, t);
|
|
|
+ if (infoResp.body && infoResp.body.code === 200 && infoResp.body.data) {
|
|
|
+ familyId = infoResp.body.data.familyId || infoResp.body.data.familyId;
|
|
|
+ }
|
|
|
+ // 如果上面没拿到,用固定测试值 2001(与文件其他地方一致,如 line 333/462/520)
|
|
|
+ if (!familyId) familyId = 2001;
|
|
|
+
|
|
|
+ r = await apiCall('POST', '/api/health/challenge/list', { familyId: familyId }, t);
|
|
|
+ var challengeOk = r.status === 200 && r.body && r.body.code === 200;
|
|
|
+ record(F, 'parent', '家庭挑战列表', challengeOk, challengeOk ? 'list OK' : r.raw);
|
|
|
+ // 验证双目标字段
|
|
|
+ var challenges = (r.body && r.body.data) ? r.body.data : [];
|
|
|
+ var hasTargetFields = challenges.length > 0 && challenges[0].targetMode && challenges[0].targetValue !== undefined;
|
|
|
+ record(F, 'parent', '挑战目标模式字段', challengeOk && hasTargetFields,
|
|
|
+ hasTargetFields ? 'targetMode=' + challenges[0].targetMode + ' targetValue=' + challenges[0].targetValue : 'no active challenges or missing fields');
|
|
|
+ // 验证进度字段
|
|
|
+ var hasProgressFields = challenges.length > 0 && challenges[0].totalProgress !== undefined && Array.isArray(challenges[0].memberProgress);
|
|
|
+ record(F, 'parent', '挑战进度字段', challengeOk && hasProgressFields,
|
|
|
+ hasProgressFields ? 'totalProgress=' + challenges[0].totalProgress + ' memberProgress=' + challenges[0].memberProgress.length + '人' : 'no progress fields');
|
|
|
+
|
|
|
+ // 历史挑战
|
|
|
+ r = await apiCall('POST', '/api/health/challenge/history', { familyId: familyId }, t);
|
|
|
+ record(F, 'parent', '挑战历史', r.status === 200 && r.body && r.body.code === 200, r.body ? 'history OK' : r.raw);
|
|
|
+
|
|
|
+ // 进度上报(如存在 active 挑战,上报 delta=1)
|
|
|
+ if (challenges.length > 0) {
|
|
|
+ var ch = challenges[0];
|
|
|
+ r = await apiCall('POST', '/api/health/challenge/progress', { challengeId: ch.id, childId: 1003, delta: 1 }, t);
|
|
|
+ record(F, 'parent', '挑战进度上报', r.status === 200 && r.body && r.body.code === 200, r.body ? 'progress reported' : r.raw);
|
|
|
+ } else {
|
|
|
+ skip(F, 'parent', '挑战进度上报', '无活跃挑战');
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// ================================================================
|