/** * ================================================================ * 场景:健康报告审核 E2E 测试 * ================================================================ * 目标:管理员通过 cfc-web HealthReportAudit 审核健康报告草稿 * 部署地址:http://cfc.iwintrue.com * * 测试场景: * 1. 报告草稿列表加载 * 2. 列表列信息显示(草稿ID、用户、类型、文件名、状态、时间、操作) * 3. 草稿状态标签(待审核) * 4. 分页控件存在 * 5. 查看详情弹窗 * 6. 详情弹窗中的指标tab * 7. 详情弹窗中的菌群tab * 8. 详情弹窗中的疾病风险tab * 9. 确认审核操作 * 10. 丢弃草稿操作 * * 前置条件:已登录管理员账号,有测试数据 * ================================================================ */ const { test, expect } = require('@playwright/test'); /** * 确保已登录到管理后台 */ async function ensureLoggedIn(page) { const sidebar = page.locator('.sidebar-container, .el-menu-vertical-demo, .el-aside, #app > div'); try { await sidebar.waitFor({ state: 'visible', timeout: 5000 }); return; } catch { // 未登录,继续执行登录流程 } await page.goto('/login', { waitUntil: 'networkidle', timeout: 30000 }); await page.waitForTimeout(2000); // 尝试多种输入框选择器 const inputSelectors = [ '.el-input__inner', 'input[type="text"]', 'input[placeholder*="账号"]', 'input[placeholder*="用户名"]', 'input[name="username"]', '.el-input input', ]; let inputFound = false; for (const sel of inputSelectors) { try { const el = page.locator(sel).first(); if (await el.isVisible({ timeout: 3000 })) { await el.fill('admin'); inputFound = true; break; } } catch { // 继续尝试下一个选择器 } } if (!inputFound) { const allInputs = page.locator('input'); const count = await allInputs.count(); if (count > 0) { await allInputs.first().fill('admin'); if (count > 1) { await allInputs.nth(1).fill('admin123'); } } } const pwdInputs = page.locator('input[type="password"]'); if (await pwdInputs.count() > 0) { await pwdInputs.first().fill('admin123'); } else { const allInputs = page.locator('input'); const count = await allInputs.count(); if (count >= 2) { await allInputs.nth(1).fill('admin123'); } } const btnSelectors = [ '.el-button--primary', 'button[type="submit"]', '.login-btn', '.el-button:has-text("登录")', '.el-button:has-text("登 录")', ]; for (const sel of btnSelectors) { try { const btn = page.locator(sel).first(); if (await btn.isVisible({ timeout: 2000 })) { await btn.click(); break; } } catch { // 继续尝试 } } await page.waitForTimeout(3000); try { await sidebar.waitFor({ state: 'visible', timeout: 10000 }); } catch { // 超时仍继续 } } test.describe('【场景流程】健康报告审核 HealthReportAudit', () => { test('[场景1] 报告草稿列表加载 - 期望页面正常加载', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(3000); await page.screenshot({ path: 'test-artifacts/health-report-audit.png' }).catch(() => {}); const pageHeader = page.locator('.admin-page-title, h2'); await expect(pageHeader).toBeVisible({ timeout: 15000 }); await expect(pageHeader).toContainText('报告草稿审核'); }); test('[场景2] 表格列信息 - 期望显示草稿ID、用户、类型、文件名、状态、时间、操作列', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const table = page.locator('.el-table'); await expect(table).toBeVisible({ timeout: 15000 }); // 验证表头单元格包含各列名 const headerCells = page.locator('.el-table__header th .cell'); const headerText = await headerCells.allTextContents(); const allText = headerText.join(' '); expect(allText).toMatch(/草稿ID|上传用户|报告类型|文件名|状态|上传时间|操作/i); }); test('[场景3] 草稿状态标签 - 期望状态列显示"待审核"标签', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const table = page.locator('.el-table'); await expect(table).toBeVisible({ timeout: 15000 }); // 如果有数据行,验证状态标签 const rows = page.locator('.el-table__body tr'); const rowCount = await rows.count(); if (rowCount > 0) { const statusTag = page.locator('.el-tag--warning').first(); const isVisible = await statusTag.isVisible().catch(() => false); if (isVisible) { const tagText = await statusTag.textContent(); expect(tagText).toMatch(/待审核/i); } } }); test('[场景4] 分页控件 - 期望列表底部有分页组件', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const pagination = page.locator('.el-pagination'); const count = await pagination.count(); // 分页可能存在(数据量超过pagesize时),也可能隐藏(数据少时) if (count > 0) { await expect(pagination.first()).toBeVisible(); } }); test('[场景5] 查看详情弹窗 - 期望点击"查看详情"后弹出详情弹窗', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const viewBtn = page.locator('.el-button--primary:has-text("查看详情")'); const visible = await viewBtn.isVisible({ timeout: 5000 }).catch(() => false); if (!visible) { test.skip(); return; } await viewBtn.first().click(); await page.waitForTimeout(2000); const dialog = page.locator('.el-dialog'); await expect(dialog).toBeVisible({ timeout: 10000 }); const dialogTitle = page.locator('.el-dialog__title, .el-dialog__header'); await expect(dialogTitle).toContainText('草稿详情'); }); test('[场景6] 详情弹窗指标Tab - 期望指标Tab能正常显示', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const viewBtn = page.locator('.el-button--primary:has-text("查看详情")'); const visible = await viewBtn.isVisible({ timeout: 5000 }).catch(() => false); if (!visible) { test.skip(); return; } await viewBtn.first().click(); await page.waitForTimeout(2000); const indicatorsTab = page.locator('.el-tabs__item:has-text("指标")'); await expect(indicatorsTab).toBeVisible({ timeout: 5000 }); // 点击指标Tab await indicatorsTab.click(); await page.waitForTimeout(1000); // 验证指标表格存在 const indicatorTable = page.locator('.el-table').last(); await expect(indicatorTable).toBeVisible({ timeout: 5000 }); }); test('[场景7] 详情弹窗菌群Tab - 期望菌群Tab能正常切换', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const viewBtn = page.locator('.el-button--primary:has-text("查看详情")'); const visible = await viewBtn.isVisible({ timeout: 5000 }).catch(() => false); if (!visible) { test.skip(); return; } await viewBtn.first().click(); await page.waitForTimeout(2000); const gutFloraTab = page.locator('.el-tabs__item:has-text("菌群")'); await expect(gutFloraTab).toBeVisible({ timeout: 5000 }); // 点击菌群Tab await gutFloraTab.click(); await page.waitForTimeout(1000); }); test('[场景8] 确认审核操作 - 期望点击确认后触发确认弹窗', async ({ page }) => { await ensureLoggedIn(page); await page.goto('/health-report-audit', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const confirmBtn = page.locator('.el-button--success:has-text("确认")'); const visible = await confirmBtn.isVisible({ timeout: 5000 }).catch(() => false); if (!visible) { test.skip(); return; } await confirmBtn.first().click(); await page.waitForTimeout(2000); // 确认弹窗(El Message Box) const msgBox = page.locator('.el-message-box'); await expect(msgBox).toBeVisible({ timeout: 5000 }); // 取消操作,不真正执行 const cancelBtn = msgBox.locator('.el-button--default, .el-message-box__btns .el-button:not(.el-button--primary)'); if (await cancelBtn.isVisible().catch(() => false)) { await cancelBtn.click(); } else { await page.keyboard.press('Escape'); } }); });