|
@@ -0,0 +1,575 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * ================================================================
|
|
|
|
|
+ * 场景:DAN 测评服务商体系全流程 E2E 测试
|
|
|
|
|
+ * ================================================================
|
|
|
|
|
+ * 用户故事:
|
|
|
|
|
+ * - 管理员:创建和管理服务商(测评/解读/规划)
|
|
|
|
|
+ * - 家长:购买测评服务、查看 AI 解读、获取规划方案
|
|
|
|
|
+ * - 测评服务商:提供测评服务、录入结果
|
|
|
|
|
+ * - 解读服务商:AI 解读 + 人工解读报告
|
|
|
|
|
+ * - 规划服务商:基于测评结果制定成长规划
|
|
|
|
|
+ *
|
|
|
|
|
+ * 流程步骤:
|
|
|
|
|
+ * 1. 管理员创建三类服务商并审核
|
|
|
|
|
+ * 2. 家长选择服务商并购买测评套餐
|
|
|
|
|
+ * 3. 测评服务商完成测评并录入结果
|
|
|
|
|
+ * 4. AI 自动生成解读报告
|
|
|
|
|
+ * 5. 解读服务商进行人工解读补充
|
|
|
|
|
+ * 6. 规划服务商制定成长规划方案
|
|
|
|
|
+ * 7. 家长查看完整报告和规划
|
|
|
|
|
+ *
|
|
|
|
|
+ * 关键里程碑:
|
|
|
|
|
+ * - [Milestone-1] 服务商创建并审核通过
|
|
|
|
|
+ * - [Milestone-2] 测评订单支付成功
|
|
|
|
|
+ * - [Milestone-3] 测评结果录入完成
|
|
|
|
|
+ * - [Milestone-4] AI 解读报告生成
|
|
|
|
|
+ * - [Milestone-5] 人工解读补充完成
|
|
|
|
|
+ * - [Milestone-6] 成长规划方案生成
|
|
|
|
|
+ * - [Milestone-7] 家长查看完整报告
|
|
|
|
|
+ * ================================================================
|
|
|
|
|
+ *
|
|
|
|
|
+ * 运行:npx playwright test tests/e2e/dan-assessment-vendor-flow.spec.js
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+const { test, expect } = require('@playwright/test');
|
|
|
|
|
+
|
|
|
|
|
+test.describe('【场景流程】DAN 测评服务商体系全流程', () => {
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 1:管理员创建测评服务商 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 1] 管理员创建测评服务商 - 期望创建并审核通过', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:管理员进入服务商管理页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/admin/vendor-review');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:创建测评服务商 ==========
|
|
|
|
|
+ // 方式 1:审核入驻申请
|
|
|
|
|
+ const pendingVendor = page.locator('.vendor-item:has-text("assessment_provider"), .vendor-item:has-text("测评服务")').first();
|
|
|
|
|
+
|
|
|
|
|
+ if (await pendingVendor.isVisible()) {
|
|
|
|
|
+ // 已有待审核的测评服务商
|
|
|
|
|
+ const approveBtn = pendingVendor.locator('.approve-btn, .pass-btn');
|
|
|
|
|
+ if (await approveBtn.isVisible()) {
|
|
|
|
|
+ await approveBtn.click();
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 方式 2:直接创建服务商用户
|
|
|
|
|
+ await page.goto('/#/pages/admin/user-create');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ const phoneInput = page.locator('input[name="phone"], .phone-input');
|
|
|
|
|
+ if (await phoneInput.isVisible()) {
|
|
|
|
|
+ await phoneInput.fill('139' + String(Date.now()).slice(-8));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const nameInput = page.locator('input[name="nickname"], .name-input');
|
|
|
|
|
+ if (await nameInput.isVisible()) {
|
|
|
|
|
+ await nameInput.fill('测评服务商_' + Date.now());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 选择服务商类型
|
|
|
|
|
+ const vendorTypeSelect = page.locator('select[name="vendorType"], .vendor-type-picker');
|
|
|
|
|
+ if (await vendorTypeSelect.isVisible()) {
|
|
|
|
|
+ await vendorTypeSelect.selectOption('assessment_provider');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ await page.click('.submit-btn, .save-btn');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-1 - 服务商创建成功 ========
|
|
|
|
|
+ await page.waitForSelector('.success-tip, .create-success, .vendor-approved', { timeout: 10000 });
|
|
|
|
|
+ expect(await page.locator('.success-tip, .create-success').isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 2:管理员创建解读服务商 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 2] 管理员创建解读服务商 - 期望创建并审核通过', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:管理员进入服务商管理页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/admin/vendor-review');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:创建解读服务商 ==========
|
|
|
|
|
+ await page.goto('/#/pages/admin/user-create');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ const phoneInput = page.locator('input[name="phone"], .phone-input');
|
|
|
|
|
+ if (await phoneInput.isVisible()) {
|
|
|
|
|
+ await phoneInput.fill('139' + String(Date.now()).slice(-8));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const nameInput = page.locator('input[name="nickname"], .name-input');
|
|
|
|
|
+ if (await nameInput.isVisible()) {
|
|
|
|
|
+ await nameInput.fill('解读服务商_' + Date.now());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 选择解读服务商类型
|
|
|
|
|
+ const vendorTypeSelect = page.locator('select[name="vendorType"], .vendor-type-picker');
|
|
|
|
|
+ if (await vendorTypeSelect.isVisible()) {
|
|
|
|
|
+ await vendorTypeSelect.selectOption('interpretation_provider');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ await page.click('.submit-btn, .save-btn');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-1 - 服务商创建成功 ========
|
|
|
|
|
+ await page.waitForSelector('.success-tip, .create-success', { timeout: 10000 });
|
|
|
|
|
+ expect(await page.locator('.success-tip, .create-success').isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 3:管理员创建规划服务商 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 3] 管理员创建规划服务商 - 期望创建并审核通过', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:管理员进入服务商管理页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/admin/vendor-review');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:创建规划服务商 ==========
|
|
|
|
|
+ await page.goto('/#/pages/admin/user-create');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ const phoneInput = page.locator('input[name="phone"], .phone-input');
|
|
|
|
|
+ if (await phoneInput.isVisible()) {
|
|
|
|
|
+ await phoneInput.fill('139' + String(Date.now()).slice(-8));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const nameInput = page.locator('input[name="nickname"], .name-input');
|
|
|
|
|
+ if (await nameInput.isVisible()) {
|
|
|
|
|
+ await nameInput.fill('规划服务商_' + Date.now());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 选择规划服务商类型(使用现有的 planner)
|
|
|
|
|
+ const vendorTypeSelect = page.locator('select[name="vendorType"], .vendor-type-picker');
|
|
|
|
|
+ if (await vendorTypeSelect.isVisible()) {
|
|
|
|
|
+ await vendorTypeSelect.selectOption('planner');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ await page.click('.submit-btn, .save-btn');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-1 - 服务商创建成功 ========
|
|
|
|
|
+ await page.waitForSelector('.success-tip, .create-success', { timeout: 10000 });
|
|
|
|
|
+ expect(await page.locator('.success-tip, .create-success').isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 4:家长购买测评服务 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 4] 家长购买测评服务 - 期望订单支付成功', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:家长进入测评套餐页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/assessment/apply');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 验证页面加载
|
|
|
|
|
+ await expect(page.locator('.assessment-apply-page, .package-list')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 1:选择测评套餐 ==========
|
|
|
|
|
+ const packageOption = page.locator('.package-option, .package-card').first();
|
|
|
|
|
+ if (await packageOption.isVisible()) {
|
|
|
|
|
+ await packageOption.click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 2:选择测评服务商 ==========
|
|
|
|
|
+ const providerSelect = page.locator('.provider-picker, .assessment-provider-select');
|
|
|
|
|
+ if (await providerSelect.isVisible()) {
|
|
|
|
|
+ await providerSelect.click();
|
|
|
|
|
+ await page.waitForSelector('.provider-option', { timeout: 3000 });
|
|
|
|
|
+ await page.locator('.provider-option:has-text("测评服务")').first().click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 3:选择孩子 ==========
|
|
|
|
|
+ const childPicker = page.locator('.child-picker');
|
|
|
|
|
+ if (await childPicker.isVisible()) {
|
|
|
|
|
+ await childPicker.click();
|
|
|
|
|
+ await page.waitForSelector('.child-option', { timeout: 3000 });
|
|
|
|
|
+ await page.locator('.child-option').first().click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 4:选择解读服务商(可选)==========
|
|
|
|
|
+ const interpretationSelect = page.locator('.interpretation-provider-select');
|
|
|
|
|
+ if (await interpretationSelect.isVisible()) {
|
|
|
|
|
+ await interpretationSelect.click();
|
|
|
|
|
+ await page.waitForSelector('.provider-option', { timeout: 3000 });
|
|
|
|
|
+ await page.locator('.provider-option:has-text("解读服务")').first().click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:提交订单 ==========
|
|
|
|
|
+ await page.click('.submit-btn, .create-order-btn');
|
|
|
|
|
+
|
|
|
|
|
+ // 等待订单创建
|
|
|
|
|
+ await page.waitForSelector('.order-confirm-modal, .order-success-tip', { timeout: 10000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-2 - 订单创建成功 ========
|
|
|
|
|
+ const orderNoElement = page.locator('.order-no, .order-number');
|
|
|
|
|
+ let orderNo = '';
|
|
|
|
|
+ if (await orderNoElement.isVisible()) {
|
|
|
|
|
+ orderNo = await orderNoElement.textContent();
|
|
|
|
|
+ expect(orderNo).toBeTruthy();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 5:支付订单 ==========
|
|
|
|
|
+ const payBtn = page.locator('.pay-btn, .go-pay-btn');
|
|
|
|
|
+ if (await payBtn.isVisible()) {
|
|
|
|
|
+ await payBtn.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, .payment-success', { timeout: 15000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:支付成功 ========
|
|
|
|
|
+ const paySuccessTip = page.locator('.pay-success-tip, .payment-success');
|
|
|
|
|
+ expect(await paySuccessTip.isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 5:测评服务商录入测评结果 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 5] 测评服务商录入测评结果 - 期望结果保存成功', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:测评服务商进入测评结果录入页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/guide/assessment/record');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 验证页面加载
|
|
|
|
|
+ await expect(page.locator('.assessment-record-page, .pending-records')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 1:选择待录入的预约 ==========
|
|
|
|
|
+ const pendingRecord = page.locator('.pending-record-item, .appointment-item').first();
|
|
|
|
|
+ if (await pendingRecord.isVisible()) {
|
|
|
|
|
+ await pendingRecord.click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 等待录入表单加载
|
|
|
|
|
+ await page.waitForSelector('.record-form, .result-input-form', { timeout: 5000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 2:填写测评维度分数 ==========
|
|
|
|
|
+ // 注意力分数
|
|
|
|
|
+ const attentionInput = page.locator('input[name="attentionScore"], .attention-input');
|
|
|
|
|
+ if (await attentionInput.isVisible()) {
|
|
|
|
|
+ await attentionInput.fill('85');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 专注力分数
|
|
|
|
|
+ const focusInput = page.locator('input[name="focusScore"], .focus-input');
|
|
|
|
|
+ if (await focusInput.isVisible()) {
|
|
|
|
|
+ await focusInput.fill('88');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 记忆力分数
|
|
|
|
|
+ const memoryInput = page.locator('input[name="memoryScore"], .memory-input');
|
|
|
|
|
+ if (await memoryInput.isVisible()) {
|
|
|
|
|
+ await memoryInput.fill('82');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 逻辑思维分数
|
|
|
|
|
+ const logicInput = page.locator('input[name="logicScore"], .logic-input');
|
|
|
|
|
+ if (await logicInput.isVisible()) {
|
|
|
|
|
+ await logicInput.fill('90');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 知觉分数
|
|
|
|
|
+ const perceptionInput = page.locator('input[name="perceptionScore"], .perception-input');
|
|
|
|
|
+ if (await perceptionInput.isVisible()) {
|
|
|
|
|
+ await perceptionInput.fill('87');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 空间分数
|
|
|
|
|
+ const spatialInput = page.locator('input[name="spatialScore"], .spatial-input');
|
|
|
|
|
+ if (await spatialInput.isVisible()) {
|
|
|
|
|
+ await spatialInput.fill('84');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理速度分数
|
|
|
|
|
+ const speedInput = page.locator('input[name="processingSpeedScore"], .speed-input');
|
|
|
|
|
+ if (await speedInput.isVisible()) {
|
|
|
|
|
+ await speedInput.fill('86');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 3:填写分析评语 ==========
|
|
|
|
|
+ const analysisTextarea = page.locator('textarea[name="analysisReport"], .analysis-textarea');
|
|
|
|
|
+ if (await analysisTextarea.isVisible()) {
|
|
|
|
|
+ await analysisTextarea.fill('孩子在注意力和逻辑思维方面表现优秀,专注力良好。建议加强记忆力训练,提升空间感知能力。');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 4:填写成长建议 ==========
|
|
|
|
|
+ const suggestionsTextarea = page.locator('textarea[name="growthSuggestions"], .suggestions-textarea');
|
|
|
|
|
+ if (await suggestionsTextarea.isVisible()) {
|
|
|
|
|
+ await suggestionsTextarea.fill('1. 每日专注力训练 15 分钟\n2. 记忆力游戏(如卡片配对)\n3. 空间拼图练习\n4. 逻辑思维题目训练');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:提交测评结果 ==========
|
|
|
|
|
+ await page.click('.submit-btn, .submit-result-btn');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-3 - 测评结果录入成功 ========
|
|
|
|
|
+ await page.waitForSelector('.success-tip, .result-saved, .submit-success', { timeout: 10000 });
|
|
|
|
|
+ expect(await page.locator('.success-tip, .result-saved').isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 6:AI 自动生成解读报告 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 6] AI 自动生成解读报告 - 期望报告生成成功', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:等待 AI 解读报告生成 ==========
|
|
|
|
|
+ // AI 解读通常是自动触发的,在测评结果提交后系统自动生成
|
|
|
|
|
+ // 这里我们验证 AI 解读报告是否已生成
|
|
|
|
|
+
|
|
|
|
|
+ await page.goto('/#/pages/assessment/results');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:查看 AI 解读报告 ==========
|
|
|
|
|
+ await page.waitForSelector('.ai-report-card, .ai-interpretation, .auto-report', { timeout: 15000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-4 - AI 解读报告生成 ========
|
|
|
|
|
+ const aiReportCard = page.locator('.ai-report-card, .ai-interpretation');
|
|
|
|
|
+ expect(await aiReportCard.isVisible()).toBeTruthy();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证报告包含关键内容
|
|
|
|
|
+ const reportContent = page.locator('.report-content, .interpretation-text');
|
|
|
|
|
+ if (await reportContent.isVisible()) {
|
|
|
|
|
+ const contentText = await reportContent.textContent();
|
|
|
|
|
+ expect(contentText.length).toBeGreaterThan(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证包含维度分析
|
|
|
|
|
+ const dimensionAnalysis = page.locator('.dimension-analysis, .score-analysis');
|
|
|
|
|
+ if (await dimensionAnalysis.isVisible()) {
|
|
|
|
|
+ const analysisText = await dimensionAnalysis.textContent();
|
|
|
|
|
+ expect(analysisText).toContain('注意力') || expect(analysisText).toContain('专注力');
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 7:解读服务商进行人工解读补充 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 7] 解读服务商人工解读补充 - 期望补充完成', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:解读服务商进入人工解读页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/interpretation/manual-review');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 验证页面加载
|
|
|
|
|
+ await expect(page.locator('.manual-review-page, .pending-interpretations')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 1:选择待解读的报告 ==========
|
|
|
|
|
+ const pendingReport = page.locator('.pending-report-item, .interpretation-item').first();
|
|
|
|
|
+ if (await pendingReport.isVisible()) {
|
|
|
|
|
+ await pendingReport.click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 等待解读表单加载
|
|
|
|
|
+ await page.waitForSelector('.interpretation-form, .manual-review-form', { timeout: 5000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 2:查看 AI 解读报告 ==========
|
|
|
|
|
+ const aiReportSection = page.locator('.ai-report-section, .ai-interpretation-preview');
|
|
|
|
|
+ if (await aiReportSection.isVisible()) {
|
|
|
|
|
+ // AI 报告已加载
|
|
|
|
|
+ expect(await aiReportSection.isVisible()).toBeTruthy();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 3:补充人工解读 ==========
|
|
|
|
|
+ const manualAnalysisTextarea = page.locator('textarea[name="manualAnalysis"], .manual-analysis-textarea');
|
|
|
|
|
+ if (await manualAnalysisTextarea.isVisible()) {
|
|
|
|
|
+ await manualAnalysisTextarea.fill('补充解读:孩子在认知发展方面整体表现良好,特别是在逻辑思维方面有明显优势。建议家长关注孩子的注意力训练,可以通过游戏化方式提升专注力持续时间。');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 4:补充个性化建议 ==========
|
|
|
|
|
+ const personalizedSuggestions = page.locator('textarea[name="personalizedSuggestions"], .suggestions-textarea');
|
|
|
|
|
+ if (await personalizedSuggestions.isVisible()) {
|
|
|
|
|
+ await personalizedSuggestionsSuggestions.fill('1. 建议每周进行 3 次专注力训练\n2. 推荐参加逻辑思维兴趣班\n3. 家长陪伴阅读提升理解能力\n4. 定期复查跟踪发展状况');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:提交人工解读 ==========
|
|
|
|
|
+ await page.click('.submit-btn, .submit-interpretation-btn');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-5 - 人工解读补充完成 ========
|
|
|
|
|
+ await page.waitForSelector('.success-tip, .interpretation-submitted, .submit-success', { timeout: 10000 });
|
|
|
|
|
+ expect(await page.locator('.success-tip, .interpretation-submitted').isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 8:规划服务商制定成长规划方案 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 8] 规划服务商制定成长规划 - 期望规划方案生成', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:规划服务商进入规划制定页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/planner/growth-plan/create');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 验证页面加载
|
|
|
|
|
+ await expect(page.locator('.growth-plan-page, .plan-form')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 1:选择孩子 ==========
|
|
|
|
|
+ const childPicker = page.locator('.child-picker');
|
|
|
|
|
+ if (await childPicker.isVisible()) {
|
|
|
|
|
+ await childPicker.click();
|
|
|
|
|
+ await page.waitForSelector('.child-option', { timeout: 3000 });
|
|
|
|
|
+ await page.locator('.child-option').first().click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 2:查看测评结果 ==========
|
|
|
|
|
+ const assessmentResultSection = page.locator('.assessment-result-section, .result-preview');
|
|
|
|
|
+ if (await assessmentResultSection.isVisible()) {
|
|
|
|
|
+ // 测评结果已加载
|
|
|
|
|
+ expect(await assessmentResultSection.isVisible()).toBeTruthy();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 3:制定短期目标(1-3 个月)==========
|
|
|
|
|
+ const shortTermGoalInput = page.locator('textarea[name="shortTermGoal"], .short-term-input');
|
|
|
|
|
+ if (await shortTermGoalInput.isVisible()) {
|
|
|
|
|
+ await shortTermGoalInput.fill('提升专注力持续时间至 20 分钟,增强记忆力训练效果');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 4:制定中期目标(3-6 个月)==========
|
|
|
|
|
+ const midTermGoalInput = page.locator('textarea[name="midTermGoal"], .mid-term-input');
|
|
|
|
|
+ if (await midTermGoalInput.isVisible()) {
|
|
|
|
|
+ await midTermGoalInput.fill('全面提升五维能力,特别是逻辑思维和空间感知能力');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 5:制定长期目标(6-12 个月)==========
|
|
|
|
|
+ const longTermGoalInput = page.locator('textarea[name="longTermGoal"], .long-term-input');
|
|
|
|
|
+ if (await longTermGoalInput.isVisible()) {
|
|
|
|
|
+ await longTermGoalInput.fill('建立完整的学习能力体系,为幼小衔接做好准备');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 6:制定训练计划 ==========
|
|
|
|
|
+ const trainingPlanTextarea = page.locator('textarea[name="trainingPlan"], .training-plan-textarea');
|
|
|
|
|
+ if (await trainingPlanTextarea.isVisible()) {
|
|
|
|
|
+ await trainingPlanTextarea.fill(`
|
|
|
|
|
+【每日训练】
|
|
|
|
|
+- 专注力训练:舒尔特方格 10 分钟
|
|
|
|
|
+- 记忆力训练:卡片配对游戏 15 分钟
|
|
|
|
|
+
|
|
|
|
|
+【每周训练】
|
|
|
|
|
+- 逻辑思维:数学思维题 3 次/周
|
|
|
|
|
+- 空间感知:拼图游戏 2 次/周
|
|
|
|
|
+
|
|
|
|
|
+【每月评估】
|
|
|
|
|
+- 月度能力测评
|
|
|
|
|
+- 训练效果跟踪
|
|
|
|
|
+- 方案调整优化
|
|
|
|
|
+ `);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 7:推荐配套服务 ==========
|
|
|
|
|
+ const serviceRecommendation = page.locator('.service-recommendation, .service-checkbox');
|
|
|
|
|
+ if (await serviceRecommendation.isVisible()) {
|
|
|
|
|
+ // 选择推荐的服务
|
|
|
|
|
+ await page.locator('.service-checkbox:has-text("专注力训练")').first().click();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:提交成长规划方案 ==========
|
|
|
|
|
+ await page.click('.submit-btn, .create-plan-btn');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-6 - 成长规划方案生成 ========
|
|
|
|
|
+ await page.waitForSelector('.success-tip, .plan-created, .submit-success', { timeout: 10000 });
|
|
|
|
|
+ expect(await page.locator('.success-tip, .plan-created').isVisible()).toBeTruthy();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 9:家长查看完整报告和规划 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 9] 家长查看完整报告和规划 - 期望查看成功', async ({ page }) => {
|
|
|
|
|
+ // ========== Given:家长进入报告查看页 ==========
|
|
|
|
|
+ await page.goto('/#/pages/assessment/results');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // ========== When:查看完整报告 ==========
|
|
|
|
|
+ // 验证测评结果
|
|
|
|
|
+ await page.waitForSelector('.assessment-result-card, .result-summary', { timeout: 10000 });
|
|
|
|
|
+ const resultCard = page.locator('.assessment-result-card, .result-summary');
|
|
|
|
|
+ expect(await resultCard.isVisible()).toBeTruthy();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证 AI 解读报告
|
|
|
|
|
+ const aiReportSection = page.locator('.ai-report-section, .ai-interpretation');
|
|
|
|
|
+ expect(await aiReportSection.isVisible()).toBeTruthy();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证人工解读报告
|
|
|
|
|
+ const manualReportSection = page.locator('.manual-interpretation-section, .manual-interpretation');
|
|
|
|
|
+ if (await manualReportSection.isVisible()) {
|
|
|
|
|
+ expect(await manualReportSection.isVisible()).toBeTruthy();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证成长规划方案
|
|
|
|
|
+ const growthPlanSection = page.locator('.growth-plan-section, .growth-plan');
|
|
|
|
|
+ if (await growthPlanSection.isVisible()) {
|
|
|
|
|
+ expect(await growthPlanSection.isVisible()).toBeTruthy();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:Milestone-7 - 完整报告查看成功 ========
|
|
|
|
|
+ // 验证报告包含完整内容
|
|
|
|
|
+ const fullReportContent = page.locator('.full-report, .complete-report');
|
|
|
|
|
+ if (await fullReportContent.isVisible()) {
|
|
|
|
|
+ const contentText = await fullReportContent.textContent();
|
|
|
|
|
+ expect(contentText.length).toBeGreaterThan(100);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证包含所有关键部分
|
|
|
|
|
+ const sections = page.locator('.report-section, .report-part');
|
|
|
|
|
+ const sectionCount = await sections.count();
|
|
|
|
|
+ expect(sectionCount).toBeGreaterThanOrEqual(3); // 至少包含:测评结果、AI 解读、规划方案
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ===== 场景 10:完整流程端到端测试 =====
|
|
|
|
|
+
|
|
|
|
|
+ test('[场景 10] DAN 测评服务商完整流程 - 期望全流程成功', async ({ page }) => {
|
|
|
|
|
+ // ========== Step 1:管理员创建服务商 ==========
|
|
|
|
|
+ await page.goto('/#/pages/admin/vendor-review');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 验证服务商管理页面加载
|
|
|
|
|
+ expect(await page.locator('.vendor-review-page').isVisible()).toBeTruthy();
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 2:家长购买测评 ==========
|
|
|
|
|
+ await page.goto('/#/pages/assessment/apply');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 选择套餐并提交
|
|
|
|
|
+ const packageOption = page.locator('.package-option').first();
|
|
|
|
|
+ if (await packageOption.isVisible()) {
|
|
|
|
|
+ await packageOption.click();
|
|
|
|
|
+ await page.click('.submit-btn');
|
|
|
|
|
+ await page.waitForSelector('.order-confirm-modal', { timeout: 10000 });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 3:测评服务商录入结果 ==========
|
|
|
|
|
+ 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();
|
|
|
|
|
+ await page.waitForSelector('.record-form', { timeout: 5000 });
|
|
|
|
|
+
|
|
|
|
|
+ // 填写分数
|
|
|
|
|
+ const scoreInputs = page.locator('.score-input');
|
|
|
|
|
+ const count = await scoreInputs.count();
|
|
|
|
|
+ for (let i = 0; i < count; i++) {
|
|
|
|
|
+ await scoreInputs.nth(i).fill('85');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ await page.click('.submit-result-btn');
|
|
|
|
|
+ await page.waitForSelector('.result-saved', { timeout: 10000 });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Step 4:查看完整报告 ==========
|
|
|
|
|
+ await page.goto('/#/pages/assessment/results');
|
|
|
|
|
+ await page.waitForLoadState('networkidle');
|
|
|
|
|
+
|
|
|
|
|
+ // 验证报告存在
|
|
|
|
|
+ await page.waitForSelector('.result-card, .report-summary', { timeout: 10000 });
|
|
|
|
|
+ const resultCard = page.locator('.result-card, .report-summary');
|
|
|
|
|
+ expect(await resultCard.isVisible()).toBeTruthy();
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Then:全流程成功 ========
|
|
|
|
|
+ // 验证所有里程碑都已达成
|
|
|
|
|
+ const milestones = [
|
|
|
|
|
+ page.locator('.assessment-result-card'),
|
|
|
|
|
+ page.locator('.ai-interpretation'),
|
|
|
|
|
+ page.locator('.growth-plan')
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ for (const milestone of milestones) {
|
|
|
|
|
+ if (await milestone.isVisible()) {
|
|
|
|
|
+ expect(await milestone.isVisible()).toBeTruthy();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+});
|