activity-registration.spec.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * ================================================================
  3. * 场景:活动报名全流程 E2E 测试
  4. * ================================================================
  5. * 用户故事:
  6. * - 管理员:创建/发布活动,审核报名
  7. * - 家长/孩子:浏览活动,报名/取消报名
  8. *
  9. * 流程步骤:
  10. * 1. 管理员创建并发布活动
  11. * 2. 家长浏览活动并报名
  12. * 3. 管理员审核报名
  13. * 4. 家长取消报名
  14. *
  15. * 关键里程碑:
  16. * - [Milestone-1] 活动发布成功
  17. * - [Milestone-2] 报名成功
  18. * - [Milestone-3] 审核成功
  19. * ================================================================
  20. *
  21. * 运行:npx playwright test tests/e2e/activity-registration.spec.js
  22. */
  23. const { test, expect } = require('@playwright/test');
  24. test.describe('【场景流程】活动报名全流程', () => {
  25. // ===== 场景1:管理员创建并发布活动 =====
  26. test('[场景1] 管理员创建并发布活动 - 期望发布成功', async ({ page }) => {
  27. // ========== Given:管理员进入活动管理页 ==========
  28. await page.goto('/#/pages/admin/activity-list');
  29. await page.waitForLoadState('networkidle');
  30. // ========== When:创建活动 ==========
  31. const createBtn = page.locator('.create-btn, .add-activity-btn');
  32. if (await createBtn.isVisible()) {
  33. await createBtn.click();
  34. } else {
  35. await page.goto('/#/pages/admin/activity-create');
  36. await page.waitForLoadState('networkidle');
  37. }
  38. await page.waitForSelector('.activity-form, .create-form', { timeout: 5000 });
  39. // 填写活动名称
  40. const titleInput = page.locator('input[name="title"], .title-input');
  41. if (await titleInput.isVisible()) {
  42. await titleInput.fill('测试活动_' + Date.now());
  43. }
  44. // 填写活动描述
  45. const descInput = page.locator('textarea[name="description"], .desc-input');
  46. if (await descInput.isVisible()) {
  47. await descInput.fill('这是一个测试活动,描述活动的具体内容。');
  48. }
  49. // 填写地点
  50. const locationInput = page.locator('input[name="location"], .location-input');
  51. if (await locationInput.isVisible()) {
  52. await locationInput.fill('线上活动');
  53. }
  54. // 填写人数上限
  55. const maxInput = page.locator('input[name="maxParticipants"], .max-input');
  56. if (await maxInput.isVisible()) {
  57. await maxInput.fill('50');
  58. }
  59. // 发布活动
  60. await page.click('.publish-btn, .submit-btn');
  61. // ========== Then:Milestone-1 - 发布成功 ========
  62. await page.waitForSelector('.success-tip, .publish-success', { timeout: 10000 });
  63. expect(await page.locator('.success-tip, .publish-success').isVisible()).toBeTruthy();
  64. });
  65. // ===== 场景2:家长浏览活动并报名 =====
  66. test('[场景2] 家长浏览活动并报名 - 期望报名成功', async ({ page }) => {
  67. // ========== Given:家长进入活动列表页 ==========
  68. await page.goto('/#/pages/discover-detail/activity-list');
  69. await page.waitForLoadState('networkidle');
  70. // ========== When:浏览并选择活动 ==========
  71. await page.waitForSelector('.activity-item, .activity-card', { timeout: 10000 });
  72. // 点击第一个活动
  73. await page.locator('.activity-item').first().click();
  74. // 等待活动详情加载
  75. await page.waitForSelector('.activity-detail, .detail-content', { timeout: 5000 });
  76. // 点击报名按钮
  77. const registerBtn = page.locator('.register-btn, .sign-up-btn, .apply-btn');
  78. if (await registerBtn.isVisible()) {
  79. await registerBtn.click();
  80. }
  81. // 选择孩子
  82. const childSelect = page.locator('.child-picker, .select-child');
  83. if (await childSelect.isVisible()) {
  84. await childSelect.click();
  85. await page.waitForSelector('.child-option', { timeout: 3000 });
  86. await page.locator('.child-option').first().click();
  87. }
  88. // 确认报名
  89. await page.click('.confirm-btn, .submit-btn');
  90. // ========== Then:Milestone-2 - 报名成功 ========
  91. await page.waitForSelector('.success-tip, .register-success, .toast-success', { timeout: 10000 });
  92. expect(await page.locator('.success-tip, .register-success').isVisible()).toBeTruthy();
  93. });
  94. // ===== 场景3:管理员审核报名 =====
  95. test('[场景3] 管理员审核报名 - 期望审核成功', async ({ page }) => {
  96. // ========== Given:管理员进入报名管理页 ==========
  97. await page.goto('/#/pages/admin/registration-list');
  98. await page.waitForLoadState('networkidle');
  99. // ========== When:审核报名 ==========
  100. await page.waitForSelector('.registration-item, .apply-item', { timeout: 10000 });
  101. const approveBtn = page.locator('.approve-btn, .pass-btn').first();
  102. if (await approveBtn.isVisible()) {
  103. await approveBtn.click();
  104. }
  105. // ========== Then:Milestone-3 - 审核成功 ========
  106. await page.waitForTimeout(500);
  107. // 验证状态变化
  108. const statusTag = page.locator('.status-tag, .registration-status');
  109. if (await statusTag.isVisible()) {
  110. const statusText = await statusTag.textContent();
  111. expect(statusText).toMatch(/已通过|approved/i);
  112. }
  113. });
  114. // ===== 场景4:家长取消报名 =====
  115. test('[场景4] 家长取消报名 - 期望取消成功', async ({ page }) => {
  116. // ========== Given:家长进入我的报名页 ==========
  117. await page.goto('/#/pages/profile/my-activities');
  118. await page.waitForLoadState('networkidle');
  119. // ========== When:取消报名 ==========
  120. await page.waitForSelector('.registration-item, .my-activity', { timeout: 10000 });
  121. const cancelBtn = page.locator('.cancel-btn, .cancel-registration').first();
  122. if (await cancelBtn.isVisible()) {
  123. await cancelBtn.click();
  124. }
  125. // 确认取消
  126. const confirmBtn = page.locator('.van-dialog__confirm, .dialog-confirm');
  127. if (await confirmBtn.isVisible()) {
  128. await confirmBtn.click();
  129. }
  130. // ========== Then:取消成功 ========
  131. await page.waitForSelector('.cancel-success, .toast-success', { timeout: 10000 });
  132. expect(await page.locator('.cancel-success, .toast-success').isVisible()).toBeTruthy();
  133. });
  134. });