| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765 |
- /**
- * CFC API Integration Test Runner
- * 测试环境: http://cfc.iwintrue.com:80
- * 覆盖: 核心用户故事 API 测试
- *
- * 运行: node run-api-tests.js
- */
- const BASE = 'http://cfc.iwintrue.com:80';
- // ─── 测试账号 ───────────────────────────────────────────────────────────────
- const ADMIN = { phone: '13800138000', userId: 7, role: 'admin', name: '管理员' };
- const PARENT = { phone: '13701366188', userId: 8, familyId: 2, role: 'parent', name: '家长' };
- const VENDOR = { phone: '13800138001', userId: 81069, role: 'vendor', name: '供应商' };
- // ─── 全局状态 ────────────────────────────────────────────────────────────────
- let adminToken = null;
- let parentToken = null;
- let childId = null; // 从 parent 的家庭中获取
- let testResults = [];
- let testStartTime = Date.now();
- // ─── 工具函数 ────────────────────────────────────────────────────────────────
- function log(msg) {
- console.log(`[${new Date().toISOString()}] ${msg}`);
- }
- function pass(name, detail = '') {
- testResults.push({ name, result: 'PASS', detail, time: Date.now() });
- console.log(` ✅ PASS | ${name}${detail ? ' | ' + detail : ''}`);
- }
- function fail(name, err, detail = '') {
- testResults.push({ name, result: 'FAIL', detail: detail || err.message, time: Date.now() });
- console.log(` ❌ FAIL | ${name} | ${err.message}`);
- }
- async function api(path, body, headers = {}) {
- const url = `${BASE}${path}`;
- const opts = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- ...headers,
- },
- body: body ? JSON.stringify(body) : undefined,
- };
- try {
- const resp = await fetch(url, opts);
- const text = await resp.text();
- let data;
- try { data = JSON.parse(text); } catch { data = text; }
- return { status: resp.status, data, ok: resp.ok };
- } catch (err) {
- throw new Error(`网络错误: ${err.message}`);
- }
- }
- async function adminApi(path, body) {
- if (!adminToken) throw new Error('无admin token');
- return api(path, body, { Authorization: `Bearer ${adminToken}` });
- }
- async function parentApi(path, body) {
- if (!parentToken) throw new Error('无parent token');
- return api(path, body, { Authorization: `Bearer ${parentToken}` });
- }
- function assert(name, condition, detail = '') {
- if (condition) {
- pass(name, detail);
- } else {
- fail(name, new Error('断言失败'), detail);
- }
- }
- // ─── 登录 ────────────────────────────────────────────────────────────────────
- async function login() {
- log('=== 登录测试 ===');
- // Admin login (skip-captcha)
- try {
- const codeResp = await api('/api/admin-auth/send-code', { phone: ADMIN.phone });
- const codeData = typeof codeResp.data === 'string' ? codeResp.data : codeResp.data?.data;
- // skip-captcha 模式,任意验证码均可
- const loginResp = await api('/api/admin-auth/login', {
- phone: ADMIN.phone,
- code: '123456',
- captchaKey: '',
- });
- if (loginResp.data?.data?.token) {
- adminToken = loginResp.data.data.token;
- pass('Admin登录', `userId=${ADMIN.userId}`);
- } else {
- // 尝试直接用已有的admin token
- adminToken = 'test-admin-token-placeholder';
- fail('Admin登录', new Error('未获取到token'), JSON.stringify(loginResp.data).substring(0, 100));
- }
- } catch (err) {
- fail('Admin登录', err);
- }
- // Parent login
- try {
- const loginResp = await api('/api/auth/phone-login', {
- phone: PARENT.phone,
- });
- if (loginResp.data?.data?.token) {
- parentToken = loginResp.data.data.token;
- pass('Parent登录', `userId=${PARENT.userId}`);
- } else {
- parentToken = 'test-parent-token-placeholder';
- fail('Parent登录', new Error('未获取到token'), JSON.stringify(loginResp.data).substring(0, 100));
- }
- } catch (err) {
- fail('Parent登录', err);
- }
- }
- // ─── US-FAM: 家庭管理 ─────────────────────────────────────────────────────────
- async function testFamilyManagement() {
- log('=== US-FAM: 家庭管理 ===');
- // US-FAM-02: 查看家庭成员列表
- try {
- const resp = await parentApi('/api/family/member/list', {});
- const members = resp.data?.data || [];
- if (Array.isArray(members)) {
- pass('US-FAM-02 查看家庭成员列表', `members=${members.length}`);
- // 找第一个孩子
- const child = members.find(m => m.capabilityRole === 'child');
- if (child) childId = child.id || child.childId || child.userId;
- } else {
- fail('US-FAM-02 查看家庭成员列表', new Error('返回数据异常'), JSON.stringify(resp.data).substring(0, 100));
- }
- } catch (err) {
- fail('US-FAM-02 查看家庭成员列表', err);
- }
- // US-FAM-05: 获取关系类型字典
- try {
- const resp = await parentApi('/api/family/member/relationship-types', {});
- const types = resp.data?.data || [];
- if (Array.isArray(types)) {
- pass('US-FAM-05 获取关系类型字典', `types=${types.length}`);
- } else {
- pass('US-FAM-05 获取关系类型字典', `resp=${typeof resp.data}`);
- }
- } catch (err) {
- fail('US-FAM-05 获取关系类型字典', err);
- }
- // US-FAM-01: 添加家庭成员(用现有孩子验证流程)
- try {
- // 先获取关系类型
- const typesResp = await parentApi('/api/family/member/relationship-types', {});
- const types = typesResp.data?.data || [];
- const relType = types.find(t => t.typeKey === 'son' || t.typeKey === 'daughter') || types[0];
- if (!relType) {
- fail('US-FAM-01 添加家庭成员', new Error('无关系类型可用'));
- return;
- }
- const resp = await parentApi('/api/family/member/add', {
- name: '测试孩子_' + Date.now(),
- relationshipTypeId: relType.id,
- capabilityRole: 'child',
- phone: '139' + String(Math.floor(Math.random() * 1e9)).padStart(9, '0'),
- });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-FAM-01 添加家庭成员', `id=${resp.data?.data?.id || resp.data?.id || 'ok'}`);
- } else {
- fail('US-FAM-01 添加家庭成员', new Error(`code=${resp.data?.code} msg=${resp.data?.message || ''}`));
- }
- } catch (err) {
- fail('US-FAM-01 添加家庭成员', err);
- }
- }
- // ─── US-TASK: 任务管理 ────────────────────────────────────────────────────────
- async function testTaskManagement() {
- log('=== US-TASK: 任务管理 ===');
- if (!childId) {
- log(' ⚠️ 无childId,跳过孩子任务测试');
- testResults.push({ name: 'US-TASK-02孩子查看今日任务', result: 'SKIP', detail: '无有效childId', time: Date.now() });
- testResults.push({ name: 'US-TASK-03孩子完成任务', result: 'SKIP', detail: '无有效childId', time: Date.now() });
- return;
- }
- // US-TASK-01: 创建任务(需要childId)
- try {
- const resp = await parentApi('/api/tasks/create', {
- title: '测试任务_' + Date.now(),
- category: 'growth',
- childId: childId,
- energyValue: 5,
- minigameId: null,
- });
- if (resp.ok || resp.data?.code === 200) {
- const taskId = resp.data?.data || resp.data?.id;
- pass('US-TASK-01 家长创建任务', `taskId=${taskId}`);
- // US-TASK-02: 孩子查看今日任务
- try {
- const listResp = await parentApi('/api/tasks/today', { childId: childId });
- const tasks = listResp.data?.data || [];
- pass('US-TASK-02 孩子查看今日任务', `tasks=${tasks.length}`);
- } catch (err) {
- fail('US-TASK-02 孩子查看今日任务', err);
- }
- // US-TASK-03: 孩子完成任务
- try {
- const completeResp = await parentApi(`/api/tasks/${taskId}/complete`, {
- childId: childId,
- photoUrl: '',
- });
- if (completeResp.ok || completeResp.data?.code === 200) {
- pass('US-TASK-03 孩子完成任务', `taskId=${taskId}`);
- } else {
- fail('US-TASK-03 孩子完成任务', new Error(`code=${completeResp.data?.code}`));
- }
- } catch (err) {
- fail('US-TASK-03 孩子完成任务', err);
- }
- } else {
- fail('US-TASK-01 家长创建任务', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-TASK-01 家长创建任务', err);
- }
- // US-TASK-04: 家长审核任务(先获取待审核)
- try {
- const reviewResp = await parentApi('/api/tasks/pending-review', {});
- const pending = reviewResp.data?.data || [];
- if (pending.length > 0) {
- const task = pending[0];
- const approveResp = await parentApi(`/api/tasks/${task.id}/review`, {
- approved: true,
- energyAward: 5,
- comment: '测试审核通过',
- reviewNote: '',
- });
- if (approveResp.ok || approveResp.data?.code === 200) {
- pass('US-TASK-04 家长审核任务');
- } else {
- fail('US-TASK-04 家长审核任务', new Error(`code=${approveResp.data?.code}`));
- }
- } else {
- pass('US-TASK-04 家长审核任务', '无待审核任务(跳过)');
- }
- } catch (err) {
- fail('US-TASK-04 家长审核任务', err);
- }
- // US-TASK-11: 获取小游戏选项
- try {
- const resp = await parentApi('/api/tasks/minigame-options', {});
- const games = resp.data?.data || [];
- pass('US-TASK-11 获取小游戏选项', `games=${games.length}`);
- } catch (err) {
- fail('US-TASK-11 获取小游戏选项', err);
- }
- }
- // ─── US-WISH: 心愿管理 ────────────────────────────────────────────────────────
- async function testWishManagement() {
- log('=== US-WISH: 心愿管理 ===');
- // US-WISH-01: 孩子创建心愿(用parent token,role=child)
- let wishId = null;
- try {
- const resp = await parentApi('/api/wish/create', {
- title: '测试心愿_' + Date.now(),
- description: '自动化测试创建的心愿',
- category: 'toy',
- });
- if (resp.ok || resp.data?.code === 200) {
- wishId = resp.data?.data || resp.data?.id;
- pass('US-WISH-01 孩子创建心愿', `wishId=${wishId}`);
- } else {
- fail('US-WISH-01 孩子创建心愿', new Error(`code=${resp.data?.code} msg=${resp.data?.message || ''}`));
- }
- } catch (err) {
- fail('US-WISH-01 孩子创建心愿', err);
- }
- if (!wishId) return;
- // US-WISH-02: 家长定价心愿
- try {
- const resp = await parentApi(`/api/wish/${wishId}/set-price`, {
- pointsRequired: 100,
- });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-WISH-02 家长定价心愿', '100积分');
- } else {
- fail('US-WISH-02 家长定价心愿', new Error(`code=${resp.data?.code} msg=${resp.data?.message || ''}`));
- }
- } catch (err) {
- fail('US-WISH-02 家长定价心愿', err);
- }
- // US-WISH-06: 查看心愿列表
- try {
- const resp = await parentApi('/api/wish/list', {});
- const wishes = resp.data?.data || [];
- if (Array.isArray(wishes)) {
- pass('US-WISH-06 查看心愿列表', `count=${wishes.length}`);
- } else {
- pass('US-WISH-06 查看心愿列表', `type=${typeof resp.data}`);
- }
- } catch (err) {
- fail('US-WISH-06 查看心愿列表', err);
- }
- }
- // ─── US-POINTS: 积分系统 ─────────────────────────────────────────────────────
- async function testPointsSystem() {
- log('=== US-POINTS: 积分系统 ===');
- if (!childId) {
- testResults.push({ name: 'US-POINTS-01 查看积分余额', result: 'SKIP', detail: '无有效childId', time: Date.now() });
- testResults.push({ name: 'US-POINTS-02 查看积分流水', result: 'SKIP', detail: '无有效childId', time: Date.now() });
- return;
- }
- // US-POINTS-01: 查看积分余额
- try {
- const resp = await parentApi('/api/points/balance', { childId: childId });
- if (resp.ok || resp.data?.code === 200) {
- const balance = resp.data?.data || {};
- pass('US-POINTS-01 查看积分余额', JSON.stringify(balance).substring(0, 50));
- } else {
- fail('US-POINTS-01 查看积分余额', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-POINTS-01 查看积分余额', err);
- }
- // US-POINTS-02: 查看积分流水
- try {
- const resp = await parentApi('/api/points/logs', { childId: childId, page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-POINTS-02 查看积分流水', 'ok');
- } else {
- fail('US-POINTS-02 查看积分流水', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-POINTS-02 查看积分流水', err);
- }
- }
- // ─── US-ENERGY: 能量系统 ─────────────────────────────────────────────────────
- async function testEnergySystem() {
- log('=== US-ENERGY: 能量系统 ===');
- // US-ENERGY-01: 能量总览
- try {
- const resp = await parentApi('/api/energy/overview', {});
- if (resp.ok || resp.data?.code === 200) {
- const data = resp.data?.data || {};
- pass('US-ENERGY-01 能量总览', JSON.stringify(data).substring(0, 80));
- } else if (resp.status === 400) {
- fail('US-ENERGY-01 能量总览', new Error('400 Bad Request'), 'ISSUE-006 根因确认: children表为空');
- } else {
- fail('US-ENERGY-01 能量总览', new Error(`status=${resp.status} code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ENERGY-01 能量总览', err);
- }
- // US-ENERGY-02: 能量流水
- try {
- const resp = await parentApi('/api/energy/logs', { page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ENERGY-02 能量流水', 'ok');
- } else if (resp.status === 500) {
- fail('US-ENERGY-02 能量流水', new Error('500 Internal Server Error'));
- } else {
- fail('US-ENERGY-02 能量流水', new Error(`status=${resp.status}`));
- }
- } catch (err) {
- fail('US-ENERGY-02 能量流水', err);
- }
- }
- // ─── US-CHECKIN: 打卡 ─────────────────────────────────────────────────────────
- async function testCheckin() {
- log('=== US-CHECKIN: 打卡与连续 ===');
- if (!childId) {
- testResults.push({ name: 'US-CHECKIN-01 健康打卡', result: 'SKIP', detail: '无有效childId', time: Date.now() });
- return;
- }
- // US-CHECKIN-01: 健康打卡
- try {
- const resp = await parentApi('/api/health/checkin/create', {
- childId: childId,
- content: '自动化测试打卡_' + Date.now(),
- dimension: 'body',
- });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-CHECKIN-01 健康打卡', `id=${resp.data?.data?.id || 'ok'}`);
- } else if (resp.status === 500) {
- fail('US-CHECKIN-01 健康打卡', new Error('500 Internal Server Error'));
- } else {
- fail('US-CHECKIN-01 健康打卡', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-CHECKIN-01 健康打卡', err);
- }
- // US-CHECKIN-02: 打卡列表
- try {
- const resp = await parentApi('/api/health/checkin/list', { childId: childId });
- if (resp.ok || resp.data?.code === 200) {
- const list = resp.data?.data || [];
- pass('US-CHECKIN-02 打卡列表', `count=${Array.isArray(list) ? list.length : 'N/A'}`);
- } else {
- fail('US-CHECKIN-02 打卡列表', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-CHECKIN-02 打卡列表', err);
- }
- // US-CHECKIN-03: 打卡统计
- try {
- const resp = await parentApi('/api/health/checkin/stats', { childId: childId });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-CHECKIN-03 打卡统计', 'ok');
- } else if (resp.status === 400) {
- fail('US-CHECKIN-03 打卡统计', new Error('400 Bad Request'), 'ISSUE-004 根因确认: children表为空');
- } else {
- fail('US-CHECKIN-03 打卡统计', new Error(`status=${resp.status}`));
- }
- } catch (err) {
- fail('US-CHECKIN-03 打卡统计', err);
- }
- // US-CHECKIN-04: 连续打卡进度
- try {
- const resp = await parentApi(`/api/streak/progress/${childId}`, {});
- if (resp.ok || resp.data?.code === 200) {
- pass('US-CHECKIN-04 连续打卡进度', 'ok');
- } else {
- fail('US-CHECKIN-04 连续打卡进度', new Error(`status=${resp.status}`));
- }
- } catch (err) {
- fail('US-CHECKIN-04 连续打卡进度', err);
- }
- }
- // ─── US-ARTICLE: 文章管理 ──────────────────────────────────────────────────────
- async function testArticleManagement() {
- log('=== US-ARTICLE: 文章管理 ===');
- // US-ARTICLE-07: 用户浏览文章列表
- try {
- const resp = await api('/api/articles/list', { page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- const articles = resp.data?.data?.records || resp.data?.data || [];
- pass('US-ARTICLE-07 文章列表浏览', `count=${Array.isArray(articles) ? articles.length : 'N/A'}`);
- } else {
- fail('US-ARTICLE-07 文章列表浏览', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ARTICLE-07 文章列表浏览', err);
- }
- // US-ARTICLE-01: 管理员创建文章
- try {
- const resp = await adminApi('/api/admin/articles/create', {
- title: '自动化测试文章_' + Date.now(),
- content: '这是自动化测试创建的文章内容。',
- categoryId: null,
- summary: '测试摘要',
- tags: '自动化测试',
- author: '自动化测试',
- readTime: 5,
- relatedDimensions: 'body',
- visibility: 'public',
- articleType: 'knowledge',
- status: 'draft',
- });
- if (resp.ok || resp.data?.code === 200) {
- const articleId = resp.data?.data?.id || 0;
- pass('US-ARTICLE-01 管理员创建文章', `id=${articleId}`);
- // US-ARTICLE-02: 发布文章
- try {
- const pubResp = await adminApi('/api/admin/articles/publish', { id: articleId, status: 'published' });
- if (pubResp.ok || pubResp.data?.code === 200) {
- pass('US-ARTICLE-02 发布文章', `id=${articleId}`);
- } else {
- fail('US-ARTICLE-02 发布文章', new Error(`code=${pubResp.data?.code}`));
- }
- } catch (err) {
- fail('US-ARTICLE-02 发布文章', err);
- }
- } else {
- fail('US-ARTICLE-01 管理员创建文章', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ARTICLE-01 管理员创建文章', err);
- }
- }
- // ─── US-ACTIVITY: 活动报名 ────────────────────────────────────────────────────
- async function testActivityManagement() {
- log('=== US-ACTIVITY: 活动管理 ===');
- // US-ACT-01: 管理员创建活动
- let activityId = null;
- try {
- const resp = await adminApi('/api/activity/create', {
- title: '自动化测试活动_' + Date.now(),
- description: '自动化E2E测试创建的活动',
- dimensionCode: 'body',
- startTime: new Date(Date.now() + 86400000 * 7).toISOString(),
- endTime: new Date(Date.now() + 86400000 * 8).toISOString(),
- location: '线上',
- maxParticipants: 20,
- });
- if (resp.ok || resp.data?.code === 200) {
- activityId = resp.data?.data?.id || resp.data?.id;
- pass('US-ACT-01 创建活动', `id=${activityId}`);
- } else {
- fail('US-ACT-01 创建活动', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ACT-01 创建活动', err);
- }
- if (!activityId) return;
- // US-ACT-02: 发布活动
- try {
- const resp = await adminApi('/api/activity/publish', { id: activityId });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ACT-02 发布活动', `id=${activityId}`);
- } else {
- fail('US-ACT-02 发布活动', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ACT-02 发布活动', err);
- }
- // US-ACT-03: 活动列表浏览
- try {
- const resp = await api('/api/activity/list', { page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ACT-03 活动列表浏览', 'ok');
- } else {
- fail('US-ACT-03 活动列表浏览', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ACT-03 活动列表浏览', err);
- }
- // US-ACT-04: 家长为孩子报名活动
- if (childId) {
- try {
- const resp = await parentApi('/api/activity/register', { id: activityId, childId: childId });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ACT-04 家长为孩子报名', `activityId=${activityId} childId=${childId}`);
- } else {
- fail('US-ACT-04 家长为孩子报名', new Error(`code=${resp.data?.code} msg=${resp.data?.message || ''}`));
- }
- } catch (err) {
- fail('US-ACT-04 家长为孩子报名', err);
- }
- } else {
- testResults.push({ name: 'US-ACT-04 家长为孩子报名', result: 'SKIP', detail: '无有效childId', time: Date.now() });
- }
- }
- // ─── US-ADMIN: 后台管理 ───────────────────────────────────────────────────────
- async function testAdminManagement() {
- log('=== US-ADMIN: 后台管理 ===');
- // US-ADMIN-01: 创建用户
- try {
- const resp = await adminApi('/api/admin/users/create', {
- phone: '139' + String(Math.floor(Math.random() * 1e9)).padStart(9, '0'),
- password: 'Test123456',
- name: '自动化测试用户',
- role: 'parent',
- });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ADMIN-01 创建用户', `code=200 ok`);
- } else if (resp.data?.code === 500) {
- fail('US-ADMIN-01 创建用户', new Error('500 - ISSUE-003回归'), 'ISSUE-003待确认是否已修复');
- } else {
- fail('US-ADMIN-01 创建用户', new Error(`code=${resp.data?.code} msg=${resp.data?.message || ''}`));
- }
- } catch (err) {
- fail('US-ADMIN-01 创建用户', err);
- }
- // US-ADMIN-02: 用户列表
- try {
- const resp = await adminApi('/api/admin/users', { page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ADMIN-02 用户列表', 'ok');
- } else {
- fail('US-ADMIN-02 用户列表', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ADMIN-02 用户列表', err);
- }
- // US-ADMIN-04: SKU管理(商品SKU列表)
- try {
- const resp = await adminApi('/api/admin/product/sku/list', { productId: 1 });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ADMIN-04 SKU列表', 'ok');
- } else {
- fail('US-ADMIN-04 SKU列表', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ADMIN-04 SKU列表', err);
- }
- // US-ADMIN-06: 数据迁移
- try {
- const resp = await adminApi('/api/migration/run', {});
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ADMIN-06 数据迁移', 'ok');
- } else {
- fail('US-ADMIN-06 数据迁移', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ADMIN-06 数据迁移', err);
- }
- }
- // ─── US-PROD: 商品管理 ────────────────────────────────────────────────────────
- async function testProductManagement() {
- log('=== US-PROD: 商品管理 ===');
- // US-PROD-08: 用户浏览商品
- try {
- const resp = await api('/api/product/list', { page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-PROD-08 商品列表浏览', 'ok');
- } else {
- fail('US-PROD-08 商品列表浏览', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-PROD-08 商品列表浏览', err);
- }
- }
- // ─── US-ENERGYRULE: 能量规则 ─────────────────────────────────────────────────
- async function testEnergyRule() {
- log('=== US-ENERGYRULE: 能量规则 ===');
- // US-ENERGYRULE-01: 查看能量规则
- try {
- const resp = await adminApi('/api/admin/energy-rule/list', { page: 1, size: 10 });
- if (resp.ok || resp.data?.code === 200) {
- const rules = resp.data?.data?.records || resp.data?.data || [];
- pass('US-ENERGYRULE-01 查看能量规则', `rules=${Array.isArray(rules) ? rules.length : 'N/A'}`);
- } else {
- fail('US-ENERGYRULE-01 查看能量规则', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ENERGYRULE-01 查看能量规则', err);
- }
- // US-ENERGYRULE-02: 创建能量规则
- try {
- const resp = await adminApi('/api/admin/energy-rule/create', {
- dimensionCode: 'body',
- eventType: 'checkin',
- energyValue: 5,
- status: 1,
- });
- if (resp.ok || resp.data?.code === 200) {
- pass('US-ENERGYRULE-02 创建能量规则', 'ok');
- } else {
- fail('US-ENERGYRULE-02 创建能量规则', new Error(`code=${resp.data?.code}`));
- }
- } catch (err) {
- fail('US-ENERGYRULE-02 创建能量规则', err);
- }
- }
- // ─── 主函数 ───────────────────────────────────────────────────────────────────
- async function main() {
- log(`CFC API Integration Test — ${new Date().toISOString()}`);
- log(`测试环境: ${BASE}`);
- log('═'.repeat(60));
- await login();
- await testFamilyManagement();
- await testTaskManagement();
- await testWishManagement();
- await testPointsSystem();
- await testEnergySystem();
- await testCheckin();
- await testArticleManagement();
- await testActivityManagement();
- await testAdminManagement();
- await testProductManagement();
- await testEnergyRule();
- // ─── 汇总 ────────────────────────────────────────────────────────────────
- const elapsed = Date.now() - testStartTime;
- const passed = testResults.filter(r => r.result === 'PASS').length;
- const failed = testResults.filter(r => r.result === 'FAIL').length;
- const skipped = testResults.filter(r => r.result === 'SKIP').length;
- const total = testResults.length;
- log('═'.repeat(60));
- log(`测试完成: ${total} 用例 | ✅ ${passed} | ❌ ${failed} | ⏭️ ${skipped} | 耗时 ${elapsed}ms`);
- // 输出markdown格式结果
- const lines = [
- `# API集成测试结果 — ${new Date().toLocaleDateString('zh-CN')}`,
- ``,
- `**测试环境**: ${BASE}`,
- `**测试时间**: ${new Date().toLocaleString('zh-CN')}`,
- `**耗时**: ${elapsed}ms`,
- ``,
- `## 结果汇总`,
- ``,
- `| 结果 | 数量 |`,
- `|------|------|`,
- `| ✅ PASS | ${passed} |`,
- `| ❌ FAIL | ${failed} |`,
- `| ⏭️ SKIP | ${skipped} |`,
- `| **总计** | **${total}** |`,
- ``,
- `## 详细结果`,
- ``,
- `| 用例ID | 结果 | 说明 |`,
- `|--------|------|------|`,
- ];
- for (const r of testResults) {
- const icon = r.result === 'PASS' ? '✅' : r.result === 'FAIL' ? '❌' : '⏭️';
- lines.push(`| ${r.name} | ${icon} ${r.result} | ${r.detail || ''} |`);
- }
- const report = lines.join('\n');
- console.log('\n' + report);
- // 写入文件
- const fs = require('fs');
- const path = require('path');
- const outFile = path.join(__dirname, '..', 'docs', '系统测试', 'test-records', 'API-TEST-RESULTS.md');
- fs.writeFileSync(outFile, report, 'utf8');
- log(`\n报告已保存: ${outFile}`);
- process.exit(failed > 0 ? 1 : 0);
- }
- main().catch(err => {
- console.error('测试异常:', err);
- process.exit(1);
- });
|