/** * ================================================================ * 场景:管家审核流程 E2E 测试 * ================================================================ * 用户故事:管理员在后台审核管家申请,通过/驳回申请, * 分配家庭成员给管家,查看管家服务记录和佣金结算。 * * 流程步骤: * 1. 管理员登录后台 * 2. 打开管家审核页面 * 3. 搜索筛选管家列表 * 4. 查看管家详情 * 5. 审核(通过或驳回) * 6. 分配家庭成员(服务订单)给管家 * 7. 查看服务记录和佣金结算 * * 关键里程碑: * - [Milestone-1] 管家审核页面加载成功(butler-review 报名选项卡加载) * - [Milestone-2] 能够搜索和筛选管家列表 * - [Milestone-3] 成功提交审核(通过或驳回) * - [Milestone-4] 成功分配家庭成员给管家 * * API 端点: * - POST /api/admin/butler/list (筛选管家列表) * - POST /api/admin/butler/review (审核管家) * - POST /api/admin/butler/assign-member (分配成员) * - POST /api/admin/butler/service-records (服务记录) * - POST /api/admin/butler/settlements (佣金结算) * * 运行:npx playwright test tests/e2e/admin-butler-review.spec.js * ================================================================ */ const { test, expect } = require('@playwright/test'); test.describe('【场景流程】管家审核流程', () => { test.beforeEach(async ({ page }) => { // 管理员登录(admin 后台) await page.goto('http://cfc.iwintrue.com/admin/login'); await page.waitForLoadState('networkidle'); const adminPhone = '13701366188'; // 已验证的管理员账号 const phoneInput = page.locator('input[placeholder="请输入手机号"]'); await phoneInput.fill(adminPhone); await page.locator('.login-btn, button:has-text("登录")').click(); await page.waitForTimeout(1500); // 验证登录成功(有 admin-tab 或管理菜单) try { await page.waitForSelector('.admin-tab, .admin-menu, .admin-layout', { timeout: 10000 }); } catch (e) { // 跳过重复登录 if (await page.url().includes('/login')) { await page.goto('http://cfc.iwintrue.com/admin/butler-review'); await page.waitForLoadState('networkidle'); } } }); /** * 场景1:管家审核页面加载 * 角色:管理员 * 触发条件:进入后台管家审核页面 * 校验:页面加载成功,tab 切换到待审核 */ test('[场景1] 管家审核页面加载 — 期望 tab 切换到待审核', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 验证页面标题 const title = page.locator('.el-card__header, .tab-header, h2:has-text("管家审核")'); expect(await title.isVisible()).toBeTruthy(); // 验证默认选中"待审核" tab const pendingTab = page.locator('.nav-item.active, .el-tab-pane.is-active, text="待审核"'); expect(await pendingTab.isVisible()).toBeTruthy(); }); /** * 场景2:搜索筛选管家列表 * 角色:管理员 * 触发条件:输入管家姓名、状态、等级等筛选条件 * 校验:表格刷新返回正常数据 */ test('[场景2] 搜索筛选管家列表 — 期望表格刷新', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 输入筛选条件 var nameInput = page.locator('input[placeholder="管家姓名"]'); if (await nameInput.isVisible()) { await nameInput.fill('张三'); } var statusSelect = page.locator('.el-select, .status-select, .select-status'); if (await statusSelect.isVisible()) { await statusSelect.click(); var pendingOption = page.locator('.el-select-dropdown__item:has-text("待审核")'); await pendingOption.click(); } // 点击搜索按钮 var searchBtn = page.locator('.search-btn, button:has-text("搜索")'); await searchBtn.click(); await page.waitForTimeout(1000); // 验证表格有数据 var tableRows = page.locator('.el-table__row, .table-row'); var rowCount = await tableRows.count(); expect(rowCount).toBeGreaterThanOrEqual(0); // 可能为空,但不报 500 // 验证列数(按钮、状态、创建时间等) if (rowCount > 0) { const rowCells = page.locator('.el-table__row:first-child .el-table__cell, th[aria-colindex="5"]'); expect(await rowCells.count()).toBeGreaterThanOrEqual(5); } }); /** * 场景3:提交管家审核(通过) * 角色:管理员 * 触发条件:选择一位待审核管家,点击通过按钮 * 校验:返回成功提示,状态变为"已通过" */ test('[场景3] 提交管家审核(通过) — 期望成功提示且状态改变', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 查找待审核管家(点击第一行的操作按钮) var approveBtn = page.locator('.el-table__row:first-child button:has-text("通过")'); if (await approveBtn.isVisible()) { await approveBtn.click(); await page.waitForTimeout(500); // 填写通过理由(可选) var reasonInput = page.locator('textarea[placeholder="可选填:通过理由"]'); if (await reasonInput.isVisible()) { await reasonInput.fill('资质符合,通过审核'); } // 提交 var submitBtn = page.locator('.el-dialog__footer button:has-text("确定"), button.el-button--primary'); await submitBtn.click(); await page.waitForTimeout(1000); // 验证提示 var successTip = page.locator('.el-message-box__success, .toast-success, text="通过成功"'); if (await successTip.isVisible().catch(() => false)) { expect(await successTip.textContent()).toContain("通过"); } else { // 刷新检查状态 await page.reload(); await page.waitForTimeout(500); var newStatus = page.locator('.el-table__row:first-child .el-tag:has-text("已通过")'); expect(await newStatus.isVisible()).toBeTruthy(); } } else { // 无待审核数据,跳过 expect(true).toBeTruthy(); } }); /** * 场景4:提交管家审核(驳回) * 角色:管理员 * 触发条件:选择一位待审核管家,点击驳回按钮 * 校验:返回成功提示,状态变为"已驳回" */ test('[场景4] 提交管家审核(驳回) — 期望成功提示且状态改变', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 查找待审核管家 var rejectBtn = page.locator('.el-table__row:first-child button:has-text("驳回")'); if (await rejectBtn.isVisible()) { await rejectBtn.click(); await page.waitForTimeout(500); // 填写驳回理由 var reasonInput = page.locator('textarea[placeholder="请填写驳回理由"]'); await reasonInput.fill('资料不齐,请补充身份证照片'); // 提交 var submitBtn = page.locator('.el-dialog__footer button:has-text("确定"), button.el-button--primary'); await submitBtn.click(); await page.waitForTimeout(1000); // 验证提示 var successTip = page.locator('.el-message-box__success, .toast-success, text="驳回成功"'); expect(await successTip.isVisible().catch(() => false)).toBeTruthy(); } else { // 无待审核数据,跳过 expect(true).toBeTruthy(); } }); /** * 场景5:分配家庭成员给管家 * 角色:管理员 * 触发条件:选定一位管家,从服务订单中选择家庭成员进行分配 * 校验:提示分配成功,管家服务记录增加 */ test('[场景5] 分配家庭成员给管家 — 期望成功并更新服务记录', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 切换到"已通过"管家列表 var activeTab = page.locator('.el-tabs__item:has-text("已通过"), .nav-item:has-text("已通过")'); await activeTab.click(); await page.waitForTimeout(500); // 查找操作栏的"分配服务"按钮 var assignBtn = page.locator('.el-table__row:first-child button:has-text("分配服务")'); if (await assignBtn.isVisible()) { await assignBtn.click(); await page.waitForTimeout(500); // 在弹窗中选择成员(勾选第一项) var memberCheckbox = page.locator('.el-checkbox:first-child input[type=checkbox]'); await memberCheckbox.check(); await page.waitForTimeout(500); // 提交 var submitBtn = page.locator('.el-dialog__footer button:has-text("分配");'); await submitBtn.click(); await page.waitForTimeout(1000); // 验证提示 var successTip = page.locator('.toast-success, text="分配成功"'); expect(await successTip.isVisible().catch(() => false)).toBeTruthy(); // 验证服务记录页面刷新 await page.goto('/#/pages/admin/service-records'); await page.waitForLoadState('networkidle'); var tableRows = page.locator('.el-table__row'); expect(await tableRows.count()).toBeGreaterThanOrEqual(0); } else { // 无已通过管家,跳过 expect(true).toBeTruthy(); } }); /** * 场景6:查看管家服务记录 * 角色:管理员 * 触发条件:切换到"服务记录" tab * 校验:表格加载正常数据 */ test('[场景6] 查看管家服务记录 — 期望表格加载', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 切换到服务记录 tab var serviceTab = page.locator('.el-tabs__item:has-text("服务记录"), .nav-item:has-text("服务记录")'); await serviceTab.click(); await page.waitForTimeout(1000); // 验证表格加载 var tableRows = page.locator('.el-table__row, .service-record-row'); var rowCount = await tableRows.count(); expect(rowCount).toBeGreaterThanOrEqual(0); // 验证记录展示内容 if (rowCount > 0) { var firstRowCells = page.locator('.el-table__row:first-child .el-table__cell'); expect(await firstRowCells.count()).toBeGreaterThanOrEqual(7); // 管家/成员/订单/服务类型/状态/时间/操作 } }); /** * 场景7:查看管家佣金结算 * 角色:管理员 * 触发条件:切换到"佣金结算" tab * 校验:表格加载正常数据 */ test('[场景7] 查看管家佣金结算 — 期望加载结算记录', async ({ page }) => { await page.goto('/#/pages/admin/butler-review'); await page.waitForLoadState('networkidle'); // 切换到佣金结算 tab var commissionTab = page.locator('.el-tabs__item:has-text("佣金结算"), .nav-item:has-text("佣金结算")'); await commissionTab.click(); await page.waitForTimeout(1000); // 验证表格加载 var tableRows = page.locator('.el-table__row, .commission-row'); var rowCount = await tableRows.count(); expect(rowCount).toBeGreaterThanOrEqual(0); // 验证记录展示内容 if (rowCount > 0) { var firstRowCells = page.locator('.el-table__row:first-child .el-table__cell'); expect(await firstRowCells.count()).toBeGreaterThanOrEqual(8); // 管家/年度/月份/收入/可提现/实际提现/状态/操作 } }); });