guide-family-list.spec.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /**
  2. * ================================================================
  3. * 场景:成长规划师家庭管理 E2E 测试
  4. * ================================================================
  5. * 用户故事:成长规划师可以查看自己管理的家庭列表,
  6. * 了解每个家庭的成员构成和服务记录。
  7. *
  8. * 流程步骤:
  9. * 1. 规划师登录后台
  10. * 2. 进入家庭管理页面
  11. * 3. 查看家庭列表
  12. * 4. 查看家庭详情
  13. * 5. 查看服务记录
  14. *
  15. * 关键里程碑:
  16. * - [Milestone-1] 家庭管理页面加载成功
  17. * - [Milestone-2] 家庭列表加载正常
  18. * - [Milestone-3] 家庭详情可查看
  19. * - [Milestone-4] 服务记录可查询
  20. *
  21. * API 端点:
  22. * - POST /api/guide/family/list (家庭列表)
  23. *
  24. * 运行:npx playwright test tests/e2e/guide-family-list.spec.js
  25. * ================================================================
  26. */
  27. const { test, expect } = require('@playwright/test');
  28. test.describe('【场景流程】成长规划师家庭管理', () => {
  29. test.beforeEach(async ({ page }) => {
  30. // 规划师登录(admin 后台)
  31. await page.goto('http://cfc.iwintrue.com/admin/login');
  32. await page.waitForLoadState('networkidle');
  33. const guidePhone = '13701366189'; // 测试规划师账号
  34. const phoneInput = page.locator('input[placeholder="请输入手机号"]');
  35. await phoneInput.fill(guidePhone);
  36. await page.locator('.login-btn, button:has-text("登录")').click();
  37. await page.waitForTimeout(1500);
  38. // 验证登录成功
  39. try {
  40. await page.waitForSelector('.guide-tab, .teacher-tab, .admin-layout', { timeout: 10000 });
  41. } catch (e) {
  42. if (await page.url().includes('/login')) {
  43. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  44. await page.waitForLoadState('networkidle');
  45. }
  46. }
  47. });
  48. /**
  49. * 场景1:家庭管理页面加载
  50. * 角色:成长规划师
  51. * 触发条件:进入家庭管理页面
  52. * 校验:页面加载成功,tab 切换到家庭列表
  53. */
  54. test('[场景1] 家庭管理页面加载 — 期望 tab 切换到家庭列表', async ({ page }) => {
  55. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  56. await page.waitForLoadState('networkidle');
  57. // 验证页面标题
  58. const title = page.locator('.el-card__header, .tab-header, h2:has-text("家庭管理")');
  59. expect(await title.isVisible()).toBeTruthy();
  60. // 验证默认选中"家庭列表" tab
  61. const listTab = page.locator('.nav-item.active, .el-tab-pane.is-active, text="家庭列表"');
  62. expect(await listTab.isVisible()).toBeTruthy();
  63. });
  64. /**
  65. * 场景2:家庭列表加载
  66. * 角色:成长规划师
  67. * 触发条件:进入家庭管理页面
  68. * 校验:列表加载正常数据
  69. */
  70. test('[场景2] 家庭列表加载 — 期望数据加载', async ({ page }) => {
  71. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  72. await page.waitForLoadState('networkidle');
  73. // 验证列表加载
  74. const familyRows = page.locator('.el-table__row, .family-row');
  75. const rowCount = await familyRows.count();
  76. expect(rowCount).toBeGreaterThanOrEqual(0);
  77. // 验证列数
  78. if (rowCount > 0) {
  79. const firstRow = familyRows.first();
  80. const cells = firstRow.locator('.el-table__cell');
  81. expect(await cells.count()).toBeGreaterThanOrEqual(5);
  82. }
  83. });
  84. /**
  85. * 场景3:搜索筛选家庭
  86. * 角色:成长规划师
  87. * 触发条件:输入家庭名称、状态等筛选条件
  88. * 校验:列表刷新返回正常数据
  89. */
  90. test('[场景3] 搜索筛选家庭 — 期望列表刷新', async ({ page }) => {
  91. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  92. await page.waitForLoadState('networkidle');
  93. // 输入筛选条件
  94. const nameInput = page.locator('input[placeholder="家庭名称"]');
  95. if (await nameInput.isVisible()) {
  96. await nameInput.fill('测试家庭');
  97. }
  98. // 点击搜索按钮
  99. const searchBtn = page.locator('.search-btn, button:has-text("搜索")');
  100. await searchBtn.click();
  101. await page.waitForTimeout(1000);
  102. // 验证列表刷新
  103. const familyRows = page.locator('.el-table__row');
  104. expect(await familyRows.count()).toBeGreaterThanOrEqual(0);
  105. });
  106. /**
  107. * 场景4:查看家庭详情
  108. * 角色:成长规划师
  109. * 触发条件:点击家庭列表中的"详情"按钮
  110. * 校验:家庭详情页面加载成功
  111. */
  112. test('[场景4] 查看家庭详情 — 期望详情加载', async ({ page }) => {
  113. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  114. await page.waitForLoadState('networkidle');
  115. // 查找第一个家庭的详情按钮
  116. const detailBtn = page.locator('.el-table__row:first-child button:has-text("详情")');
  117. if (await detailBtn.isVisible()) {
  118. await detailBtn.click();
  119. await page.waitForTimeout(1000);
  120. // 验证详情加载
  121. const familyInfo = page.locator('.family-info, .detail-card');
  122. expect(await familyInfo.isVisible()).toBeTruthy();
  123. // 验证家庭成员列表
  124. const memberRows = page.locator('.member-item, .el-table__row');
  125. expect(await memberRows.count()).toBeGreaterThanOrEqual(0);
  126. } else {
  127. // 无家庭数据,跳过
  128. expect(true).toBeTruthy();
  129. }
  130. });
  131. /**
  132. * 场景5:查看家庭服务记录
  133. * 角色:成长规划师
  134. * 触发条件:在家庭详情页切换到服务记录 tab
  135. * 校验:服务记录加载正常
  136. */
  137. test('[场景5] 查看家庭服务记录 — 期望记录加载', async ({ page }) => {
  138. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  139. await page.waitForLoadState('networkidle');
  140. // 查找第一个家庭的详情按钮
  141. const detailBtn = page.locator('.el-table__row:first-child button:has-text("详情")');
  142. if (await detailBtn.isVisible()) {
  143. await detailBtn.click();
  144. await page.waitForTimeout(1000);
  145. // 切换到服务记录 tab
  146. const recordTab = page.locator('.nav-item:has-text("服务记录"), .tab-item:has-text("服务")');
  147. await recordTab.click();
  148. await page.waitForTimeout(1000);
  149. // 验证记录加载
  150. const recordRows = page.locator('.el-table__row, .service-record');
  151. expect(await recordRows.count()).toBeGreaterThanOrEqual(0);
  152. } else {
  153. // 无家庭数据,跳过
  154. expect(true).toBeTruthy();
  155. }
  156. });
  157. /**
  158. * 场景6:家庭变更日志
  159. * 角色:成长规划师
  160. * 触发条件:在家庭详情页切换到变更日志 tab
  161. * 校验:变更日志加载正常
  162. */
  163. test('[场景6] 查看家庭变更日志 — 期望日志加载', async ({ page }) => {
  164. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  165. await page.waitForLoadState('networkidle');
  166. // 查找第一个家庭的详情按钮
  167. const detailBtn = page.locator('.el-table__row:first-child button:has-text("详情")');
  168. if (await detailBtn.isVisible()) {
  169. await detailBtn.click();
  170. await page.waitForTimeout(1000);
  171. // 切换到变更日志 tab
  172. const logTab = page.locator('.nav-item:has-text("变更日志"), .tab-item:has-text("日志")');
  173. await logTab.click();
  174. await page.waitForTimeout(1000);
  175. // 验证日志加载
  176. const logRows = page.locator('.el-table__row, .log-item');
  177. expect(await logRows.count()).toBeGreaterThanOrEqual(0);
  178. } else {
  179. // 无家庭数据,跳过
  180. expect(true).toBeTruthy();
  181. }
  182. });
  183. /**
  184. * 场景7:家庭关系图谱
  185. * 角色:成长规划师
  186. * 触发条件:在家庭详情页切换到关系图谱 tab
  187. * 校验:关系图谱加载正常
  188. */
  189. test('[场景7] 查看家庭关系图谱 — 期望图谱加载', async ({ page }) => {
  190. await page.goto('http://cfc.iwintrue.com/admin/guide-family');
  191. await page.waitForLoadState('networkidle');
  192. // 查找第一个家庭的详情按钮
  193. const detailBtn = page.locator('.el-table__row:first-child button:has-text("详情")');
  194. if (await detailBtn.isVisible()) {
  195. await detailBtn.click();
  196. await page.waitForTimeout(1000);
  197. // 切换到关系图谱 tab
  198. const relationTab = page.locator('.nav-item:has-text("关系图谱"), .tab-item:has-text("关系")');
  199. await relationTab.click();
  200. await page.waitForTimeout(1000);
  201. // 验证图谱加载
  202. const relationGraph = page.locator('.relation-graph, .graph-container, svg');
  203. expect(await relationGraph.isVisible().catch(() => false)).toBeTruthy();
  204. } else {
  205. // 无家庭数据,跳过
  206. expect(true).toBeTruthy();
  207. }
  208. });
  209. });