admin-butler-review.spec.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /**
  2. * ================================================================
  3. * 场景:管家审核流程 E2E 测试
  4. * ================================================================
  5. * 用户故事:管理员在后台审核管家申请,通过/驳回申请,
  6. * 分配家庭成员给管家,查看管家服务记录和佣金结算。
  7. *
  8. * 流程步骤:
  9. * 1. 管理员登录后台
  10. * 2. 打开管家审核页面
  11. * 3. 搜索筛选管家列表
  12. * 4. 查看管家详情
  13. * 5. 审核(通过或驳回)
  14. * 6. 分配家庭成员(服务订单)给管家
  15. * 7. 查看服务记录和佣金结算
  16. *
  17. * 关键里程碑:
  18. * - [Milestone-1] 管家审核页面加载成功(butler-review 报名选项卡加载)
  19. * - [Milestone-2] 能够搜索和筛选管家列表
  20. * - [Milestone-3] 成功提交审核(通过或驳回)
  21. * - [Milestone-4] 成功分配家庭成员给管家
  22. *
  23. * API 端点:
  24. * - POST /api/admin/butler/list (筛选管家列表)
  25. * - POST /api/admin/butler/review (审核管家)
  26. * - POST /api/admin/butler/assign-member (分配成员)
  27. * - POST /api/admin/butler/service-records (服务记录)
  28. * - POST /api/admin/butler/settlements (佣金结算)
  29. *
  30. * 运行:npx playwright test tests/e2e/admin-butler-review.spec.js
  31. * ================================================================
  32. */
  33. const { test, expect } = require('@playwright/test');
  34. test.describe('【场景流程】管家审核流程', () => {
  35. test.beforeEach(async ({ page }) => {
  36. // 管理员登录(admin 后台)
  37. await page.goto('http://cfc.iwintrue.com/admin/login');
  38. await page.waitForLoadState('networkidle');
  39. const adminPhone = '13701366188'; // 已验证的管理员账号
  40. const phoneInput = page.locator('input[placeholder="请输入手机号"]');
  41. await phoneInput.fill(adminPhone);
  42. await page.locator('.login-btn, button:has-text("登录")').click();
  43. await page.waitForTimeout(1500);
  44. // 验证登录成功(有 admin-tab 或管理菜单)
  45. try {
  46. await page.waitForSelector('.admin-tab, .admin-menu, .admin-layout', { timeout: 10000 });
  47. } catch (e) {
  48. // 跳过重复登录
  49. if (await page.url().includes('/login')) {
  50. await page.goto('http://cfc.iwintrue.com/admin/butler-review');
  51. await page.waitForLoadState('networkidle');
  52. }
  53. }
  54. });
  55. /**
  56. * 场景1:管家审核页面加载
  57. * 角色:管理员
  58. * 触发条件:进入后台管家审核页面
  59. * 校验:页面加载成功,tab 切换到待审核
  60. */
  61. test('[场景1] 管家审核页面加载 — 期望 tab 切换到待审核', async ({ page }) => {
  62. await page.goto('/#/pages/admin/butler-review');
  63. await page.waitForLoadState('networkidle');
  64. // 验证页面标题
  65. const title = page.locator('.el-card__header, .tab-header, h2:has-text("管家审核")');
  66. expect(await title.isVisible()).toBeTruthy();
  67. // 验证默认选中"待审核" tab
  68. const pendingTab = page.locator('.nav-item.active, .el-tab-pane.is-active, text="待审核"');
  69. expect(await pendingTab.isVisible()).toBeTruthy();
  70. });
  71. /**
  72. * 场景2:搜索筛选管家列表
  73. * 角色:管理员
  74. * 触发条件:输入管家姓名、状态、等级等筛选条件
  75. * 校验:表格刷新返回正常数据
  76. */
  77. test('[场景2] 搜索筛选管家列表 — 期望表格刷新', async ({ page }) => {
  78. await page.goto('/#/pages/admin/butler-review');
  79. await page.waitForLoadState('networkidle');
  80. // 输入筛选条件
  81. var nameInput = page.locator('input[placeholder="管家姓名"]');
  82. if (await nameInput.isVisible()) {
  83. await nameInput.fill('张三');
  84. }
  85. var statusSelect = page.locator('.el-select, .status-select, .select-status');
  86. if (await statusSelect.isVisible()) {
  87. await statusSelect.click();
  88. var pendingOption = page.locator('.el-select-dropdown__item:has-text("待审核")');
  89. await pendingOption.click();
  90. }
  91. // 点击搜索按钮
  92. var searchBtn = page.locator('.search-btn, button:has-text("搜索")');
  93. await searchBtn.click();
  94. await page.waitForTimeout(1000);
  95. // 验证表格有数据
  96. var tableRows = page.locator('.el-table__row, .table-row');
  97. var rowCount = await tableRows.count();
  98. expect(rowCount).toBeGreaterThanOrEqual(0); // 可能为空,但不报 500
  99. // 验证列数(按钮、状态、创建时间等)
  100. if (rowCount > 0) {
  101. const rowCells = page.locator('.el-table__row:first-child .el-table__cell, th[aria-colindex="5"]');
  102. expect(await rowCells.count()).toBeGreaterThanOrEqual(5);
  103. }
  104. });
  105. /**
  106. * 场景3:提交管家审核(通过)
  107. * 角色:管理员
  108. * 触发条件:选择一位待审核管家,点击通过按钮
  109. * 校验:返回成功提示,状态变为"已通过"
  110. */
  111. test('[场景3] 提交管家审核(通过) — 期望成功提示且状态改变', async ({ page }) => {
  112. await page.goto('/#/pages/admin/butler-review');
  113. await page.waitForLoadState('networkidle');
  114. // 查找待审核管家(点击第一行的操作按钮)
  115. var approveBtn = page.locator('.el-table__row:first-child button:has-text("通过")');
  116. if (await approveBtn.isVisible()) {
  117. await approveBtn.click();
  118. await page.waitForTimeout(500);
  119. // 填写通过理由(可选)
  120. var reasonInput = page.locator('textarea[placeholder="可选填:通过理由"]');
  121. if (await reasonInput.isVisible()) {
  122. await reasonInput.fill('资质符合,通过审核');
  123. }
  124. // 提交
  125. var submitBtn = page.locator('.el-dialog__footer button:has-text("确定"), button.el-button--primary');
  126. await submitBtn.click();
  127. await page.waitForTimeout(1000);
  128. // 验证提示
  129. var successTip = page.locator('.el-message-box__success, .toast-success, text="通过成功"');
  130. if (await successTip.isVisible().catch(() => false)) {
  131. expect(await successTip.textContent()).toContain("通过");
  132. } else {
  133. // 刷新检查状态
  134. await page.reload();
  135. await page.waitForTimeout(500);
  136. var newStatus = page.locator('.el-table__row:first-child .el-tag:has-text("已通过")');
  137. expect(await newStatus.isVisible()).toBeTruthy();
  138. }
  139. } else {
  140. // 无待审核数据,跳过
  141. expect(true).toBeTruthy();
  142. }
  143. });
  144. /**
  145. * 场景4:提交管家审核(驳回)
  146. * 角色:管理员
  147. * 触发条件:选择一位待审核管家,点击驳回按钮
  148. * 校验:返回成功提示,状态变为"已驳回"
  149. */
  150. test('[场景4] 提交管家审核(驳回) — 期望成功提示且状态改变', async ({ page }) => {
  151. await page.goto('/#/pages/admin/butler-review');
  152. await page.waitForLoadState('networkidle');
  153. // 查找待审核管家
  154. var rejectBtn = page.locator('.el-table__row:first-child button:has-text("驳回")');
  155. if (await rejectBtn.isVisible()) {
  156. await rejectBtn.click();
  157. await page.waitForTimeout(500);
  158. // 填写驳回理由
  159. var reasonInput = page.locator('textarea[placeholder="请填写驳回理由"]');
  160. await reasonInput.fill('资料不齐,请补充身份证照片');
  161. // 提交
  162. var submitBtn = page.locator('.el-dialog__footer button:has-text("确定"), button.el-button--primary');
  163. await submitBtn.click();
  164. await page.waitForTimeout(1000);
  165. // 验证提示
  166. var successTip = page.locator('.el-message-box__success, .toast-success, text="驳回成功"');
  167. expect(await successTip.isVisible().catch(() => false)).toBeTruthy();
  168. } else {
  169. // 无待审核数据,跳过
  170. expect(true).toBeTruthy();
  171. }
  172. });
  173. /**
  174. * 场景5:分配家庭成员给管家
  175. * 角色:管理员
  176. * 触发条件:选定一位管家,从服务订单中选择家庭成员进行分配
  177. * 校验:提示分配成功,管家服务记录增加
  178. */
  179. test('[场景5] 分配家庭成员给管家 — 期望成功并更新服务记录', async ({ page }) => {
  180. await page.goto('/#/pages/admin/butler-review');
  181. await page.waitForLoadState('networkidle');
  182. // 切换到"已通过"管家列表
  183. var activeTab = page.locator('.el-tabs__item:has-text("已通过"), .nav-item:has-text("已通过")');
  184. await activeTab.click();
  185. await page.waitForTimeout(500);
  186. // 查找操作栏的"分配服务"按钮
  187. var assignBtn = page.locator('.el-table__row:first-child button:has-text("分配服务")');
  188. if (await assignBtn.isVisible()) {
  189. await assignBtn.click();
  190. await page.waitForTimeout(500);
  191. // 在弹窗中选择成员(勾选第一项)
  192. var memberCheckbox = page.locator('.el-checkbox:first-child input[type=checkbox]');
  193. await memberCheckbox.check();
  194. await page.waitForTimeout(500);
  195. // 提交
  196. var submitBtn = page.locator('.el-dialog__footer button:has-text("分配");');
  197. await submitBtn.click();
  198. await page.waitForTimeout(1000);
  199. // 验证提示
  200. var successTip = page.locator('.toast-success, text="分配成功"');
  201. expect(await successTip.isVisible().catch(() => false)).toBeTruthy();
  202. // 验证服务记录页面刷新
  203. await page.goto('/#/pages/admin/service-records');
  204. await page.waitForLoadState('networkidle');
  205. var tableRows = page.locator('.el-table__row');
  206. expect(await tableRows.count()).toBeGreaterThanOrEqual(0);
  207. } else {
  208. // 无已通过管家,跳过
  209. expect(true).toBeTruthy();
  210. }
  211. });
  212. /**
  213. * 场景6:查看管家服务记录
  214. * 角色:管理员
  215. * 触发条件:切换到"服务记录" tab
  216. * 校验:表格加载正常数据
  217. */
  218. test('[场景6] 查看管家服务记录 — 期望表格加载', async ({ page }) => {
  219. await page.goto('/#/pages/admin/butler-review');
  220. await page.waitForLoadState('networkidle');
  221. // 切换到服务记录 tab
  222. var serviceTab = page.locator('.el-tabs__item:has-text("服务记录"), .nav-item:has-text("服务记录")');
  223. await serviceTab.click();
  224. await page.waitForTimeout(1000);
  225. // 验证表格加载
  226. var tableRows = page.locator('.el-table__row, .service-record-row');
  227. var rowCount = await tableRows.count();
  228. expect(rowCount).toBeGreaterThanOrEqual(0);
  229. // 验证记录展示内容
  230. if (rowCount > 0) {
  231. var firstRowCells = page.locator('.el-table__row:first-child .el-table__cell');
  232. expect(await firstRowCells.count()).toBeGreaterThanOrEqual(7); // 管家/成员/订单/服务类型/状态/时间/操作
  233. }
  234. });
  235. /**
  236. * 场景7:查看管家佣金结算
  237. * 角色:管理员
  238. * 触发条件:切换到"佣金结算" tab
  239. * 校验:表格加载正常数据
  240. */
  241. test('[场景7] 查看管家佣金结算 — 期望加载结算记录', async ({ page }) => {
  242. await page.goto('/#/pages/admin/butler-review');
  243. await page.waitForLoadState('networkidle');
  244. // 切换到佣金结算 tab
  245. var commissionTab = page.locator('.el-tabs__item:has-text("佣金结算"), .nav-item:has-text("佣金结算")');
  246. await commissionTab.click();
  247. await page.waitForTimeout(1000);
  248. // 验证表格加载
  249. var tableRows = page.locator('.el-table__row, .commission-row');
  250. var rowCount = await tableRows.count();
  251. expect(rowCount).toBeGreaterThanOrEqual(0);
  252. // 验证记录展示内容
  253. if (rowCount > 0) {
  254. var firstRowCells = page.locator('.el-table__row:first-child .el-table__cell');
  255. expect(await firstRowCells.count()).toBeGreaterThanOrEqual(8); // 管家/年度/月份/收入/可提现/实际提现/状态/操作
  256. }
  257. });
  258. });