const { test, expect, request } = require('@playwright/test'); const API_BASE_URL = 'https://ajy.danclub.cn/api'; /** * 7.1 用户管理接口 */ test.describe('API-001: 获取用户列表', () => { test('GET /api/users', async ({ request }) => { const response = await request.get(`${API_BASE_URL}/users?page=1&pageSize=10`); expect(response.status()).toBe(200); const data = await response.json(); expect(Array.isArray(data.list)).toBe(true); }); }); test.describe('API-002: 获取用户详情', () => { test('GET /api/users/:id', async ({ request }) => { const response = await request.get(`${API_BASE_URL}/users/U001`); expect(response.status()).toBe(200); const data = await response.json(); expect(data.id).toBe('U001'); }); }); test.describe('API-003: 新增用户', () => { test('POST /api/users', async ({ request }) => { const userData = { name: '测试用户', gender: '男', age: 35, phone: '13900000000', shoulderWidth: 42, bodyLength: 85 }; const response = await request.post(`${API_BASE_URL}/users`, { data: userData }); expect(response.status()).toBe(201); const data = await response.json(); expect(data.name).toBe('测试用户'); }); }); test.describe('API-004: 更新用户', () => { test('PUT /api/users/:id', async ({ request }) => { const updateData = { name: '更新后的姓名' }; const response = await request.put(`${API_BASE_URL}/users/U001`, { data: updateData }); expect(response.status()).toBe(200); const data = await response.json(); expect(data.name).toBe('更新后的姓名'); }); }); test.describe('API-005: 生成穴位坐标', () => { test('POST /api/users/:id/acupoint-coordinates', async ({ request }) => { const response = await request.post(`${API_BASE_URL}/users/U001/acupoint-coordinates`); expect(response.status()).toBe(200); const data = await response.json(); expect(Array.isArray(data.acupoints)).toBe(true); }); }); /** * 7.2 方案管理接口 */ test.describe('API-010: 获取方案列表', () => { test('GET /api/schemes', async ({ request }) => { const response = await request.get(`${API_BASE_URL}/schemes`); expect(response.status()).toBe(200); const data = await response.json(); expect(Array.isArray(data.list)).toBe(true); }); }); test.describe('API-011: 获取方案详情', () => { test('GET /api/schemes/:id', async ({ request }) => { const response = await request.get(`${API_BASE_URL}/schemes/S001`); expect(response.status()).toBe(200); const data = await response.json(); expect(data.id).toBe('S001'); }); }); test.describe('API-012: 创建方案', () => { test('POST /api/schemes', async ({ request }) => { const schemeData = { name: '测试方案', mode: '一键艾灸', efficacy: '驱寒' }; const response = await request.post(`${API_BASE_URL}/schemes`, { data: schemeData }); expect(response.status()).toBe(201); const data = await response.json(); expect(data.name).toBe('测试方案'); }); }); test.describe('API-013: 发布方案', () => { test('POST /api/schemes/:id/publish', async ({ request }) => { const response = await request.post(`${API_BASE_URL}/schemes/S001/publish`); expect(response.status()).toBe(200); const data = await response.json(); expect(data.status).toBe('已发布'); }); }); test.describe('API-014: 同步圣手方案', () => { test('POST /api/users/:id/devices/:deviceId/expert-sync', async ({ request }) => { const response = await request.post(`${API_BASE_URL}/users/U001/devices/AJY001/expert-sync`); expect(response.status()).toBe(200); const data = await response.json(); expect(data.syncedCount).toBeGreaterThan(0); }); }); /** * 8. 数据库测试 * 需要直接访问数据库或通过API验证约束 */ test.describe('DB-001: 唯一性约束-手机号', () => { test('插入重复手机号', async ({ request }) => { const userData = { phone: '13800138000' }; const response = await request.post(`${API_BASE_URL}/users`, { data: userData }); expect(response.status()).toBeGreaterThanOrEqual(400); }); }); test.describe('DB-002: 唯一性约束-设备编号', () => { test('插入重复设备编号', async ({ request }) => { const deviceData = { deviceNo: 'AJY001' }; const response = await request.post(`${API_BASE_URL}/devices`, { data: deviceData }); expect(response.status()).toBeGreaterThanOrEqual(400); }); }); test.describe('DB-003: 主设备唯一性', () => { test('同一用户设置两个主设备', async ({ request }) => { const firstDevice = { userId: 'U001', deviceNo: 'AJY001', isMain: true }; const secondDevice = { userId: 'U001', deviceNo: 'AJY002', isMain: true }; await request.post(`${API_BASE_URL}/user-devices`, { data: firstDevice }); const response = await request.post(`${API_BASE_URL}/user-devices`, { data: secondDevice }); const data = await response.json(); expect(data.isMain).toBe(true); }); }); test.describe('DB-004: 逻辑删除', () => { test('删除用户', async ({ request }) => { const response = await request.delete(`${API_BASE_URL}/users/U001`); expect(response.status()).toBe(200); const data = await response.json(); expect(data.deleted).toBe(1); }); }); test.describe('DB-005: 外键级联', () => { test('删除用户下的设备绑定', async ({ request }) => { const response = await request.delete(`${API_BASE_URL}/users/U001`); const bindings = await request.get(`${API_BASE_URL}/user-devices?userId=U001`); const data = await bindings.json(); expect(data.list.length).toBe(0); }); }); test.describe('DB-006: 数据类型验证', () => { test('插入超出范围的肩宽', async ({ request }) => { const userData = { shoulderWidth: 100 }; const response = await request.post(`${API_BASE_URL}/users`, { data: userData }); expect(response.status()).toBeGreaterThanOrEqual(400); }); }); /** * 9. 验收测试 */ test.describe('AT-001: 穴位定位精度', () => { test('完整指寸数据生成坐标', async ({ request }) => { const response = await request.post(`${API_BASE_URL}/algorithm/acupoint-generate`, { data: { shoulderWidth: 42, bodyLength: 85, gender: '男', cun1: 2.2, cun1_5: 3.3, cun3: 6.6 } }); const data = await response.json(); const errors = data.acupoints.map(a => a.error).filter(e => e > 2); expect(errors.length).toBe(0); }); }); test.describe('AT-002: 穴位库动态扩展', () => { test('新增穴位在方案中使用', async ({ request }) => { const acupointData = { name: '测试穴位', meridian: '督脉', efficacy: '驱寒' }; await request.post(`${API_BASE_URL}/acupoints`, { data: acupointData }); const schemes = await request.get(`${API_BASE_URL}/schemes`); const data = await schemes.json(); expect(data.list.length).toBeGreaterThan(0); }); }); test.describe('AT-003: 8种专业模式', () => { test('创建8种功效方案', async ({ request }) => { const efficacies = ['驱寒', '祛湿', '清热', '补气', '养血', '活血', '安神', '理气']; for (const efficacy of efficacies) { const schemeData = { name: `${efficacy}方案`, mode: '专业模式', efficacy }; const response = await request.post(`${API_BASE_URL}/schemes`, { data: schemeData }); expect(response.status()).toBe(201); } }); }); test.describe('AT-004: 工艺语言生成', () => { test('���建��家方案生成设备指令', async ({ request }) => { const schemeData = { name: '专家方案', mode: '延年圣手', expertName: '测试专家' }; const response = await request.post(`${API_BASE_URL}/schemes`, { data: schemeData }); const data = await response.json(); expect(data.instructions).toBeDefined(); }); }); test.describe('AT-005: API响应时间', () => { test('核心API响应时间<200ms', async ({ request }) => { const times = []; for (let i = 0; i < 100; i++) { const start = Date.now(); await request.get(`${API_BASE_URL}/users`); const time = Date.now() - start; times.push(time); } const avgTime = times.reduce((a, b) => a + b, 0) / times.length; expect(avgTime).toBeLessThan(200); }); }); test.describe('AT-006: 症状推荐覆盖率', () => { test('常见症状推荐覆盖率≥80%', async ({ request }) => { const symptoms = ['感冒', '发烧', '咳嗽', '头痛', '腰痛', '失眠', '胃痛', '痛经', '关节炎', '高血压']; let covered = 0; for (const symptom of symptoms) { const response = await request.get(`${API_BASE_URL}/schemes/recommend?symptom=${symptom}`); const data = await response.json(); if (data.list && data.list.length > 0) covered++; } const coverage = (covered / symptoms.length) * 100; expect(coverage).toBeGreaterThanOrEqual(80); }); });