瀏覽代碼

test: 新增内容管理/操作日志/性能测试用例38条

liaoxg 3 月之前
父節點
當前提交
8f7598a562
共有 3 個文件被更改,包括 378 次插入0 次删除
  1. 109 0
      test-e2e/e2e/content.spec.js
  2. 143 0
      test-e2e/e2e/operation-log.spec.js
  3. 126 0
      test-e2e/e2e/performance.spec.js

+ 109 - 0
test-e2e/e2e/content.spec.js

@@ -0,0 +1,109 @@
+const { test, expect } = require('@playwright/test');
+
+const BASE_URL = 'https://ajy.danclub.cn';
+const TEST_ADMIN = { username: 'admin', password: 'admin123' };
+
+test.describe('内容管理测试', () => {
+  test.beforeEach(async ({ page }) => {
+    await page.goto(BASE_URL);
+    await page.waitForLoadState('networkidle');
+    await page.getByPlaceholder('请输入用户名').fill(TEST_ADMIN.username);
+    await page.getByPlaceholder('请输入密码').fill(TEST_ADMIN.password);
+    await page.getByRole('button', { name: '登 录' }).click();
+    await page.waitForURL(`${BASE_URL}/#/user/app`, { timeout: 10000 });
+  });
+
+  test('CM-001: 查看文章列表', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    await page.waitForTimeout(1000);
+  });
+
+  test('CM-002: 按标题搜索文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    const searchInput = page.getByPlaceholder('请输入文章标题');
+    if (await searchInput.isVisible()) {
+      await searchInput.fill('艾灸');
+      await page.getByRole('button', { name: '查询' }).click();
+      await page.waitForTimeout(1000);
+    }
+  });
+
+  test('CM-003: 按分类筛选文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('CM-004: 按状态筛选文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('CM-010: 新增文章-必填验证', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    const addBtn = page.getByRole('button', { name: '新增' });
+    if (await addBtn.isVisible()) {
+      await addBtn.click();
+      await page.waitForTimeout(500);
+      await page.getByRole('button', { name: '保存' }).click();
+      await page.waitForTimeout(500);
+    }
+  });
+
+  test('CM-011: 文章标题超长验证', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('CM-012: 发布文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    const addBtn = page.getByRole('button', { name: '新增' });
+    if (await addBtn.isVisible()) {
+      await addBtn.click();
+      await page.waitForTimeout(500);
+    }
+  });
+
+  test('CM-013: 编辑文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    const editBtn = page.getByRole('button', { name: '编辑' }).first();
+    if (await editBtn.isVisible()) {
+      await editBtn.click();
+      await page.waitForTimeout(500);
+    }
+  });
+
+  test('CM-014: 删除文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('CM-015: 审核文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('CM-016: 批量发布文章', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    const checkbox = page.locator('.el-table__header .el-checkbox').first();
+    if (await checkbox.isVisible()) {
+      await checkbox.click();
+      await page.waitForTimeout(300);
+    }
+  });
+
+  test('CM-017: 文章分页切换', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/content`);
+    await page.waitForLoadState('networkidle');
+    const nextButton = page.locator('.btn-next').first();
+    if (await nextButton.isVisible()) {
+      await nextButton.click();
+      await page.waitForTimeout(1000);
+    }
+  });
+});

+ 143 - 0
test-e2e/e2e/operation-log.spec.js

@@ -0,0 +1,143 @@
+const { test, expect } = require('@playwright/test');
+
+const BASE_URL = 'https://ajy.danclub.cn';
+const TEST_ADMIN = { username: 'admin', password: 'admin123' };
+
+test.describe('操作日志测试', () => {
+  test.beforeEach(async ({ page }) => {
+    await page.goto(BASE_URL);
+    await page.waitForLoadState('networkidle');
+    await page.getByPlaceholder('请输入用户名').fill(TEST_ADMIN.username);
+    await page.getByPlaceholder('请输入密码').fill(TEST_ADMIN.password);
+    await page.getByRole('button', { name: '登 录' }).click();
+    await page.waitForURL(`${BASE_URL}/#/user/app`, { timeout: 10000 });
+  });
+
+  test('OL-001: 查看操作日志列表', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    await page.waitForTimeout(1000);
+  });
+
+  test('OL-002: 按操作人筛选', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    const operatorInput = page.getByPlaceholder('请输入操作人');
+    if (await operatorInput.isVisible()) {
+      await operatorInput.fill('admin');
+      await page.getByRole('button', { name: '查询' }).click();
+      await page.waitForTimeout(1000);
+    }
+  });
+
+  test('OL-003: 按操作类型筛选', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    const typeSelect = page.locator('.el-select').first();
+    if (await typeSelect.isVisible()) {
+      await typeSelect.click();
+      await page.waitForTimeout(300);
+    }
+  });
+
+  test('OL-004: 按时间范围筛选', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('OL-005: 按模块筛选', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('OL-006: 日志分页-每页20条', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    const pageSizeSelect = page.locator('.el-select').last();
+    if (await pageSizeSelect.isVisible()) {
+      await pageSizeSelect.click();
+      await page.waitForTimeout(300);
+      await page.getByRole('option', { name: '20 条/页' }).click();
+      await page.waitForTimeout(1000);
+    }
+  });
+
+  test('OL-007: 日志分页-每页50条', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('OL-008: 导出日志Excel', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    await page.waitForTimeout(1000);
+  });
+
+  test('OL-009: 重置查询条件', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    const operatorInput = page.getByPlaceholder('请输入操作人');
+    if (await operatorInput.isVisible()) {
+      await operatorInput.fill('test');
+      await page.getByRole('button', { name: '重置' }).click();
+      await page.waitForTimeout(500);
+      await expect(operatorInput).toHaveValue('');
+    }
+  });
+
+  test('OL-010: 日志详情查看', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system/log`);
+    await page.waitForLoadState('networkidle');
+    const detailBtn = page.getByRole('button', { name: '详情' }).first();
+    if (await detailBtn.isVisible()) {
+      await detailBtn.click();
+      await page.waitForTimeout(500);
+    }
+  });
+});
+
+test.describe('管理员管理测试', () => {
+  test.beforeEach(async ({ page }) => {
+    await page.goto(BASE_URL);
+    await page.waitForLoadState('networkidle');
+    await page.getByPlaceholder('请输入用户名').fill(TEST_ADMIN.username);
+    await page.getByPlaceholder('请输入密码').fill(TEST_ADMIN.password);
+    await page.getByRole('button', { name: '登 录' }).click();
+    await page.waitForURL(`${BASE_URL}/#/user/app`, { timeout: 10000 });
+  });
+
+  test('OL-020: 新增管理员-用户名重复验证', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system`);
+    await page.waitForLoadState('networkidle');
+    const addBtn = page.getByRole('button', { name: '新增管理员' });
+    if (await addBtn.isVisible()) {
+      await addBtn.click();
+      await page.waitForTimeout(500);
+      await page.getByRole('button', { name: '保存' }).click();
+      await page.waitForTimeout(500);
+    }
+  });
+
+  test('OL-021: 禁用管理员', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('OL-022: 启用管理员', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system`);
+    await page.waitForLoadState('networkidle');
+  });
+
+  test('OL-023: 管理员密码格式验证', async ({ page }) => {
+    await page.goto(`${BASE_URL}/#/system`);
+    await page.waitForLoadState('networkidle');
+    const addBtn = page.getByRole('button', { name: '新增管理员' });
+    if (await addBtn.isVisible()) {
+      await addBtn.click();
+      await page.waitForTimeout(500);
+      await page.getByPlaceholder('请输入密码').fill('123');
+      await page.getByRole('button', { name: '保存' }).click();
+      await page.waitForTimeout(500);
+    }
+  });
+});

+ 126 - 0
test-e2e/e2e/performance.spec.js

@@ -0,0 +1,126 @@
+const { test, expect, request } = require('@playwright/test');
+
+const BASE_URL = 'https://ajy.danclub.cn';
+const API_BASE_URL = 'https://ajy.danclub.cn/api';
+const PERFORMANCE_THRESHOLD_MS = 200;
+
+test.describe('API性能测试', () => {
+  test('PERF-001: 用户列表接口响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.get(`${API_BASE_URL}/users?page=1&pageSize=10`);
+    const duration = Date.now() - start;
+    expect(response.status()).toBe(200);
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS);
+  });
+
+  test('PERF-002: 设备列表接口响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.get(`${API_BASE_URL}/device/page?pageNum=1&pageSize=10`);
+    const duration = Date.now() - start;
+    expect(response.status()).toBe(200);
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS);
+  });
+
+  test('PERF-003: 穴位列表接口响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.get(`${API_BASE_URL}/acupoint/page?pageNum=1&pageSize=10`);
+    const duration = Date.now() - start;
+    expect([200, 404]).toContain(response.status());
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS * 2);
+  });
+
+  test('PERF-004: 方案列表接口响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.get(`${API_BASE_URL}/plan/page?pageNum=1&pageSize=10`);
+    const duration = Date.now() - start;
+    expect([200, 404]).toContain(response.status());
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS * 2);
+  });
+
+  test('PERF-005: 穴位坐标生成响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.post(`${API_BASE_URL}/algorithm/acupoint-generate`, {
+      data: { shoulderWidth: 42, bodyLength: 85, gender: '男', cun1: 2.2 }
+    });
+    const duration = Date.now() - start;
+    expect([200, 401]).toContain(response.status());
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS * 3);
+  });
+
+  test('PERF-006: 指寸估算响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.post(`${API_BASE_URL}/algorithm/cun-calculate`, {
+      data: { shoulderWidth: 42, bodyLength: 85, gender: '男' }
+    });
+    const duration = Date.now() - start;
+    expect([200, 401]).toContain(response.status());
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS * 2);
+  });
+
+  test('PERF-007: 数据验证接口响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.post(`${API_BASE_URL}/algorithm/validate`, {
+      data: { shoulderWidth: 42, gender: '男' }
+    });
+    const duration = Date.now() - start;
+    expect([200, 401]).toContain(response.status());
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS * 2);
+  });
+
+  test('PERF-008: 置信度计算响应时间', async ({ request }) => {
+    const start = Date.now();
+    const response = await request.post(`${API_BASE_URL}/algorithm/confidence`, {
+      data: { shoulderWidth: 42, bodyLength: 85, cun1: 2.2 }
+    });
+    const duration = Date.now() - start;
+    expect([200, 401]).toContain(response.status());
+    expect(duration).toBeLessThan(PERFORMANCE_THRESHOLD_MS * 2);
+  });
+});
+
+test.describe('页面加载性能测试', () => {
+  test('PERF-010: 用户列表页面加载时间', async ({ page }) => {
+    await page.goto(BASE_URL);
+    await page.waitForLoadState('networkidle');
+    await page.getByPlaceholder('请输入用户名').fill('admin');
+    await page.getByPlaceholder('请输入密码').fill('admin123');
+    await page.getByRole('button', { name: '登 录' }).click();
+    await page.waitForURL(`${BASE_URL}/#/user/app`, { timeout: 10000 });
+
+    const start = Date.now();
+    await page.goto(`${BASE_URL}/#/user/app`);
+    await page.waitForLoadState('networkidle');
+    const duration = Date.now() - start;
+    expect(duration).toBeLessThan(3000);
+  });
+
+  test('PERF-011: 设备列表页面加载时间', async ({ page }) => {
+    await page.goto(BASE_URL);
+    await page.waitForLoadState('networkidle');
+    await page.getByPlaceholder('请输入用户名').fill('admin');
+    await page.getByPlaceholder('请输入密码').fill('admin123');
+    await page.getByRole('button', { name: '登 录' }).click();
+    await page.waitForURL(`${BASE_URL}/#/user/app`, { timeout: 10000 });
+
+    const start = Date.now();
+    await page.goto(`${BASE_URL}/#/device`);
+    await page.waitForLoadState('networkidle');
+    const duration = Date.now() - start;
+    expect(duration).toBeLessThan(3000);
+  });
+
+  test('PERF-012: 穴位列表页面加载时间', async ({ page }) => {
+    await page.goto(BASE_URL);
+    await page.waitForLoadState('networkidle');
+    await page.getByPlaceholder('请输入用户名').fill('admin');
+    await page.getByPlaceholder('请输入密码').fill('admin123');
+    await page.getByRole('button', { name: '登 录' }).click();
+    await page.waitForURL(`${BASE_URL}/#/user/app`, { timeout: 10000 });
+
+    const start = Date.now();
+    await page.goto(`${BASE_URL}/#/acupoint`);
+    await page.waitForLoadState('networkidle');
+    const duration = Date.now() - start;
+    expect(duration).toBeLessThan(3000);
+  });
+});