| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /**
- * ================================================================
- * 场景:能量系统收支全流程 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);
- });
- });
|