diff --git a/openhis-ui-vue3/tests/e2e/pages/LoginPage.ts b/openhis-ui-vue3/tests/e2e/pages/LoginPage.ts index cac99bc7..8d802a3d 100644 --- a/openhis-ui-vue3/tests/e2e/pages/LoginPage.ts +++ b/openhis-ui-vue3/tests/e2e/pages/LoginPage.ts @@ -13,8 +13,21 @@ export class LoginPage { } async login(username: string, password: string) { - await this.page.fill('input[placeholder*="用户名"], input[placeholder*="账号"]', username); - await this.page.fill('input[placeholder*="密码"]', password); + // Actual placeholders from login.vue: "账号" and "密码" + await this.page.fill('input[placeholder="账号"]', username); + await this.page.fill('input[placeholder="密码"]', password); + // Check for tenant selection if exists + const tenantSelect = this.page.locator('.el-select__wrapper, input[placeholder="请选择医疗机构"]').first(); + if (await tenantSelect.isVisible().catch(() => false)) { + await tenantSelect.click(); + await this.page.waitForTimeout(500); + // Select first option + const firstOption = this.page.locator('.el-select-dropdown__item, .el-option').first(); + if (await firstOption.isVisible().catch(() => false)) { + await firstOption.click(); + await this.page.waitForTimeout(500); + } + } await this.page.click('button:has-text("登录")'); await this.page.waitForLoadState('networkidle'); } @@ -28,6 +41,6 @@ export class LoginPage { } async expectOnLoginPage() { - await expect(this.page.locator('input[placeholder*="用户名"], input[placeholder*="账号"]')).toBeVisible(); + await expect(this.page.locator('input[placeholder="账号"]')).toBeVisible(); } } diff --git a/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts b/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts index ea19e40b..acae54f6 100644 --- a/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts +++ b/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts @@ -18,13 +18,11 @@ test.describe('🐛 Bug回归测试', () => { const addBtn = page.locator('button:has-text("新增"), button:has-text("生成")'); if (await addBtn.isVisible()) { - // 快速连续点击3次 await addBtn.click(); await addBtn.click(); await addBtn.click(); await page.waitForTimeout(2000); - // 验证只弹出一个对话框 const dialogs = page.locator('.el-dialog, .el-message-box'); expect(await dialogs.count()).toBeLessThanOrEqual(1); } @@ -33,12 +31,10 @@ test.describe('🐛 Bug回归测试', () => { test('#443 手术计费签发耗材 @bug443 @regression', async ({ page }) => { await page.goto(TEST_URLS.surgeryBilling); await page.waitForLoadState('networkidle'); - // 验证签发功能不报错(locationId为空时应有默认值) const signBtn = page.locator('button:has-text("签发"), button:has-text("提交")'); if (await signBtn.isVisible()) { await signBtn.click(); await page.waitForTimeout(2000); - // 不应出现"发放库房为空"错误 const errorMsg = page.locator('text=发放库房为空'); expect(await errorMsg.count()).toBe(0); } @@ -47,7 +43,6 @@ test.describe('🐛 Bug回归测试', () => { test('#427 检查项目分类手风琴展开 @regression', async ({ page }) => { await page.goto(TEST_URLS.doctorStation); await page.waitForLoadState('networkidle'); - // 验证分类展开功能 const categories = page.locator('.el-collapse-item, .category-item'); const count = await categories.count(); if (count > 0) { diff --git a/openhis-ui-vue3/tests/e2e/specs/concurrency.spec.ts b/openhis-ui-vue3/tests/e2e/specs/concurrency.spec.ts index 7a89ef65..7a47b04b 100644 --- a/openhis-ui-vue3/tests/e2e/specs/concurrency.spec.ts +++ b/openhis-ui-vue3/tests/e2e/specs/concurrency.spec.ts @@ -1,25 +1,23 @@ -import { test, expect, Browser } from '@playwright/test'; +import { test, expect } from '@playwright/test'; import { TEST_USERS, TEST_URLS } from '../utils/test-data'; test.describe('🔄 并发操作测试', () => { test('#437 多窗口同时操作手术计费 @bug437', async ({ browser }) => { - // 打开两个浏览器上下文(模拟多标签页) const context1 = await browser.newContext(); const context2 = await browser.newContext(); const page1 = await context1.newPage(); const page2 = await context2.newPage(); - // 两个页面都登录 + // Login on both pages for (const page of [page1, page2]) { await page.goto(TEST_URLS.login); - await page.fill('input[placeholder*="用户名"], input[placeholder*="账号"]', TEST_USERS.admin.username); - await page.fill('input[placeholder*="密码"]', TEST_USERS.admin.password); + await page.fill('input[placeholder="账号"]', TEST_USERS.admin.username); + await page.fill('input[placeholder="密码"]', TEST_USERS.admin.password); await page.click('button:has-text("登录")'); await page.waitForURL(/.*(dashboard|home|index).*/); } - // 两个页面同时访问手术计费 await Promise.all([ page1.goto(TEST_URLS.surgeryBilling), page2.goto(TEST_URLS.surgeryBilling), @@ -30,7 +28,6 @@ test.describe('🔄 并发操作测试', () => { page2.waitForLoadState('networkidle'), ]); - // 同时在两个页面点击生成 const genBtn1 = page1.locator('button:has-text("生成")'); const genBtn2 = page2.locator('button:has-text("生成")'); @@ -42,14 +39,12 @@ test.describe('🔄 并发操作测试', () => { await page1.waitForTimeout(3000); - // 验证数据一致性:不应出现重复记录 const table1 = page1.locator('el-table__body tr, .el-table__row'); const table2 = page2.locator('el-table__body tr, .el-table__row'); const count1 = await table1.count(); const count2 = await table2.count(); - // 两个页面看到的数据应该一致 expect(count1).toBe(count2); } diff --git a/openhis-ui-vue3/tests/e2e/specs/doctor-station.spec.ts b/openhis-ui-vue3/tests/e2e/specs/doctor-station.spec.ts index 23f5a2b5..3cd8c1ac 100644 --- a/openhis-ui-vue3/tests/e2e/specs/doctor-station.spec.ts +++ b/openhis-ui-vue3/tests/e2e/specs/doctor-station.spec.ts @@ -1,36 +1,34 @@ import { test, expect } from '@playwright/test'; import { LoginPage } from '../pages/LoginPage'; -import { DoctorStationPage } from '../pages/DoctorStationPage'; import { TEST_USERS, TEST_URLS } from '../utils/test-data'; test.describe('🏥 门诊医生站', () => { let loginPage: LoginPage; - let doctorPage: DoctorStationPage; test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page); - doctorPage = new DoctorStationPage(page); await loginPage.goto(); await loginPage.login(TEST_USERS.admin.username, TEST_USERS.admin.password); await loginPage.expectLoginSuccess(); }); - test('#427 分类手风琴展开/收起 @regression', async () => { - await doctorPage.goto(); + test('#427 分类手风琴展开/收起 @regression', async ({ page }) => { + await page.goto(TEST_URLS.doctorStation); + await page.waitForLoadState('networkidle'); - const items = doctorPage.categoryItems; + const items = page.locator('.el-collapse-item, .category-item'); const count = await items.count(); if (count >= 2) { - // 展开第一个 - await doctorPage.expandCategory(0); - // 展开第二个,第一个应收起 - await doctorPage.expandCategory(1); + await items.nth(0).click(); + await page.waitForTimeout(500); + await items.nth(1).click(); + await page.waitForTimeout(500); } }); - test('TC-DOCTOR-001: 医生站页面加载 @smoke', async () => { - await doctorPage.goto(); - await expect(doctorPage.page).toHaveURL(/.*doctorstation.*/); + test('TC-DOCTOR-001: 医生站页面加载 @smoke', async ({ page }) => { + await page.goto(TEST_URLS.doctorStation); + await expect(page).toHaveURL(/.*doctorstation.*/); }); }); diff --git a/openhis-ui-vue3/tests/e2e/specs/surgery-billing.spec.ts b/openhis-ui-vue3/tests/e2e/specs/surgery-billing.spec.ts index 8fcacd27..2308f35e 100644 --- a/openhis-ui-vue3/tests/e2e/specs/surgery-billing.spec.ts +++ b/openhis-ui-vue3/tests/e2e/specs/surgery-billing.spec.ts @@ -1,43 +1,42 @@ import { test, expect } from '@playwright/test'; import { LoginPage } from '../pages/LoginPage'; -import { SurgeryBillingPage } from '../pages/SurgeryBillingPage'; import { TEST_USERS, TEST_URLS } from '../utils/test-data'; test.describe('💊 手术计费模块', () => { let loginPage: LoginPage; - let surgeryPage: SurgeryBillingPage; test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page); - surgeryPage = new SurgeryBillingPage(page); await loginPage.goto(); await loginPage.login(TEST_USERS.admin.username, TEST_USERS.admin.password); await loginPage.expectLoginSuccess(); }); - test('#437 快速连续点击防重复 @bug437 @smoke', async () => { - await surgeryPage.goto(); + test('#437 快速连续点击防重复 @bug437 @smoke', async ({ page }) => { + await page.goto(TEST_URLS.surgeryBilling); + await page.waitForLoadState('networkidle'); - if (await surgeryPage.generateBtn.isVisible()) { - // 模拟用户快速连点 - await surgeryPage.rapidClickGenerate(5); - await surgeryPage.page.waitForTimeout(3000); + const genBtn = page.locator('button:has-text("生成"), button:has-text("新增")'); + if (await genBtn.isVisible()) { + for (let i = 0; i < 5; i++) { + await genBtn.click().catch(() => {}); + } + await page.waitForTimeout(3000); - // 验证没有产生重复对话框 - const count = await surgeryPage.getDialogCount(); + const count = await page.locator('.el-dialog, .el-message-box').count(); expect(count).toBeLessThanOrEqual(1); } }); - test('#443 签发耗材不报库房错误 @bug443 @smoke', async () => { - await surgeryPage.goto(); + test('#443 签发耗材不报库房错误 @bug443 @smoke', async ({ page }) => { + await page.goto(TEST_URLS.surgeryBilling); + await page.waitForLoadState('networkidle'); - if (await surgeryPage.signBtn.isVisible()) { - await surgeryPage.signBtn.click(); - await surgeryPage.page.waitForTimeout(2000); - - // 不应出现"发放库房为空"错误 - await surgeryPage.expectNoLocationIdError(); + const signBtn = page.locator('button:has-text("签发"), button:has-text("提交")'); + if (await signBtn.isVisible()) { + await signBtn.click(); + await page.waitForTimeout(2000); + await expect(page.locator('text=发放库房为空')).toHaveCount(0, { timeout: 5000 }); } }); }); diff --git a/openhis-ui-vue3/tests/e2e/utils/test-data.ts b/openhis-ui-vue3/tests/e2e/utils/test-data.ts index cd823c60..93b5cf44 100644 --- a/openhis-ui-vue3/tests/e2e/utils/test-data.ts +++ b/openhis-ui-vue3/tests/e2e/utils/test-data.ts @@ -1,45 +1,13 @@ -/** - * 测试数据工厂 - OpenHIS E2E测试 - */ - -// 测试用户(从环境变量读取,严禁硬编码密码) export const TEST_USERS = { admin: { username: process.env.TEST_USERNAME || 'admin', password: process.env.TEST_PASSWORD || 'admin123', }, - doctor: { - username: process.env.TEST_DOCTOR_USERNAME || 'doctor', - password: process.env.TEST_DOCTOR_PASSWORD || 'doctor123', - }, - nurse: { - username: process.env.TEST_NURSE_USERNAME || 'nurse', - password: process.env.TEST_NURSE_PASSWORD || 'nurse123', - }, }; -// 核心路由 export const TEST_URLS = { login: '/', dashboard: '/index', doctorStation: '/doctorstation', surgeryBilling: '/operatingroom', - charge: '/charge', - pharmacy: '/pharmacymanagement', }; - -// 测试用例标签 -export const TAGS = { - smoke: '@smoke', // 冒烟测试 - regression: '@regression', // 回归测试 - bug437: '@bug437', // #437 重复计费 - bug443: '@bug443', // #443 签发耗材报错 - bug445: '@bug445', // #445 待生成列表 -}; - -// 验证环境变量 -export function validateTestEnv() { - if (!process.env.TEST_USERNAME || !process.env.TEST_PASSWORD) { - console.warn('⚠️ 未配置TEST_USERNAME/TEST_PASSWORD,使用默认值'); - } -}