/** * ================================================================ * 场景:测评订单全流程 E2E 测试 * ================================================================ * 用户故事:作为家长,我希望为孩子购买专业测评服务, * 以便了解孩子的认知发展状况并获得成长建议。 * * 流程步骤: * 1. 家长选择规划师和测评套餐,进入测评申请页面 * 2. 家长填写孩子信息,提交测评申请 * 3. 家长完成支付,订单状态变更为"已支付" * 4. 系统自动确认预约,预约状态变更为"待测评" * 5. 规划师确认预约,查看孩子的基本信息(快照) * 6. 规划师完成测评,录入认知评估结果 * 7. 家长/孩子查看测评报告 * * 关键里程碑: * - [Milestone-1] 订单创建成功,获得订单号 * - [Milestone-2] 支付成功,预约自动创建 * - [Milestone-3] 规划师确认预约 * - [Milestone-4] 测评结果录入完成 * - [Milestone-5] 家长可查询到孩子的最新报告 * ================================================================ * * 运行:npx playwright test tests/e2e/assessment-order-flow.spec.js */ const { test, expect } = require('@playwright/test'); test.describe('【场景流程】测评订单全流程', () => { // ===== 场景1:家长选购测评套餐 ===== /** * 场景:家长选择规划师并购买测评套餐 * 角色:家长 * 触发条件:家长选择了具体的规划师和测评套餐 */ test('[场景1] 家长购买测评套餐并完成支付 - 期望全流程成功', async ({ page }) => { // ========== Given:家长进入测评申请页面 ========== await page.goto('/#/pages/assessment/apply'); await page.waitForLoadState('networkidle'); // 验证页面加载成功 await expect(page.locator('.assessment-apply-page')).toBeVisible({ timeout: 10000 }); // ========== Step 1:选择孩子 ========== const childSelector = page.locator('.child-picker'); if (await childSelector.isVisible()) { await childSelector.click(); await page.waitForSelector('.child-option', { timeout: 5000 }); await page.click('.child-option:first-child'); } // ========== Step 2:选择规划师(可选)========== const guideSelector = page.locator('.guide-picker'); if (await guideSelector.isVisible()) { await guideSelector.click(); await page.waitForSelector('.guide-option', { timeout: 5000 }); await page.click('.guide-option:first-child'); } // ========== Step 3:选择测评套餐 ========== await page.click('.package-option:first-child'); // ========== When:提交申请 ========== await page.click('.submit-btn'); // ========== Then:Milestone-1 - 订单创建成功 ======== // 等待订单确认弹窗或跳转 await page.waitForSelector('.order-confirm-modal, .order-success-tip', { timeout: 10000 }); // 验证订单号生成(订单号应该在页面某处显示) const orderSuccessTip = page.locator('.order-success-tip, .order-no'); if (await orderSuccessTip.isVisible()) { const orderText = await orderSuccessTip.textContent(); expect(orderText).toMatch(/订单|ASR|成功/); } // ========== Step 4:点击去支付 ========== await page.click('.go-pay-btn'); // ========== Then:Milestone-2 - 支付成功 ======== // 选择支付方式 const wechatPayOption = page.locator('.pay-method:has-text("微信支付")'); if (await wechatPayOption.isVisible()) { await wechatPayOption.click(); } // 确认支付 await page.click('.confirm-pay-btn'); // 等待支付成功提示 await page.waitForSelector('.pay-success-tip, .payment-success', { timeout: 15000 }); // 验证支付状态 const successTip = page.locator('.pay-success-tip, .payment-success'); expect(await successTip.isVisible()).toBeTruthy(); }); // ===== 场景2:自动分配规划师流程 ===== /** * 场景:家长未指定规划师,系统自动分配家庭绑定的规划师 * 角色:家长 * 触发条件:家长未指定 guideId,但家庭已绑定规划师 */ test('[场景2] 未指定规划师时系统自动分配 - 期望使用家庭绑定的规划师', async ({ page }) => { // ========== Given:家庭已绑定规划师 ========== await page.goto('/#/pages/assessment/apply'); await page.waitForLoadState('networkidle'); // ========== Step 1:选择孩子 ========== const childSelector = page.locator('.child-picker'); if (await childSelector.isVisible()) { await childSelector.click(); await page.waitForSelector('.child-option', { timeout: 5000 }); await page.click('.child-option:first-child'); } // ========== Step 2:直接选择套餐(不选规划师)========== await page.click('.package-option:first-child'); // ========== When:提交申请 ========== await page.click('.submit-btn'); // ========== Then:系统自动使用家庭绑定的规划师 ======== // 应该显示自动分配提示或规划师名称 await page.waitForSelector('.auto-assign-tip, .guide-name', { timeout: 10000 }); const guideName = page.locator('.guide-name, .guide-info'); if (await guideName.isVisible()) { const nameText = await guideName.textContent(); expect(nameText.length).toBeGreaterThan(0); } }); // ===== 场景3:规划师录入测评结果 ===== /** * 场景:规划师完成测评后,录入孩子的认知评估结果 * 角色:成长规划师 * 触发条件:预约已完成,规划师完成了一对一测评 */ test('[场景3] 规划师录入测评结果 - 期望结果保存并可查询', async ({ page }) => { // ========== Given:规划师进入测评结果录入页面 ========== await page.goto('/#/pages/guide/assessment/record'); await page.waitForLoadState('networkidle'); // ========== Step 1:选择要录入的预约 ========== await page.waitForSelector('.appointment-item', { timeout: 10000 }); await page.click('.appointment-item:first-child'); // ========== Step 2:填写测评结果 ========== // 输入各项分数 const scoreInputs = page.locator('.score-input'); const scoreCount = await scoreInputs.count(); for (let i = 0; i < scoreCount; i++) { await scoreInputs.nth(i).fill(String(Math.floor(Math.random() * 20) + 80)); } // 输入综合评语 const reportTextarea = page.locator('.analysis-report textarea, .report-textarea'); if (await reportTextarea.isVisible()) { await reportTextarea.fill('孩子整体认知发展良好,在注意力和逻辑思维方面表现突出...'); } // ========== When:提交测评结果 ========== await page.click('.submit-result-btn'); // ========== Then:Milestone-4 - 测评结果保存成功 ======== await page.waitForSelector('.submit-success-tip, .result-saved', { timeout: 10000 }); const successTip = page.locator('.submit-success-tip, .result-saved'); expect(await successTip.isVisible()).toBeTruthy(); }); // ===== 场景4:家长查询孩子测评报告 ===== /** * 场景:家长为孩子购买测评后,查看孩子的最新认知评估报告 * 角色:家长 * 触发条件:规划师已完成测评并录入结果 */ test('[场景4] 家长查询孩子最新报告 - 期望返回完整报告内容', async ({ page }) => { // ========== Given:进入测评报告页面 ========== await page.goto('/#/pages/assessment/results'); await page.waitForLoadState('networkidle'); // ========== Step 1:选择孩子 ========== const childSelector = page.locator('.child-picker'); if (await childSelector.isVisible()) { await childSelector.click(); await page.waitForSelector('.child-option', { timeout: 5000 }); await page.click('.child-option:first-child'); } // ========== When:查看报告 ========== await page.click('.view-report-btn'); // ========== Then:Milestone-5 - 返回完整报告内容 ======== await page.waitForSelector('.report-detail, .result-card', { timeout: 10000 }); // 验证报告包含必要内容 const reportDetail = page.locator('.report-detail, .result-content'); expect(await reportDetail.isVisible()).toBeTruthy(); // 验证分数显示 const scoreDisplay = page.locator('.overall-score, .score-value'); if (await scoreDisplay.isVisible()) { const scoreText = await scoreDisplay.textContent(); expect(scoreText).toMatch(/\d+/); } }); // ===== 场景5:取消未支付订单 ===== /** * 场景:家长创建订单后决定取消,选择关闭交易 * 角色:家长 * 触发条件:订单状态为"待支付" */ test('[场景5] 家长取消未支付订单 - 期望订单关闭成功', async ({ page }) => { // ========== Given:进入我的订单页面 ========== await page.goto('/#/pages/assessment/orders'); await page.waitForLoadState('networkidle'); // ========== Step 1:找到待支付订单 ========== await page.waitForSelector('.order-item', { timeout: 10000 }); const pendingOrder = page.locator('.order-item:has-text("待支付"), .order-item:has-text("待付款")').first(); await pendingOrder.click(); // ========== When:点击取消订单 ========== await page.click('.cancel-order-btn'); // 确认取消 const confirmBtn = page.locator('.confirm-cancel-btn, .van-dialog__confirm'); if (await confirmBtn.isVisible()) { await confirmBtn.click(); } // ========== Then:订单成功取消 ======== await page.waitForSelector('.cancel-success-tip, .order-closed', { timeout: 10000 }); // 订单状态应变为"已取消" const orderStatus = page.locator('.order-status'); if (await orderStatus.isVisible()) { const statusText = await orderStatus.textContent(); expect(statusText).toMatch(/已取消|已关闭/); } }); // ===== 场景6:已支付订单退款 ===== /** * 场景:家长支付后因故需要退款 * 角色:家长(发起退款)→ 系统处理 * 触发条件:订单状态为"已支付" */ test('[场景6] 已支付订单申请退款 - 期望退款成功', async ({ page }) => { // ========== Given:进入订单详情 ========== await page.goto('/#/pages/assessment/order-detail?orderNo=ASR20260628001'); await page.waitForLoadState('networkidle'); // ========== When:申请退款 ========== await page.click('.apply-refund-btn'); // 填写退款原因 const reasonInput = page.locator('.refund-reason textarea, .reason-input'); if (await reasonInput.isVisible()) { await reasonInput.fill('因计划变更,需要退款'); } // 确认提交 await page.click('.submit-refund-btn'); // ========== Then:退款申请提交成功 ======== await page.waitForSelector('.refund-submitted, .refund-success', { timeout: 10000 }); const refundTip = page.locator('.refund-submitted, .refund-success'); expect(await refundTip.isVisible()).toBeTruthy(); }); // ===== 场景7:完整测评流程(端到端)===== test('[场景7] 完整测评生命周期 - 期望全流程成功', async ({ page }) => { // ========== Step 1:申请测评 ========== await page.goto('/#/pages/assessment/apply'); await page.waitForLoadState('networkidle'); // 选择孩子 const childSelector = page.locator('.child-picker'); if (await childSelector.isVisible()) { await childSelector.click(); await page.waitForSelector('.child-option', { timeout: 5000 }); await page.click('.child-option:first-child'); } // 选择套餐并提交 await page.click('.package-option:first-child'); await page.click('.submit-btn'); // 等待订单创建 await page.waitForSelector('.order-no, .go-pay-btn', { timeout: 10000 }); // ========== Step 2:支付订单 ========== const goPayBtn = page.locator('.go-pay-btn'); if (await goPayBtn.isVisible()) { await goPayBtn.click(); // 选择微信支付并确认 const wechatPay = page.locator('.pay-method:has-text("微信")'); if (await wechatPay.isVisible()) { await wechatPay.click(); } await page.click('.confirm-pay-btn'); await page.waitForSelector('.pay-success-tip', { timeout: 15000 }); } // ========== Step 3:规划师确认预约 ========== await page.goto('/#/pages/guide/assessment/list'); await page.waitForLoadState('networkidle'); const appointmentItem = page.locator('.appointment-item').first(); if (await appointmentItem.isVisible()) { await appointmentItem.click(); await page.click('.confirm-appointment-btn'); } // ========== Step 4:规划师录入结果 ========== await page.goto('/#/pages/guide/assessment/record'); await page.waitForLoadState('networkidle'); const pendingRecord = page.locator('.pending-record-item').first(); if (await pendingRecord.isVisible()) { await pendingRecord.click(); // 填写分数 const scoreInputs = page.locator('.score-input'); for (let i = 0; i < await scoreInputs.count(); i++) { await scoreInputs.nth(i).fill('85'); } await page.click('.submit-result-btn'); await page.waitForSelector('.result-saved', { timeout: 10000 }); } // ========== Step 5:家长查看报告 ========== await page.goto('/#/pages/assessment/results'); await page.waitForLoadState('networkidle'); // 选择孩子 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'); } // 验证报告存在 await page.waitForSelector('.report-card, .result-item', { timeout: 10000 }); }); });