/** * ================================================================ * 场景:家庭收益管理流程 E2E 测试 * ================================================================ * 用户故事:家长可以管理家庭公共账户收支,兑换心愿, * 查看家庭成员待分配余额,审核提现申请。 * * 流程步骤: * 1. 家长登录,进入个人中心 * 2. 打开家庭收益管理页面 * 3. 查看家庭收益概览 * 4. 兑换心愿(能量到现金) * 5. 分配收益给成员 * 6. 查看收益记录 * * API 端点: * - POST /api/admin/earnings/families (家庭列表) * - POST /api/admin/earnings/family/{familyId}/summary (家庭概览) * - POST /api/admin/earnings/family/{familyId}/records (收支记录) * * 运行:npx playwright test tests/e2e/family-earnings-flow.spec.js * ================================================================ */ const { test, expect } = require('@playwright/test'); test.describe('【场景流程】家庭收益管理流程', () => { test.beforeEach(async ({ page }) => { // 家长登录 await page.goto('/#/pages/login/login'); await page.waitForLoadState('networkidle'); const phone = '13701366187'; // 测试家长账号 const phoneInput = page.locator('input[type=tel], input[placeholder="手机号"]'); await phoneInput.fill(phone); await page.waitForTimeout(500); await page.locator('.login-btn, button:has-text("登录")').click(); await page.waitForTimeout(2000); try { await expect(page.locator('.home-tab, .tab-bar, .mine-tab')).toBeVisible({ timeout: 10000 }); } catch (e) { // 跳过重复登录检查 } }); /** * 场景1:家庭收益概览页面加载 * 校验:页面加载成功,显示能量、可提现、已提现数据 */ test('[场景1] 家庭收益概览页面加载', async ({ page }) => { await page.goto('/#/pages/profile/family-earnings'); await page.waitForLoadState('networkidle'); // 验证页面标题 const title = page.locator('.nav-bar, .title-wrapper, h2:has-text("家庭收益")'); expect(await title.isVisible()).toBeTruthy(); // 验证卡片展示 const energyCard = page.locator('.earnings-card, .energy-card, .balance-card'); expect(await energyCard.first().isVisible()).toBeTruthy(); // 验证统计数据 const energyData = page.locator('.balance-data, .energy-amount'); const energyText = await energyData.first().textContent(); expect(energyText.length).toBeGreaterThan(0); }); /** * 场景2:兑换心愿(能量→现金) * 校验:兑换成功,记录更新 */ test('[场景2] 兑换心愿', async ({ page }) => { await page.goto('/#/pages/profile/family-earnings'); await page.waitForLoadState('networkidle'); // 必须确保家庭有收益 const energyCard = page.locator('.earnings-card, .energy-card'); if (await energyCard.first().isVisible()) { const energyBefore = await page.locator('.energy-amount').textContent(); const availableEnergy = parseInt(energyBefore.replace(/[^0-9]/g, '')) || 0; if (availableEnergy > 0) { // 点击兑换按钮 const exchangeBtn = page.locator('button:has-text("兑换"), .exchange-btn'); await exchangeBtn.click(); await page.waitForTimeout(1000); // 输入金额 const amountInput = page.locator('input[placeholder="兑换金额"]'); await amountInput.fill('100'); // 提交 const submitBtn = page.locator('.confirm-btn, button:has-text("确定")'); await submitBtn.click(); await page.waitForTimeout(1000); // 验证提示 const successTip = page.locator('.modal-success, .toast-success, text="兑换成功"'); expect(await successTip.isVisible().catch(() => false)).toBeTruthy(); } } expect(true).toBeTruthy(); }); /** * 场景3:分配收益给家庭成员 * 校验:分配成功 */ test('[场景3] 分配收益给成员', async ({ page }) => { await page.goto('/#/pages/profile/family-earnings'); await page.waitForLoadState('networkidle'); // 点击分配按钮 const distributeBtn = page.locator('button:has-text("分配"), .distribute-btn'); await distributeBtn.click(); await page.waitForTimeout(1000); // 选择成员 const memberSelect = page.locator('.el-select-dropdown, .member-select'); if (await memberSelect.isVisible()) { await memberSelect.locator('.el-select-dropdown__item:first-child').click(); } else { await page.locator('.member-item:first-child').click(); } // 填写金额 const amountInput = page.locator('input[placeholder="分配金额"]'); await amountInput.fill('50'); // 提交 const submitBtn = page.locator('.confirm-btn, button:has-text("确定")'); await submitBtn.click(); await page.waitForTimeout(1000); // 验证提示 const successTip = page.locator('.modal-success, .toast-success, text="分配成功"'); expect(await successTip.isVisible().catch(() => false)).toBeTruthy(); }); /** * 场景4:查看收支记录列表 * 校验:列表加载正常数据 */ test('[场景4] 查看收支记录', async ({ page }) => { await page.goto('/#/pages/profile/family-earnings'); await page.waitForLoadState('networkidle'); // 切换到收支记录 tab const recordsTab = page.locator('.tab-item:has-text("收支记录")'); await recordsTab.click(); await page.waitForTimeout(1000); // 验证列表加载 const records = page.locator('.record-item, .earnings-record'); expect(await records.first().isVisible().catch(() => false)).toBeTruthy(); }); /** * 场景5:管理员视角 — 家庭收益管理 * 角色:管理员 * 触发条件:进入后台家庭收益管理页面 * 校验:查看家庭列表和收益记录 */ test('[场景5] 管理员管理家庭收益', async ({ page }) => { // 管理员登录(admin 后台) await page.goto('http://cfc.iwintrue.com/admin/login'); await page.waitForTimeout(1000); const adminPhone = '13701366188'; await page.locator('input[placeholder="请输入手机号"]').fill(adminPhone); await page.locator('button:has-text("登录")').click(); await page.waitForTimeout(2000); // 进入家庭收益管理 await page.goto('http://cfc.iwintrue.com/admin/family-earnings'); await page.waitForLoadState('networkidle'); // 验证家庭列表加载 const familyRows = page.locator('.el-table__row, .family-row'); expect(await familyRows.count()).toBeGreaterThanOrEqual(0); // 点击查看详情 if (await familyRows.count() > 0) { const firstRow = familyRows.first(); const viewBtn = firstRow.locator('button:has-text("查看")'); await viewBtn.click(); await page.waitForTimeout(500); // 验证概览数据加载 const summaryData = page.locator('.summary-card, .earnings-summary'); expect(await summaryData.isVisible()).toBeTruthy(); // 查看收益记录 const recordTab = page.locator('.tab-item:has-text("收益记录")'); await recordTab.click(); await page.waitForTimeout(500); const recordRows = page.locator('.el-table__row, .record-row'); expect(await recordRows.count()).toBeGreaterThanOrEqual(0); } }); /** * 场景6:提现申请审核流程 * 角色:管理员 * 触发条件:进入后台提现审核页面 * 校验:能查看待审核记录并操作 */ test('[场景6] 提现申请审核', async ({ page }) => { // 管理员登录(admin 后台) await page.goto('http://cfc.iwintrue.com/admin/login'); await page.locator('input[placeholder="请输入手机号"]').fill('13701366188'); await page.locator('button:has-text("登录")').click(); await page.waitForTimeout(2000); // 进入提现审核 await page.goto('http://cfc.iwintrue.com/admin/family-earnings/withdraw'); await page.waitForLoadState('networkidle'); // 验证待审核记录加载 const withdrawRows = page.locator('.el-table__row, .withdraw-row'); const rowCount = await withdrawRows.count(); if (rowCount > 0) { // 审核通过第一条 const approveBtn = withdrawRows.first().locator('button:has-text("通过")'); await approveBtn.click(); await page.waitForTimeout(500); // 提交 const submitBtn = page.locator('.confirm-btn, .el-button--primary'); await submitBtn.click(); await page.waitForTimeout(1000); // 验证提示 const successTip = page.locator('.modal-success, .toast-success'); expect(await successTip.isVisible().catch(() => false)).toBeTruthy(); } else { // 无待审核记录,跳过 expect(true).toBeTruthy(); } }); });