/** * ================================================================ * 场景:能量系统收支全流程 E2E 测试 * ================================================================ * 用户故事:作为家长,我希望了解和管理家庭成员的五维能量收支情况, * 通过完成任务获取能量,用能量兑换奖励。 * * 流程步骤: * 1. 查看家庭能量沙盘,了解各维度能量分布 * 2. 孩子完成任务,获得能量奖励(收入) * 3. 使用能量兑换心愿或参与活动(支出) * 4. 系统根据收支计算新的维度比例 * 5. 综合健康指数更新 * * 关键里程碑: * - [Milestone-1] 获取能量沙盘,了解当前能量状态 * - [Milestone-2] 任务完成,能量发放成功 * - [Milestone-3] 能量兑换,积分扣减 * - [Milestone-4] 维度比例重算 * - [Milestone-5] 健康指数更新 * ================================================================ * * 运行:npx playwright test tests/e2e/energy-system.spec.js */ const { test, expect } = require('@playwright/test'); test.describe('【场景流程】能量系统收支全流程', () => { // ===== 场景1:获取家庭能量沙盘 ===== /** * 场景:家长查看家庭的五维能量分布 * 角色:家长 * 触发条件:进入能量沙盘页面 */ test('[场景1] 获取家庭能量沙盘 - 期望返回五维能量数据', async ({ page }) => { // ========== Given:进入能量沙盘页面 ========== await page.goto('/#/pages/energy/sandbox'); await page.waitForLoadState('networkidle'); // ========== When:页面加载完成 ========== await page.waitForSelector('.energy-sandbox, .sandbox-container', { timeout: 10000 }); // ========== Then:Milestone-1 - 返回完整能量数据 ======== // 验证五维能量显示 const bodyEnergy = page.locator('.body-energy, .energy-body'); const mindEnergy = page.locator('.mind-energy, .energy-mind'); const wisdomEnergy = page.locator('.wisdom-energy, .energy-wisdom'); const actionEnergy = page.locator('.action-energy, .energy-action'); const wealthEnergy = page.locator('.wealth-energy, .energy-wealth'); expect(await bodyEnergy.isVisible()).toBeTruthy(); expect(await mindEnergy.isVisible()).toBeTruthy(); expect(await wisdomEnergy.isVisible()).toBeTruthy(); expect(await actionEnergy.isVisible()).toBeTruthy(); expect(await wealthEnergy.isVisible()).toBeTruthy(); // 验证健康指数显示 const healthIndex = page.locator('.health-index, .index-value'); if (await healthIndex.isVisible()) { const indexText = await healthIndex.textContent(); expect(indexText).toMatch(/\d+/); } }); /** * 场景:用户未加入任何家庭 * 角色:用户 * 触发条件:用户尝试查看能量但未加入家庭 */ test('[场景1b] 用户未加入家庭 - 期望返回错误提示', async ({ page }) => { // ========== Given:用户未加入家庭(使用模拟数据)========== await page.goto('/#/pages/energy/sandbox'); await page.waitForLoadState('networkidle'); // ========== When:请求能量沙盘 ========== await page.waitForTimeout(2000); // ========== Then:返回错误或空状态 ======== const errorTip = page.locator('.error-tip, .no-family-tip'); const emptyState = page.locator('.empty-state, .no-data'); const hasError = await errorTip.isVisible(); const hasEmpty = await emptyState.isVisible(); expect(hasError || hasEmpty).toBeTruthy(); }); // ===== 场景2:任务完成能量发放 ===== /** * 场景:孩子完成任务后,系统自动发放能量奖励 * 角色:系统(自动触发) * 触发条件:任务状态变更为"已完成" */ test('[场景2] 任务完成能量发放 - 期望能量增加且流水记录', async ({ page }) => { // ========== Given:完成任务后进入任务详情 ========== await page.goto('/#/pages/tasks/complete/1'); await page.waitForLoadState('networkidle'); // ========== When:查看任务完成状态 ========== await page.waitForSelector('.task-complete, .task-done', { timeout: 10000 }); // ========== Then:Milestone-2 - 能量发放成功 ======== // 验证能量奖励显示 const energyReward = page.locator('.energy-reward, .reward-amount'); if (await energyReward.isVisible()) { const rewardText = await energyReward.textContent(); expect(rewardText).toMatch(/\d+/); } // 验证能量发放提示 const grantTip = page.locator('.energy-granted, .grant-success'); if (await grantTip.isVisible()) { expect(await grantTip.isVisible()).toBeTruthy(); } }); // ===== 场景3:能量兑换心愿 ===== /** * 场景:孩子使用积累的能量兑换心愿 * 角色:孩子 * 触发条件:兑换心愿时选择能量支付 */ test('[场景3] 能量兑换心愿 - 期望能量扣减', async ({ page }) => { // ========== Given:进入心愿兑换页面 ========== await page.goto('/#/pages/wishes/exchange/1'); await page.waitForLoadState('networkidle'); // ========== Step 1:选择能量支付 ========== const energyPayOption = page.locator('.pay-method:has-text("能量"), .energy-pay'); if (await energyPayOption.isVisible()) { await energyPayOption.click(); } // ========== When:确认兑换 ========== await page.click('.confirm-exchange-btn, .exchange-btn'); // ========== Then:Milestone-3 - 能量扣减成功 ======== await page.waitForSelector('.exchange-success, .energy-deducted, .success-tip', { timeout: 10000 }); // 验证能量扣减提示 const deductTip = page.locator('.energy-deducted, .deduct-success'); expect(await deductTip.isVisible()).toBeTruthy(); // 验证剩余能量显示 const remainingEnergy = page.locator('.remaining-energy, .current-energy'); if (await remainingEnergy.isVisible()) { const energyText = await remainingEnergy.textContent(); expect(energyText).toMatch(/\d+/); } }); /** * 场景:能量不足时兑换心愿 * 角色:孩子 * 触发条件:当前能量不足以支付 */ test('[场景3b] 能量不足时兑换 - 期望返回错误', async ({ page }) => { // ========== Given:能量不足 ========== await page.goto('/#/pages/wishes/exchange/999'); await page.waitForLoadState('networkidle'); // ========== When:点击兑换 ========== const exchangeBtn = page.locator('.exchange-btn, .confirm-exchange-btn'); if (await exchangeBtn.isVisible()) { await exchangeBtn.click(); // ========== Then:返回错误 ======== await page.waitForSelector('.error-tip, .insufficient-energy', { timeout: 5000 }); const errorTip = page.locator('.error-tip, .insufficient-energy'); expect(await errorTip.isVisible()).toBeTruthy(); expect(await errorTip.textContent()).toMatch(/能量|不足/); } }); // ===== 场景4:查询能量流水 ===== /** * 场景:查看能量收支明细 * 角色:家长或孩子 * 触发条件:进入能量明细页面 */ test('[场景4] 查询能量流水 - 期望返回分页记录', async ({ page }) => { // ========== Given:进入能量流水页面 ========== await page.goto('/#/pages/energy/logs'); await page.waitForLoadState('networkidle'); // ========== Step 1:选择孩子(如果是家长)========== const childPicker = page.locator('.child-picker'); if (await childPicker.isVisible()) { await childPicker.click(); await page.waitForSelector('.child-option', { timeout: 5000 }); await page.click('.child-option:first-child'); } // ========== When:查看流水列表 ========== await page.waitForSelector('.log-item, .energy-log', { timeout: 10000 }); // ========== Then:返回流水列表 ======== const logItems = page.locator('.log-item, .energy-log'); const count = await logItems.count(); expect(count).toBeGreaterThan(0); // 验证流水类型显示(收入/支出) const firstLog = logItems.first(); const logType = firstLog.locator('.log-type, .type-tag'); if (await logType.isVisible()) { const typeText = await logType.textContent(); expect(typeText).toMatch(/收入|支出|奖励|消耗/); } }); // ===== 场景5:获取五维能量概览 ===== /** * 场景:查看孩子的五维能量概览 * 角色:家长 * 触发条件:查看孩子的能量总览 */ test('[场景5] 获取五维能量概览 - 期望返回五维汇总数据', async ({ page }) => { // ========== Given:进入能量概览页面 ========== await page.goto('/#/pages/energy/overview'); await page.waitForLoadState('networkidle'); // ========== Step 1:选择孩子 ========== const childPicker = page.locator('.child-picker'); if (await childPicker.isVisible()) { await childPicker.click(); await page.waitForSelector('.child-option', { timeout: 5000 }); await page.click('.child-option:first-child'); } // ========== When:查看能量概览 ========== await page.waitForSelector('.energy-overview, .overview-container', { timeout: 10000 }); // ========== Then:Milestone-5 - 返回概览数据包含健康指数 ======== // 验证总能量显示 const totalEnergy = page.locator('.total-energy, .energy-total'); expect(await totalEnergy.isVisible()).toBeTruthy(); // 验证五维数据存在 const dimensionEnergies = page.locator('.dimension-energy'); const dimensionCount = await dimensionEnergies.count(); expect(dimensionCount).toBeGreaterThanOrEqual(5); // 验证健康指数 const healthIndex = page.locator('.health-index, .index-value'); if (await healthIndex.isVisible()) { const indexText = await healthIndex.textContent(); expect(indexText).toMatch(/\d+/); } }); // ===== 场景6:完整能量收支流程(端到端)===== test('[场景6] 完整能量收支流程 - 期望全流程成功', async ({ page }) => { // ========== Step 1:查看能量沙盘 ========== await page.goto('/#/pages/energy/sandbox'); await page.waitForLoadState('networkidle'); await page.waitForSelector('.energy-sandbox', { timeout: 10000 }); // 记录初始能量值 const initialTotal = page.locator('.total-energy, .energy-total'); let initialValue = 0; if (await initialTotal.isVisible()) { const text = await initialTotal.textContent(); initialValue = parseInt(text.replace(/\D/g, '')) || 0; } // ========== Step 2:完成任务获得能量 ========== await page.goto('/#/pages/tasks/complete/1'); await page.waitForLoadState('networkidle'); await page.waitForSelector('.task-complete, .energy-reward', { timeout: 10000 }); // ========== Step 3:查看流水确认收入 ========== await page.goto('/#/pages/energy/logs'); await page.waitForLoadState('networkidle'); await page.waitForSelector('.log-item', { timeout: 10000 }); // 验证有收入记录 const incomeLog = page.locator('.log-item:has-text("收入"), .log-item:has-text("奖励")').first(); expect(await incomeLog.isVisible()).toBeTruthy(); // ========== Step 4:查看更新后的能量值 ========== await page.goto('/#/pages/energy/sandbox'); await page.waitForLoadState('networkidle'); const updatedTotal = page.locator('.total-energy, .energy-total'); if (await updatedTotal.isVisible()) { const text = await updatedTotal.textContent(); const updatedValue = parseInt(text.replace(/\D/g, '')) || 0; // 能量应该增加 expect(updatedValue).toBeGreaterThanOrEqual(initialValue); } // ========== Step 5:查看概览 ========== await page.goto('/#/pages/energy/overview'); await page.waitForLoadState('networkidle'); await page.waitForSelector('.energy-overview', { timeout: 10000 }); // 验证五维数据 const dimensions = page.locator('.dimension-energy'); expect(await dimensions.count()).toBeGreaterThanOrEqual(5); }); });