소스 검색

test: fix 35+ flow-l1 test param issues (118→153 passed)

E2E Test Bot 1 개월 전
부모
커밋
fbb9e042c4
1개의 변경된 파일117개의 추가작업 그리고 73개의 파일을 삭제
  1. 117 73
      tests/e2e/flow-l1-tests.js

+ 117 - 73
tests/e2e/flow-l1-tests.js

@@ -40,6 +40,9 @@ var results = {
   details: []
 };
 
+// Store last API response for debug output on failure
+var lastApiResponse = null;
+
 function log(msg) {
   console.log('[TEST] ' + msg);
 }
@@ -47,6 +50,11 @@ function log(msg) {
 function record(flow, role, step, passed, detail) {
   var icon = passed ? '✅' : '❌';
   var line = icon + ' [' + flow + '] ' + role + ' | ' + step + (detail ? ' — ' + detail : '');
+  if (!passed && lastApiResponse) {
+    // Show actual error response for debugging
+    var respPreview = JSON.stringify(lastApiResponse).substring(0, 300);
+    line += ' | RESP: ' + respPreview;
+  }
   console.log(line);
   results.details.push({ flow: flow, role: role, step: step, passed: passed, detail: detail });
   if (passed) results.passed++;
@@ -100,6 +108,7 @@ function apiCall(method, endpoint, data, token) {
         var rawBody = Buffer.concat(chunks).toString();
         var parsed = null;
         try { parsed = JSON.parse(rawBody); } catch(e) { parsed = null; }
+        lastApiResponse = parsed || rawBody;
         resolve({
           status: res.statusCode,
           body: parsed,
@@ -283,12 +292,12 @@ async function testFamilyFlow() {
   r = await apiCall('POST', '/api/family/invite/qrcode', {}, t);
   record(F, 'parent', '查看邀请码', r.status === 200 && r.body && r.body.code === 200, r.body && r.body.data && r.body.data.inviteCode ? 'inviteCode=' + r.body.data.inviteCode : r.raw);
 
-  // 家庭关系问卷
-  r = await apiCall('POST', '/api/family/questionnaire/generate', {}, t);
+  // 家庭关系问卷(需要memberId)
+  r = await apiCall('POST', '/api/family/questionnaire/generate', { memberId: 1003 }, t);
   record(F, 'parent', 'AI生成问卷', r.status === 200 && r.body && r.body.code === 200, r.body ? 'questionnaire OK' : r.body ? r.body.message : r.raw);
 
-  // 关系质量
-  r = await apiCall('POST', '/api/family/relationship/scores', {}, t);
+  // 关系质量(需要familyId)
+  r = await apiCall('POST', '/api/family/relationship/scores', { familyId: 2001 }, t);
   record(F, 'parent', '关系质量评分', r.status === 200 && r.body && r.body.code === 200, r.body ? 'scores OK' : r.raw);
 
   // 互动记录
@@ -341,7 +350,7 @@ async function testTaskFlow() {
   var t2 = tokens.child;
   if (!t2) { skip(F, 'child', '所有测试', '未登录'); return; }
 
-  r = await apiCall('POST', '/api/tasks/today', {}, t2);
+  r = await apiCall('POST', '/api/tasks/today', { childId: 1003 }, t2);
   var tasks = (r.body && r.body.code === 200 && r.body.data) ? (Array.isArray(r.body.data) ? r.body.data : (r.body.data.tasks || [])) : [];
   record(F, 'child', '今日任务列表', r.status === 200 && r.body && r.body.code === 200, 'count=' + tasks.length);
 
@@ -361,8 +370,8 @@ async function testTaskFlow() {
     skip(F, 'child', '完成任务', '无可用待完成任务');
   }
 
-  // 任务历史
-  r = await apiCall('POST', '/api/tasks/history', {}, t2);
+  // 任务历史(需要childId)
+  r = await apiCall('POST', '/api/tasks/history', { childId: 1003 }, t2);
   record(F, 'child', '任务历史', r.status === 200 && r.body && r.body.code === 200, r.body ? 'history OK' : r.raw);
 
   // --- 家长:审核 ---
@@ -463,38 +472,47 @@ async function testEnergyFlow() {
   var t = tokens.parent;
   if (!t) { skip(F, 'parent', '所有测试', '未登录'); return; }
 
-  var r = await apiCall('POST', '/api/energy/overview', {}, t);
+  var r = await apiCall('POST', '/api/energy/overview', { childId: 1003 }, t);
   record(F, 'parent', '五维概览', r.status === 200 && r.body && r.body.code === 200, r.body ? 'overview OK' : r.raw);
 
   r = await apiCall('POST', '/api/energy/sandbox', {}, t);
   record(F, 'parent', '能量沙盘', r.status === 200 && r.body && r.body.code === 200, r.body ? 'sandbox OK' : r.raw);
 
-  r = await apiCall('POST', '/api/energy/logs', {}, t);
+  r = await apiCall('POST', '/api/energy/logs', { childId: 1003 }, t);
   record(F, 'parent', '能量流水', r.status === 200 && r.body && r.body.code === 200, r.body ? 'logs OK' : r.raw);
 
-  r = await apiCall('POST', '/api/energy/score-history', {}, t);
+  r = await apiCall('POST', '/api/energy/score-history', { memberId: 1003, memberType: 'child' }, t);
   record(F, 'parent', '分数历史', r.status === 200 && r.body && r.body.code === 200, r.body ? 'history OK' : r.raw);
 
-  r = await apiCall('POST', '/api/energy/family-score-history', {}, t);
+  r = await apiCall('POST', '/api/energy/family-score-history', { familyId: 2001 }, t);
   record(F, 'parent', '家庭五维聚合', r.status === 200 && r.body && r.body.code === 200, r.body ? 'family score OK' : r.raw);
 
-  // 能量发放
-  r = await apiCall('POST', '/api/energy/grant', { childId: 1003, amount: 5, reason: 'Test grant' }, t);
+  // 能量发放(需要childId + taskId + amount)先创建任务获取真实taskId
+  var r2 = await apiCall('POST', '/api/tasks/create', {
+    childId: 1003,
+    title: 'TEST-Energy-Grant',
+    description: 'Energy grant test',
+    category: 'study',
+    points: 10,
+    requireReview: false
+  }, t);
+  var realTaskId = (r2.body && r2.body.code === 200 && r2.body.data) ? r2.body.data : 1;
+  r = await apiCall('POST', '/api/energy/grant', { childId: 1003, taskId: realTaskId, amount: 5, reason: 'Test grant' }, t);
   record(F, 'parent', '发放能量', r.status === 200 && r.body && r.body.code === 200, r.body ? 'grant OK' : r.body ? r.body.message : r.raw);
 
   // 孩子维度
   var t2 = tokens.child;
   if (t2) {
-    r = await apiCall('POST', '/api/energy/overview', {}, t2);
+    r = await apiCall('POST', '/api/energy/overview', { childId: 1003 }, t2);
     record(F, 'child', '五维概览', r.status === 200 && r.body && r.body.code === 200, r.body ? 'child overview OK' : r.raw);
   }
 
-  // 维度管理
-  r = await apiCall('POST', '/api/dimension/overview', {}, t);
+  // 维度管理(需要memberId)
+  r = await apiCall('POST', '/api/dimension/overview', { memberId: 1003 }, t);
   record(F, 'parent', '维度概览', r.status === 200 && r.body && r.body.code === 200, r.body ? 'dimension overview OK' : r.raw);
 
-  // 年度能量
-  r = await apiCall('POST', '/api/zodiac/energy', {}, t);
+  // 年度能量(需要birthYear/birthMonth/birthDay作为查询参数)
+  r = await apiCall('POST', '/api/zodiac/energy?birthYear=2018&birthMonth=5&birthDay=15', {}, t);
   record(F, 'parent', '年度五维能量', r.status === 200 && r.body && r.body.code === 200, r.body ? 'zodiac energy OK' : r.raw);
 
   // 家庭收入
@@ -530,19 +548,23 @@ async function testCheckinFlow() {
   }, t);
   record(F, 'child', '运动打卡', r.status === 200 && r.body && r.body.code === 200, r.body ? 'exercise OK' : r.body ? r.body.message : r.raw);
 
-  // 饮食打卡
+  // 饮食打卡(HealthMealRecord实体,需要memberId + mealType + foodItems)
   r = await apiCall('POST', '/api/health/meal/create', {
+    memberId: 1003,
     mealType: 'lunch',
-    foods: 'rice,vegetables',
-    note: 'Test meal'
+    foodItems: 'rice,vegetables',
+    remark: 'Test meal'
   }, t);
   record(F, 'child', '饮食打卡', r.status === 200 && r.body && r.body.code === 200, r.body ? 'meal OK' : r.body ? r.body.message : r.raw);
 
-  // 睡眠打卡
+  // 睡眠打卡(HealthSleepRecord实体,需要memberId + sleepTime + wakeTime)
   r = await apiCall('POST', '/api/health/sleep/create', {
-    sleepTime: '22:00',
-    wakeTime: '07:00',
-    quality: 'good'
+    memberId: 1003,
+    sleepTime: '2026-07-27T22:00:00',
+    wakeTime: '2026-07-28T07:00:00',
+    durationMinutes: 540,
+    qualityScore: 8,
+    remark: 'Good sleep'
   }, t);
   record(F, 'child', '睡眠打卡', r.status === 200 && r.body && r.body.code === 200, r.body ? 'sleep OK' : r.body ? r.body.message : r.raw);
 
@@ -613,8 +635,8 @@ async function testGrowthFlow() {
     record(F, 'parent', '档案详情', r.status === 200 && r.body && r.body.code === 200, r.body ? 'detail OK' : r.raw);
   }
 
-  // 生长记录
-  r = await apiCall('POST', '/api/health/growth/list', {}, t);
+  // 生长记录(需要memberId)
+  r = await apiCall('POST', '/api/health/growth/list', { memberId: 1003 }, t);
   record(F, 'parent', '生长记录列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'growth list OK' : r.raw);
 
   r = await apiCall('POST', '/api/health/growth/create', {
@@ -625,11 +647,15 @@ async function testGrowthFlow() {
   }, t);
   record(F, 'parent', '创建生长记录', r.status === 200 && r.body && r.body.code === 200, r.body ? 'growth create OK' : r.body ? r.body.message : r.raw);
 
-  // 成长计划
+  // 成长计划(GrowthPlan实体,需要planTitle+planContent+durationMonths+status+startDate+endDate)
   r = await apiCall('POST', '/api/growth/plan/create', {
     childId: 1003,
-    title: 'Test Growth Plan',
-    goals: 'Improve reading skills'
+    planTitle: 'Test Growth Plan',
+    planContent: 'Improve reading skills',
+    durationMonths: 6,
+    status: 'active',
+    startDate: '2026-07-01',
+    endDate: '2027-01-01'
   }, t);
   record(F, 'parent', '创建成长计划', r.status === 200 && r.body && r.body.code === 200, r.body ? 'plan create OK' : r.body ? r.body.message : r.raw);
 
@@ -660,7 +686,7 @@ async function testDanFlow() {
   r = await apiCall('POST', '/api/dan-assessment/material/active', {}, t);
   record(F, 'parent', '启用材料', r.status === 200 && r.body && r.body.code === 200, r.body ? 'active material OK' : r.raw);
 
-  r = await apiCall('POST', '/api/dan-assessment/family/config', {}, t);
+  r = await apiCall('POST', '/api/dan-assessment/family/config?familyId=2001', {}, t);
   record(F, 'parent', '家庭测评配置', r.status === 200 && r.body && r.body.code === 200, r.body ? 'family config OK' : r.raw);
 
   // 额度
@@ -679,19 +705,24 @@ async function testDanFlow() {
   record(F, 'parent', '评估师列表', r.status === 200 && r.body && r.body.code === 200, r.body && r.body.data ? 'assessors=' + (Array.isArray(r.body.data) ? r.body.data.length : 'N/A') : r.raw);
 
   // 最新测评结果
-  r = await apiCall('POST', '/api/assessment/latest-result', {}, t);
+  r = await apiCall('POST', '/api/assessment/latest-result', { childId: 1003 }, t);
   record(F, 'parent', '最新测评结果', r.status === 200 && r.body && r.body.code === 200, r.body ? 'latest result OK' : r.raw);
 
   // 测评历史
-  r = await apiCall('POST', '/api/assessment/history', {}, t);
+  r = await apiCall('POST', '/api/assessment/history', { childId: 1003 }, t);
   record(F, 'parent', '测评历史', r.status === 200 && r.body && r.body.code === 200, r.body ? 'history OK' : r.raw);
 
-  // 我的报告
-  r = await apiCall('POST', '/api/assessment/my-results', {}, t);
-  record(F, 'parent', '我的报告', r.status === 200 && r.body && r.body.code === 200, r.body ? 'my results OK' : r.raw);
+  // 我的报告(只有指导师可以查看,改用teacher token)
+  var tTeacher = tokens.teacher;
+  if (tTeacher) {
+    r = await apiCall('POST', '/api/assessment/my-results', {}, tTeacher);
+    record(F, 'parent', '我的报告', r.status === 200 && r.body && r.body.code === 200, r.body ? 'my results OK' : r.raw);
+  } else {
+    skip(F, 'parent', '我的报告', 'teacher未登录');
+  }
 
-  // 家长自评
-  r = await apiCall('POST', '/api/parent/assessment/create', {}, t);
+  // 家长自评(需要childId + materialId,"暂无可用测评资料"为业务逻辑非bug)
+  r = await apiCall('POST', '/api/parent/assessment/create', { childId: 1003, materialId: 1 }, t);
   record(F, 'parent', '创建家长自评', r.status === 200 && r.body && r.body.code === 200, r.body ? 'self assessment OK' : r.body ? r.body.message : r.raw);
 
   r = await apiCall('POST', '/api/parent/assessment/records', {}, t);
@@ -812,24 +843,25 @@ async function testMinigameFlow() {
   r = await apiCall('POST', '/api/mini-game/schulte', {}, t);
   record(F, 'child', '舒尔特方格详情', r.status === 200 && r.body && r.body.code === 200, r.body ? 'schulte OK' : r.raw);
 
-  // 完成游戏
+  // 完成游戏(CompleteGameDTO: childId + gameCode + completionTime + score)
   r = await apiCall('POST', '/api/mini-game/complete', {
+    childId: 1003,
     gameCode: 'schulte',
     score: 95,
-    timeSpent: 30
+    completionTime: 30
   }, t);
   record(F, 'child', '完成游戏', r.status === 200 && r.body && r.body.code === 200, r.body ? 'complete OK' : r.body ? r.body.message : r.raw);
 
   // 游戏历史
-  r = await apiCall('POST', '/api/game/history', {}, t);
+  r = await apiCall('POST', '/api/game/history', { childId: 1003 }, t);
   record(F, 'child', '游戏历史', r.status === 200 && r.body && r.body.code === 200, r.body ? 'history OK' : r.raw);
 
   // 最佳成绩
-  r = await apiCall('POST', '/api/game/best', {}, t);
+  r = await apiCall('POST', '/api/game/best', { childId: 1003 }, t);
   record(F, 'child', '最佳成绩', r.status === 200 && r.body && r.body.code === 200, r.body ? 'best OK' : r.raw);
 
-  // 排行榜
-  r = await apiCall('POST', '/api/game/leaderboard', {}, t);
+  // 排行榜(需要gameCode)
+  r = await apiCall('POST', '/api/game/leaderboard', { gameCode: 'schulte' }, t);
   record(F, 'child', '排行榜', r.status === 200 && r.body && r.body.code === 200, r.body ? 'leaderboard OK' : r.raw);
 
   // 智慧数学
@@ -868,8 +900,8 @@ async function testNutritionFlow() {
   r = await apiCall('POST', '/api/nutrition/profile/get', {}, t);
   record(F, 'parent', '获取营养偏好', r.status === 200 && r.body && r.body.code === 200, r.body ? 'nutrition profile OK' : r.raw);
 
-  // 维度推荐
-  r = await apiCall('POST', '/api/recommend/dimension-products', {}, t);
+  // 维度推荐(需要dimensionCode)
+  r = await apiCall('POST', '/api/recommend/dimension-products', { dimensionCode: 'body' }, t);
   record(F, 'parent', '维度推荐商品', r.status === 200 && r.body && r.body.code === 200, r.body ? 'dimension products OK' : r.raw);
 
   // 北京知识库
@@ -888,7 +920,7 @@ async function testMindFlow() {
   var t = tokens.child;
   if (!t) { skip(F, 'child', '所有测试', '未登录'); return; }
 
-  // 情绪打卡
+  // 情绪打卡(EmotionCheckinDTO - 服务端用userId=child的userId找孩子)
   var r = await apiCall('POST', '/api/mind/checkin/create', {
     emotion: 'happy',
     intensity: 8,
@@ -896,28 +928,32 @@ async function testMindFlow() {
   }, t);
   record(F, 'child', '情绪打卡', r.status === 200 && r.body && r.body.code === 200, r.body ? 'emotion checkin OK' : r.body ? r.body.message : r.raw);
 
-  r = await apiCall('POST', '/api/mind/checkin/list', {}, t);
+  // 情绪列表(需要childId)
+  r = await apiCall('POST', '/api/mind/checkin/list', { childId: 1003 }, t);
   record(F, 'child', '情绪列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'emotion list OK' : r.raw);
 
-  r = await apiCall('POST', '/api/mind/checkin/latest', {}, t);
+  // 最新情绪(需要childId)
+  r = await apiCall('POST', '/api/mind/checkin/latest', { childId: 1003 }, t);
   record(F, 'child', '最新情绪', r.status === 200 && r.body && r.body.code === 200, r.body ? 'latest OK' : r.raw);
 
-  r = await apiCall('POST', '/api/mind/checkin/trend', {}, t);
+  // 情绪趋势(需要childId)
+  r = await apiCall('POST', '/api/mind/checkin/trend', { childId: 1003 }, t);
   record(F, 'child', '情绪趋势', r.status === 200 && r.body && r.body.code === 200, r.body ? 'trend OK' : r.raw);
 
-  r = await apiCall('POST', '/api/mind/checkin/stats', {}, t);
+  // 情绪统计(需要childId)
+  r = await apiCall('POST', '/api/mind/checkin/stats', { childId: 1003 }, t);
   record(F, 'child', '情绪统计', r.status === 200 && r.body && r.body.code === 200, r.body ? 'stats OK' : r.raw);
 
-  // 心理测评
-  r = await apiCall('POST', '/api/mind/screening/history', {}, t);
+  // 心理测评(需要childId)
+  r = await apiCall('POST', '/api/mind/screening/history', { childId: 1003 }, t);
   record(F, 'child', '筛查历史', r.status === 200 && r.body && r.body.code === 200, r.body ? 'screening history OK' : r.raw);
 
-  // 心理运势
-  r = await apiCall('POST', '/api/mind/fortune', {}, t);
+  // 心理运势(需要familyId)
+  r = await apiCall('POST', '/api/mind/fortune?familyId=2001', {}, t);
   record(F, 'child', '心理运势', r.status === 200 && r.body && r.body.code === 200, r.body ? 'fortune OK' : r.raw);
 
-  // EMI报告
-  r = await apiCall('POST', '/api/mind/emireport/latest', {}, t);
+  // EMI报告(需要childId)
+  r = await apiCall('POST', '/api/mind/emireport/latest', { childId: 1003 }, t);
   record(F, 'child', 'EMI报告', r.status === 200 && r.body && r.body.code === 200, r.body ? 'EMI report OK' : r.raw);
 }
 
@@ -932,16 +968,22 @@ async function testHealthDetectionFlow() {
   var t = tokens.parent;
   if (!t) { skip(F, 'parent', '所有测试', '未登录'); return; }
 
-  var r = await apiCall('POST', '/api/health/report/list', {}, t);
+  var r = await apiCall('POST', '/api/health/report/list', { childId: 1003 }, t);
   record(F, 'parent', '健康报告列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'report list OK' : r.raw);
 
-  r = await apiCall('POST', '/api/health/report/latest', {}, t);
+  // 先获取最新报告的reportId
+  r = await apiCall('POST', '/api/health/report/latest', { childId: 1003 }, t);
+  var reportId = (r.body && r.body.code === 200 && r.body.data) ? (r.body.data.id || r.body.data.reportId) : null;
   record(F, 'parent', '最新报告', r.status === 200 && r.body && r.body.code === 200, r.body ? 'latest report OK' : r.raw);
 
-  r = await apiCall('POST', '/api/health/indicator/list', {}, t);
+  // 先获取有数据的 reportId(如果最新报告无指标,先创建一个测试报告)
+  r = await apiCall('POST', '/api/health/report/list', { childId: 1003 }, t);
+  var validReportId = (r.body && r.body.code === 200 && r.body.data && Array.isArray(r.body.data) && r.body.data.length > 0)
+    ? (r.body.data[0].id || r.body.data[0].reportId) : 1;
+  r = await apiCall('POST', '/api/health/indicator/list', { reportId: validReportId }, t);
   record(F, 'parent', '指标明细', r.status === 200 && r.body && r.body.code === 200, r.body ? 'indicators OK' : r.raw);
 
-  r = await apiCall('POST', '/api/health/nutrition/deficiency', {}, t);
+  r = await apiCall('POST', '/api/health/nutrition/deficiency', { childId: 1003 }, t);
   record(F, 'parent', '营养缺乏分析', r.status === 200 && r.body && r.body.code === 200, r.body ? 'deficiency OK' : r.raw);
 }
 
@@ -1023,8 +1065,8 @@ async function testAIFlow() {
   r = await apiCall('POST', '/api/ai/butler/sessions/list', {}, t);
   record(F, 'parent', 'AI管家会话列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'butler sessions OK' : r.raw);
 
-  // AI上下文
-  r = await apiCall('POST', '/api/ai/context', {}, t);
+  // AI上下文(user_id 必须是字符串类型,后端用 (String) 强转)
+  r = await apiCall('POST', '/api/ai/context', { user_id: "1002", intent_type: "general" }, t);
   record(F, 'parent', 'AI上下文', r.status === 200 && r.body && r.body.code === 200, r.body ? 'context OK' : r.raw);
 
   // 推荐搜索
@@ -1052,14 +1094,16 @@ async function testMembershipFlow() {
   r = await apiCall('POST', '/api/membership/level', {}, t);
   record(F, 'parent', '当前等级', r.status === 200 && r.body && r.body.code === 200, r.body ? 'current level OK' : r.raw);
 
-  r = await apiCall('POST', '/api/membership/can-use', {}, t);
+  // 功能权限(需要 feature 参数)
+  r = await apiCall('POST', '/api/membership/can-use', { feature: 'advance_analysis' }, t);
   record(F, 'parent', '功能权限', r.status === 200 && r.body && r.body.code === 200, r.body ? 'can-use OK' : r.raw);
 
-  r = await apiCall('POST', '/api/membership/discount', {}, t);
+  // 会员折扣(需要 amount 参数)
+  r = await apiCall('POST', '/api/membership/discount', { amount: 1000 }, t);
   record(F, 'parent', '会员折扣', r.status === 200 && r.body && r.body.code === 200, r.body ? 'discount OK' : r.raw);
 
-  // 订阅
-  r = await apiCall('POST', '/api/subscription/status', {}, t);
+  // 订阅状态(需要familyId)
+  r = await apiCall('POST', '/api/subscription/status?familyId=2001', {}, t);
   record(F, 'parent', '订阅状态', r.status === 200 && r.body && r.body.code === 200, r.body ? 'subscription status OK' : r.raw);
 
   r = await apiCall('POST', '/api/subscription/plans', {}, t);
@@ -1187,10 +1231,10 @@ async function testCircleFlow() {
   var t = tokens.parent;
   if (!t) { skip(F, 'parent', '所有测试', '未登录'); return; }
 
-  var r = await apiCall('POST', '/api/circle/my-circles', {}, t);
+  var r = await apiCall('POST', '/api/circle/my-circles', { memberId: 1003 }, t);
   record(F, 'parent', '我的圈子', r.status === 200 && r.body && r.body.code === 200, r.body ? 'my circles OK' : r.raw);
 
-  r = await apiCall('POST', '/api/circle/discover', {}, t);
+  r = await apiCall('POST', '/api/circle/discover', { childId: 1003 }, t);
   record(F, 'parent', '发现圈子', r.status === 200 && r.body && r.body.code === 200, r.body ? 'discover OK' : r.raw);
 
   // 健康圈子
@@ -1220,10 +1264,10 @@ async function testKnowledgeFlow() {
     var r = await apiCall('POST', '/api/health/knowledge/list', {}, t);
     record(F, 'admin', '知识库列表', r.status === 200 && r.body && r.body.code === 200, r.body ? 'kb list OK' : r.raw);
 
-    r = await apiCall('POST', '/api/health/knowledge/v3/bacteria/query', { keyword: 'lactobacillus' }, t);
+    r = await apiCall('POST', '/api/health/knowledge/v3/bacteria/query', { name: 'lactobacillus' }, t);
     record(F, 'admin', '菌属查询', r.status === 200 && r.body && r.body.code === 200, r.body ? 'bacteria query OK' : r.raw);
 
-    r = await apiCall('POST', '/api/health/knowledge/v3/food/query', { keyword: 'apple' }, t);
+    r = await apiCall('POST', '/api/health/knowledge/v3/food/query', { name: 'apple' }, t);
     record(F, 'admin', '食物营养查询', r.status === 200 && r.body && r.body.code === 200, r.body ? 'food query OK' : r.raw);
   }
 
@@ -1267,8 +1311,8 @@ async function testExtraFlow() {
   r = await apiCall('POST', '/api/feedback/recent', {}, t);
   record(F, 'parent', '最近反馈', r.status === 200 && r.body && r.body.code === 200, r.body ? 'recent feedback OK' : r.raw);
 
-  // 生成小程序码
-  r = await apiCall('POST', '/api/common/qrcode', {}, t);
+  // 生成小程序码(仅支持 type=register 且需要 referralCode)
+  r = await apiCall('POST', '/api/common/qrcode', { type: 'register', referralCode: 'TEST2001' }, t);
   record(F, 'parent', '生成小程序码', r.status === 200 && r.body && r.body.code === 200, r.body ? 'qrcode OK' : r.raw);
 
   // 引导进度