points-system.spec.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. * ================================================================
  19. *
  20. * 运行:npx playwright test tests/e2e/points-system.spec.js
  21. */
  22. const { test, expect } = require('@playwright/test');
  23. test.describe('【场景流程】积分系统全流程', () => {
  24. // ===== 场景1:查看积分余额 =====
  25. test('[场景1] 查看积分余额 - 期望返回余额信息', async ({ page }) => {
  26. // ========== Given:进入积分页面 ==========
  27. await page.goto('/#/pages/profile/points');
  28. await page.waitForLoadState('networkidle');
  29. // ========== When:查看余额 ==========
  30. await page.waitForSelector('.points-card, .balance-card', { timeout: 10000 });
  31. // ========== Then:Milestone-1 - 返回余额 ========
  32. const balanceCard = page.locator('.balance-card, .points-balance');
  33. if (await balanceCard.isVisible()) {
  34. const balanceText = await balanceCard.textContent();
  35. expect(balanceText).toBeTruthy();
  36. }
  37. // 验证积分数值显示
  38. const pointsValue = page.locator('.points-value, .balance-num');
  39. if (await pointsValue.isVisible()) {
  40. const valueText = await pointsValue.textContent();
  41. expect(valueText).toMatch(/\d+/);
  42. }
  43. });
  44. // ===== 场景2:查看积分流水 =====
  45. test('[场景2] 查看积分流水 - 期望返回流水列表', async ({ page }) => {
  46. // ========== Given:进入积分流水页 ==========
  47. await page.goto('/#/pages/profile/points-detail');
  48. await page.waitForLoadState('networkidle');
  49. // ========== When:查看流水 ==========
  50. await page.waitForSelector('.flow-list, .points-log, .transaction-list', { timeout: 10000 });
  51. // ========== Then:返回流水列表 ========
  52. const flowItems = page.locator('.flow-item, .log-item, .transaction-item');
  53. const count = await flowItems.count();
  54. expect(count).toBeGreaterThanOrEqual(0);
  55. if (count > 0) {
  56. // 验证流水包含关键信息
  57. const firstItem = flowItems.first();
  58. expect(await firstItem.isVisible()).toBeTruthy();
  59. // 验证包含金额信息
  60. const amountTag = firstItem.locator('.amount, .points-change');
  61. if (await amountTag.isVisible()) {
  62. const amountText = await amountTag.textContent();
  63. expect(amountText).toBeTruthy();
  64. }
  65. }
  66. });
  67. // ===== 场景3:按分类查看流水 =====
  68. test('[场景3] 按分类查看流水 - 期望返回筛选后流水', async ({ page }) => {
  69. // ========== Given:进入积分流水页 ==========
  70. await page.goto('/#/pages/profile/points-detail');
  71. await page.waitForLoadState('networkidle');
  72. // ========== When:选择分类筛选 ==========
  73. const categoryPicker = page.locator('.category-picker, .filter-btn');
  74. if (await categoryPicker.isVisible()) {
  75. await categoryPicker.click();
  76. await page.waitForSelector('.option-item, .filter-option', { timeout: 3000 });
  77. await page.locator('.option-item').nth(1).click();
  78. }
  79. // ========== Then:返回筛选后流水 ========
  80. await page.waitForTimeout(500);
  81. const flowItems = page.locator('.flow-item, .log-item');
  82. const count = await flowItems.count();
  83. // 验证筛选生效(可能有0条或多条)
  84. expect(count).toBeGreaterThanOrEqual(0);
  85. });
  86. // ===== 场景4:家长手动调整积分 =====
  87. test('[场景4] 家长手动调整积分 - 期望调整成功', async ({ page }) => {
  88. // ========== Given:进入积分调整页 ==========
  89. await page.goto('/#/pages/profile/points-adjust');
  90. await page.waitForLoadState('networkidle');
  91. // ========== When:调整积分 ==========
  92. // 选择孩子
  93. const childSelect = page.locator('.child-picker');
  94. if (await childSelect.isVisible()) {
  95. await childSelect.click();
  96. await page.waitForSelector('.child-option', { timeout: 3000 });
  97. await page.locator('.child-option').first().click();
  98. }
  99. // 输入调整值
  100. const amountInput = page.locator('input[name="amount"], .amount-input');
  101. if (await amountInput.isVisible()) {
  102. await amountInput.fill('10');
  103. }
  104. // 输入原因
  105. const reasonInput = page.locator('textarea[name="reason"], .reason-input');
  106. if (await reasonInput.isVisible()) {
  107. await reasonInput.fill('表现优秀,额外奖励');
  108. }
  109. // 提交
  110. await page.click('.submit-btn, .adjust-btn');
  111. // ========== Then:Milestone-2 - 调整成功 ========
  112. await page.waitForSelector('.success-tip, .adjust-success, .toast-success', { timeout: 10000 });
  113. expect(await page.locator('.success-tip, .adjust-success').isVisible()).toBeTruthy();
  114. });
  115. });