Переглянути джерело

✅ test(e2e): 增强用户管理页面测试稳定性和可靠性

- 创建用户流程:
  - 明确指定模态框中的"创建用户"按钮,避免定位混淆
  - 添加创建成功提示的等待验证
  - 添加页面刷新和加载状态等待,确保数据同步

- 编辑用户流程:
  - 优化编辑按钮定位逻辑,使用第一个按钮作为编辑按钮
  - 添加编辑按钮可见性等待和编辑模态框出现等待
  - 明确指定模态框中的"更新用户"按钮

- 删除用户流程:
  - 优化删除按钮定位逻辑,使用第二个按钮作为删除按钮
  - 添加删除按钮可见性等待和删除操作完成等待
  - 添加删除失败提示检查和页面刷新确认

- 添加userExists方法,简化用户存在性检查
- 优化expectUserExists和expectUserNotExists方法,使用新的userExists方法实现更可靠的断言
yourname 2 місяців тому
батько
коміт
43580da106
1 змінених файлів з 50 додано та 9 видалено
  1. 50 9
      tests/e2e/pages/admin/user-management.page.ts

+ 50 - 9
tests/e2e/pages/admin/user-management.page.ts

@@ -74,9 +74,18 @@ export class UserManagementPage {
       await this.page.getByLabel('真实姓名').fill(userData.name);
     }
 
-    // 提交表单
-    await this.page.getByRole('button', { name: '创建用户' }).click();
+    // 提交表单 - 使用模态框中的创建按钮
+    await this.page.locator('[role="dialog"]').getByRole('button', { name: '创建用户' }).click();
     await this.page.waitForLoadState('networkidle');
+
+    // 等待用户创建成功提示
+    await this.page.waitForSelector('text=创建成功', { timeout: 10000 });
+
+    // 等待页面自动刷新或手动刷新
+    await this.page.waitForTimeout(1000);
+    await this.page.reload();
+    await this.page.waitForLoadState('networkidle');
+    await this.expectToBeVisible();
   }
 
   async getUserCount(): Promise<number> {
@@ -89,6 +98,11 @@ export class UserManagementPage {
     return (await userRow.count()) > 0 ? userRow : null;
   }
 
+  async userExists(username: string): Promise<boolean> {
+    const userRow = this.userTable.locator('tbody tr').filter({ hasText: username }).first();
+    return (await userRow.count()) > 0;
+  }
+
   async editUser(username: string, updates: {
     nickname?: string;
     email?: string;
@@ -98,7 +112,13 @@ export class UserManagementPage {
     const userRow = await this.getUserByUsername(username);
     if (!userRow) throw new Error(`User ${username} not found`);
 
-    await userRow.locator('button').filter({ hasText: '编辑' }).click();
+    // 编辑按钮是图标按钮,使用按钮定位(第一个按钮是编辑,第二个是删除)
+    const editButton = userRow.locator('button').first();
+    await editButton.waitFor({ state: 'visible', timeout: 10000 });
+    await editButton.click();
+
+    // 等待编辑模态框出现
+    await this.page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: 10000 });
 
     // 更新字段
     if (updates.nickname) {
@@ -115,26 +135,47 @@ export class UserManagementPage {
     }
 
     // 提交更新
-    await this.page.getByRole('button', { name: '更新用户' }).click();
+    await this.page.locator('[role="dialog"]').getByRole('button', { name: '更新用户' }).click();
     await this.page.waitForLoadState('networkidle');
+
+    // 等待操作完成
+    await this.page.waitForTimeout(1000);
   }
 
   async deleteUser(username: string) {
     const userRow = await this.getUserByUsername(username);
     if (!userRow) throw new Error(`User ${username} not found`);
 
-    await userRow.locator('button').filter({ hasText: '删除' }).click();
+    // 删除按钮是图标按钮,使用按钮定位(第二个按钮是删除)
+    const deleteButton = userRow.locator('button').nth(1);
+    await deleteButton.waitFor({ state: 'visible', timeout: 10000 });
+    await deleteButton.click();
+
+    // 确认删除对话框
     await this.page.getByRole('button', { name: '删除' }).click();
+
+    // 等待删除操作完成
+    await this.page.waitForTimeout(2000);
+
+    // 检查是否有错误提示
+    const errorVisible = await this.page.locator('text=删除失败').isVisible().catch(() => false);
+    if (errorVisible) {
+      throw new Error('删除操作失败:前端显示删除失败提示');
+    }
+
+    // 刷新页面确认用户是否被删除
+    await this.page.reload();
     await this.page.waitForLoadState('networkidle');
+    await this.expectToBeVisible();
   }
 
   async expectUserExists(username: string) {
-    const userRow = await this.getUserByUsername(username);
-    await expect(userRow).not.toBeNull();
+    const exists = await this.userExists(username);
+    expect(exists).toBe(true);
   }
 
   async expectUserNotExists(username: string) {
-    const userRow = await this.getUserByUsername(username);
-    await expect(userRow).toBeNull();
+    const exists = await this.userExists(username);
+    expect(exists).toBe(false);
   }
 }