assessment-order-flow.spec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /**
  2. * ================================================================
  3. * 场景:测评管理全流程 E2E 测试(cfc-web 管理端版)
  4. * ================================================================
  5. * 适配远程环境:cfc-web 管理端 (/admin),非 uni-app H5
  6. * 前置条件:无(远程 API 和 SPA 已部署,独立测试账号可用)
  7. * 运行:npx playwright test tests/e2e/assessment-order-flow.spec.js --config=playwright.remote.config.js
  8. *
  9. * 5 个场景对应已部署的 admin 测评页面:
  10. * 1. /assessment-admin - 测评管理(积分配置 + 资料管理)
  11. * 2. /assessment-orders - 测评订单(预约管理 + 筛选搜索)
  12. * 3. /assessment-assign - 待分配规划师
  13. * 4. /dan-execution - DAN服务执行管理
  14. * 5. /assessment-products - 测评商品管理
  15. * ================================================================
  16. */
  17. const { test, expect } = require('@playwright/test');
  18. var BASE_URL = 'http://cfc.iwintrue.com';
  19. var APP_PREFIX = '/admin';
  20. // ================================================================
  21. // 登录 helper:API 登录 → 注入 localStorage(与 menu-survey 一致)
  22. // ================================================================
  23. var ADMIN_PHONE = '13800138000';
  24. var ADMIN_PASSWORD = 'admin123';
  25. async function loginAsAdmin(page) {
  26. var res = await page.request.post(BASE_URL + '/api/admin-auth/login-by-password', {
  27. data: { phone: ADMIN_PHONE, password: ADMIN_PASSWORD },
  28. headers: { 'Content-Type': 'application/json' }
  29. });
  30. expect(res.ok()).toBeTruthy();
  31. var body = await res.json();
  32. expect(body.code).toBe(200);
  33. expect(body.data && body.data.token).toBeTruthy();
  34. var token = body.data.token;
  35. var role = body.data.role || 'admin';
  36. var roles = body.data.roles && body.data.roles.length ? body.data.roles : [role];
  37. // 注意:addInitScript 只接受一个 arg,必须打包成单个对象传参
  38. await page.addInitScript(function (auth) {
  39. localStorage.setItem('token', auth.token);
  40. localStorage.setItem('access_token', auth.token);
  41. localStorage.setItem('role', auth.role);
  42. localStorage.setItem('roles', JSON.stringify(auth.roles));
  43. localStorage.setItem('adminId', String(auth.adminId));
  44. }, { token: token, role: role, roles: roles, adminId: body.data.adminId });
  45. }
  46. test.describe('【场景流程】测评管理全流程 (cfc-web)', () => {
  47. /**
  48. * 场景1:测评管理页加载
  49. * 页面:/assessment-admin → Assessment.vue
  50. * 验证:积分配置表单 + 测评资料表格均渲染
  51. */
  52. test('[场景1] 测评管理页 - 期望积分配置与资料表格可见', async ({ page }) => {
  53. await loginAsAdmin(page);
  54. await page.goto(BASE_URL + APP_PREFIX + '/assessment-admin', { waitUntil: 'networkidle', timeout: 60000 });
  55. // 1. 页面根容器
  56. await expect(page.locator('.admin-page')).toBeVisible({ timeout: 15000 });
  57. // 2. 积分配置卡片:el-form + el-input-number
  58. var configCard = page.locator('.config-card');
  59. await expect(configCard).toBeVisible();
  60. // 3. 测评资料卡片:表格 el-table 渲染
  61. var materialsCard = page.locator('.materials-card');
  62. await expect(materialsCard).toBeVisible();
  63. // 4. 表格存在(可能有数据或空态)
  64. var table = page.locator('.el-table');
  65. await expect(table.first()).toBeVisible();
  66. // 5. 搜索框存在
  67. var searchInput = page.locator('.el-input__inner').first();
  68. await expect(searchInput).toBeVisible();
  69. // 6. 添加资料按钮存在
  70. var addBtn = page.locator('button:has-text("添加资料")');
  71. await expect(addBtn).toBeVisible();
  72. });
  73. /**
  74. * 场景2:测评订单管理 - 搜索与状态筛选
  75. * 页面:/assessment-orders → AssessmentOrders.vue
  76. * 验证:标题 + 预约表格 + 筛选组件 + 搜索功能
  77. */
  78. test('[场景2] 测评订单管理 - 期望预约表格与筛选功能可用', async ({ page }) => {
  79. await loginAsAdmin(page);
  80. await page.goto(BASE_URL + APP_PREFIX + '/assessment-orders', { waitUntil: 'networkidle', timeout: 60000 });
  81. // 1. 页面标题
  82. var title = page.locator('.admin-page-title');
  83. await expect(title).toContainText('测评预约管理');
  84. // 2. 表格存在
  85. var table = page.locator('.el-table');
  86. await expect(table.first()).toBeVisible({ timeout: 15000 });
  87. // 3. 表格列标签(用户/孩子/测评方案/状态等)
  88. var headerCells = page.locator('.el-table__header th');
  89. var headerCount = await headerCells.count();
  90. expect(headerCount).toBeGreaterThanOrEqual(5);
  91. // 4. 状态筛选下拉框
  92. var statusSelect = page.locator('.el-select').first();
  93. await expect(statusSelect).toBeVisible();
  94. // 5. 搜索输入框(用 placeholder 定位,避免与 el-select 的 input 混淆)
  95. var searchInput = page.locator('input[placeholder*="搜索"]');
  96. await expect(searchInput).toBeVisible();
  97. // 6. 搜索按钮(使用 force 避免 el-select 下拉箭头遮罩)
  98. var searchBtn = page.locator('button:has-text("搜索")');
  99. await expect(searchBtn).toBeVisible();
  100. // 7. 执行搜索(输入关键词测试筛选功能)
  101. await searchInput.fill('13701366188');
  102. await searchBtn.click({ force: true });
  103. await page.waitForTimeout(2000);
  104. // 搜索后表格仍在(可能无结果,但组件正常工作)
  105. await expect(table.first()).toBeVisible();
  106. // 8. 分页组件存在(数据较多时展示)
  107. var pagination = page.locator('.el-pagination');
  108. var hasPagination = await pagination.isVisible().catch(function () { return false; });
  109. // 分页可能不显示(数据量小),有则断言,无则跳过
  110. if (hasPagination) {
  111. await expect(pagination).toBeVisible();
  112. }
  113. });
  114. /**
  115. * 场景3:待分配规划师
  116. * 页面:/assessment-assign → AssessmentAssign.vue
  117. * 验证:待分配列表 + 分配规划师按钮存在
  118. */
  119. test('[场景3] 待分配规划师 - 期望列表与分配功能可用', async ({ page }) => {
  120. await loginAsAdmin(page);
  121. await page.goto(BASE_URL + APP_PREFIX + '/assessment-assign', { waitUntil: 'networkidle', timeout: 60000 });
  122. // 1. 页面标题
  123. var title = page.locator('.admin-page-title');
  124. await expect(title).toContainText('待分配规划师');
  125. // 2. 表格存在(可能有记录或空态)
  126. var table = page.locator('.el-table');
  127. await expect(table.first()).toBeVisible({ timeout: 15000 });
  128. // 3. 表格列标签(ID/用户/孩子/预约日期等)
  129. var headerCells = page.locator('.el-table__header th');
  130. var headerCount = await headerCells.count();
  131. expect(headerCount).toBeGreaterThanOrEqual(4);
  132. // 4. 操作列有"分配规划师"按钮(每行一个)
  133. var assignBtn = page.locator('button:has-text("分配规划师")').first();
  134. var hasAssignBtn = await assignBtn.isVisible().catch(function () { return false; });
  135. if (hasAssignBtn) {
  136. // 有数据行时验证按钮可点击
  137. await expect(assignBtn).toBeEnabled();
  138. }
  139. // 5. 刷新按钮存在
  140. var refreshBtn = page.locator('button:has-text("刷新")');
  141. await expect(refreshBtn).toBeVisible();
  142. });
  143. /**
  144. * 场景4:DAN服务执行管理
  145. * 页面:/dan-execution → DanExecution.vue
  146. * 验证:执行列表 + 状态筛选 + 搜索功能
  147. */
  148. test('[场景4] DAN服务执行管理 - 期望执行列表与筛选可用', async ({ page }) => {
  149. await loginAsAdmin(page);
  150. await page.goto(BASE_URL + APP_PREFIX + '/dan-execution', { waitUntil: 'networkidle', timeout: 60000 });
  151. // 1. 页面标题
  152. var title = page.locator('.admin-page-title');
  153. await expect(title).toContainText('DAN测评服务执行管理');
  154. // 2. 表格存在
  155. var table = page.locator('.el-table');
  156. await expect(table.first()).toBeVisible({ timeout: 15000 });
  157. // 3. 表格列标签(ID/订单ID/评估师状态/规划师状态等)
  158. var headerCells = page.locator('.el-table__header th');
  159. var headerCount = await headerCells.count();
  160. expect(headerCount).toBeGreaterThanOrEqual(5);
  161. // 4. 执行状态筛选下拉框
  162. var statusSelect = page.locator('.el-select').first();
  163. await expect(statusSelect).toBeVisible();
  164. // 5. 搜索按钮
  165. var searchBtn = page.locator('button:has-text("搜索")');
  166. await expect(searchBtn).toBeVisible();
  167. // 6. 表格行中的数据若存在则验证状态标签
  168. var statusTag = page.locator('.el-tag').first();
  169. var hasTag = await statusTag.isVisible().catch(function () { return false; });
  170. if (hasTag) {
  171. var tagText = await statusTag.textContent();
  172. expect(tagText).toBeTruthy();
  173. }
  174. });
  175. /**
  176. * 场景5:测评商品管理
  177. * 页面:/assessment-products → AssessmentProducts.vue
  178. * 验证:商品列表 + 搜索 + 状态筛选 + 新增商品按钮
  179. */
  180. test('[场景5] 测评商品管理 - 期望商品列表与筛选功能可用', async ({ page }) => {
  181. await loginAsAdmin(page);
  182. await page.goto(BASE_URL + APP_PREFIX + '/assessment-products', { waitUntil: 'networkidle', timeout: 60000 });
  183. // 1. 页面标题
  184. var title = page.locator('.admin-page-title');
  185. await expect(title).toContainText('测评商品管理');
  186. // 2. 表格存在
  187. var table = page.locator('.el-table');
  188. await expect(table.first()).toBeVisible({ timeout: 15000 });
  189. // 3. 表格列标签(ID/商品名称/状态/售价等)
  190. var headerCells = page.locator('.el-table__header th');
  191. var headerCount = await headerCells.count();
  192. expect(headerCount).toBeGreaterThanOrEqual(5);
  193. // 4. 搜索框(用 placeholder 定位)
  194. var searchInput = page.locator('input[placeholder*="搜索"]');
  195. await expect(searchInput).toBeVisible();
  196. // 5. 商品状态筛选下拉框
  197. var statusSelect = page.locator('.el-select').first();
  198. await expect(statusSelect).toBeVisible();
  199. // 6. 新增测评商品按钮
  200. var addBtn = page.locator('button:has-text("新增测评商品")');
  201. await expect(addBtn).toBeVisible();
  202. // 7. 查询按钮
  203. var queryBtn = page.locator('button:has-text("查询")');
  204. await expect(queryBtn).toBeVisible();
  205. // 8. 执行搜索测试
  206. await searchInput.fill('测评');
  207. // 触发搜索(按回车或点击查询按钮)
  208. await queryBtn.click({ force: true });
  209. await page.waitForTimeout(2000);
  210. // 搜索后表格仍在
  211. await expect(table.first()).toBeVisible();
  212. });
  213. });