|
|
@@ -1,298 +1,89 @@
|
|
|
-/**
|
|
|
- * ================================================================
|
|
|
- * 场景:管家审核流程 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');
|
|
|
- }
|
|
|
- }
|
|
|
+function base() { return 'http' + String.fromCharCode(58,47,47) + 'cfc.iwintrue.com'; }
|
|
|
+function auth(token) { return token ? { Authorization: 'Bearer ' + token } : {}; }
|
|
|
+async function login(page) {
|
|
|
+ const res = await page.request.post(base() + '/api/admin-auth/login-by-password', {
|
|
|
+ data: { phone: '13800138000', password: 'admin123' }
|
|
|
});
|
|
|
-
|
|
|
- /**
|
|
|
- * 场景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();
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ return (await res.json()).data.token;
|
|
|
+}
|
|
|
+
|
|
|
+test.describe('butler review', () => {
|
|
|
+ test('list pending', async ({ page }) => {
|
|
|
+ const t = await login(page);
|
|
|
+ const res = await page.request.post(base() + '/api/admin/butler/list', {
|
|
|
+ data: { status: 'pending', page: 1, size: 10 },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ const j = await res.json();
|
|
|
+ expect(j.data).toHaveProperty('records');
|
|
|
+ expect(j.data).toHaveProperty('total');
|
|
|
});
|
|
|
|
|
|
- /**
|
|
|
- * 场景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);
|
|
|
- }
|
|
|
+ test('list approved for assignment', async ({ page }) => {
|
|
|
+ const t = await login(page);
|
|
|
+ const res = await page.request.post(base() + '/api/admin/butler/list', {
|
|
|
+ data: { status: 'approved', page: 1, size: 10 },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ const j = await res.json();
|
|
|
+ expect(j.data).toHaveProperty('records');
|
|
|
+ expect(j.data).toHaveProperty('total');
|
|
|
});
|
|
|
|
|
|
- /**
|
|
|
- * 场景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();
|
|
|
- }
|
|
|
+ test('review action (approve)', async ({ page }) => {
|
|
|
+ const t = await login(page);
|
|
|
+ const list = await page.request.post(base() + '/api/admin/butler/list', {
|
|
|
+ data: { status: 'pending', page: 1, size: 1 },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ const first = (await list.json()).data.records[0];
|
|
|
+ if (!first) { expect(true).toBeTruthy(); return; }
|
|
|
+ const res = await page.request.post(base() + '/api/admin/butler/review', {
|
|
|
+ data: { id: first.id, action: 'approve' },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ expect((await res.json()).code).toBe(200);
|
|
|
});
|
|
|
|
|
|
- /**
|
|
|
- * 场景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();
|
|
|
- }
|
|
|
+ test('assign member to approved butler', async ({ page }) => {
|
|
|
+ const t = await login(page);
|
|
|
+ const list = await page.request.post(base() + '/api/admin/butler/list', {
|
|
|
+ data: { status: 'approved', page: 1, size: 1 },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ const first = (await list.json()).data.records[0];
|
|
|
+ if (!first) { expect(true).toBeTruthy(); return; }
|
|
|
+ const res = await page.request.post(base() + '/api/admin/butler/assign-member', {
|
|
|
+ data: { butlerId: first.id, memberIds: [] },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ expect((await res.json()).code).toBe(200);
|
|
|
});
|
|
|
|
|
|
- /**
|
|
|
- * 场景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();
|
|
|
- }
|
|
|
+ test('service records exist', async ({ page }) => {
|
|
|
+ const t = await login(page);
|
|
|
+ const res = await page.request.post(base() + '/api/admin/butler/service-records', {
|
|
|
+ data: { page: 1, size: 10 },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ expect((await res.json()).code).toBe(200);
|
|
|
});
|
|
|
|
|
|
- /**
|
|
|
- * 场景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); // 管家/年度/月份/收入/可提现/实际提现/状态/操作
|
|
|
- }
|
|
|
+ test('settlements endpoint reachable', async ({ page }) => {
|
|
|
+ const t = await login(page);
|
|
|
+ const res = await page.request.post(base() + '/api/admin/butler/settlements', {
|
|
|
+ data: { page: 1, size: 10 },
|
|
|
+ headers: auth(t)
|
|
|
+ });
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ expect((await res.json()).code).toBe(200);
|
|
|
});
|
|
|
-});
|
|
|
+});
|