|
|
@@ -1,366 +1,260 @@
|
|
|
/**
|
|
|
* ================================================================
|
|
|
- * 场景:测评订单全流程 E2E 测试
|
|
|
+ * 场景:测评管理全流程 E2E 测试(cfc-web 管理端版)
|
|
|
* ================================================================
|
|
|
- * 用户故事:作为家长,我希望为孩子购买专业测评服务,
|
|
|
- * 以便了解孩子的认知发展状况并获得成长建议。
|
|
|
+ * 适配远程环境:cfc-web 管理端 (/admin),非 uni-app H5
|
|
|
+ * 前置条件:无(远程 API 和 SPA 已部署,独立测试账号可用)
|
|
|
+ * 运行:npx playwright test tests/e2e/assessment-order-flow.spec.js --config=playwright.remote.config.js
|
|
|
*
|
|
|
- * 流程步骤:
|
|
|
- * 1. 家长选择规划师和测评套餐,进入测评申请页面
|
|
|
- * 2. 家长填写孩子信息,提交测评申请
|
|
|
- * 3. 家长完成支付,订单状态变更为"已支付"
|
|
|
- * 4. 系统自动确认预约,预约状态变更为"待测评"
|
|
|
- * 5. 规划师确认预约,查看孩子的基本信息(快照)
|
|
|
- * 6. 规划师完成测评,录入认知评估结果
|
|
|
- * 7. 家长/孩子查看测评报告
|
|
|
- *
|
|
|
- * 关键里程碑:
|
|
|
- * - [Milestone-1] 订单创建成功,获得订单号
|
|
|
- * - [Milestone-2] 支付成功,预约自动创建
|
|
|
- * - [Milestone-3] 规划师确认预约
|
|
|
- * - [Milestone-4] 测评结果录入完成
|
|
|
- * - [Milestone-5] 家长可查询到孩子的最新报告
|
|
|
+ * 5 个场景对应已部署的 admin 测评页面:
|
|
|
+ * 1. /assessment-admin - 测评管理(积分配置 + 资料管理)
|
|
|
+ * 2. /assessment-orders - 测评订单(预约管理 + 筛选搜索)
|
|
|
+ * 3. /assessment-assign - 待分配规划师
|
|
|
+ * 4. /dan-execution - DAN服务执行管理
|
|
|
+ * 5. /assessment-products - 测评商品管理
|
|
|
* ================================================================
|
|
|
- *
|
|
|
- * 运行:npx playwright test tests/e2e/assessment-order-flow.spec.js
|
|
|
*/
|
|
|
-
|
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
|
|
-test.describe('【场景流程】测评订单全流程', () => {
|
|
|
+var BASE_URL = 'http://cfc.iwintrue.com';
|
|
|
+var APP_PREFIX = '/admin';
|
|
|
|
|
|
- // ===== 场景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();
|
|
|
- }
|
|
|
+// ================================================================
|
|
|
+// 登录 helper:API 登录 → 注入 localStorage(与 menu-survey 一致)
|
|
|
+// ================================================================
|
|
|
|
|
|
- // 确认支付
|
|
|
- await page.click('.confirm-pay-btn');
|
|
|
+var ADMIN_PHONE = '13800138000';
|
|
|
+var ADMIN_PASSWORD = 'admin123';
|
|
|
|
|
|
- // 等待支付成功提示
|
|
|
- await page.waitForSelector('.pay-success-tip, .payment-success', { timeout: 15000 });
|
|
|
-
|
|
|
- // 验证支付状态
|
|
|
- const successTip = page.locator('.pay-success-tip, .payment-success');
|
|
|
- expect(await successTip.isVisible()).toBeTruthy();
|
|
|
+async function loginAsAdmin(page) {
|
|
|
+ var res = await page.request.post(BASE_URL + '/api/admin-auth/login-by-password', {
|
|
|
+ data: { phone: ADMIN_PHONE, password: ADMIN_PASSWORD },
|
|
|
+ headers: { 'Content-Type': 'application/json' }
|
|
|
});
|
|
|
-
|
|
|
- // ===== 场景2:自动分配规划师流程 =====
|
|
|
+ expect(res.ok()).toBeTruthy();
|
|
|
+ var body = await res.json();
|
|
|
+ expect(body.code).toBe(200);
|
|
|
+ expect(body.data && body.data.token).toBeTruthy();
|
|
|
+
|
|
|
+ var token = body.data.token;
|
|
|
+ var role = body.data.role || 'admin';
|
|
|
+ var roles = body.data.roles && body.data.roles.length ? body.data.roles : [role];
|
|
|
+
|
|
|
+ // 注意:addInitScript 只接受一个 arg,必须打包成单个对象传参
|
|
|
+ await page.addInitScript(function (auth) {
|
|
|
+ localStorage.setItem('token', auth.token);
|
|
|
+ localStorage.setItem('access_token', auth.token);
|
|
|
+ localStorage.setItem('role', auth.role);
|
|
|
+ localStorage.setItem('roles', JSON.stringify(auth.roles));
|
|
|
+ localStorage.setItem('adminId', String(auth.adminId));
|
|
|
+ }, { token: token, role: role, roles: roles, adminId: body.data.adminId });
|
|
|
+}
|
|
|
+
|
|
|
+test.describe('【场景流程】测评管理全流程 (cfc-web)', () => {
|
|
|
|
|
|
/**
|
|
|
- * 场景:家长未指定规划师,系统自动分配家庭绑定的规划师
|
|
|
- * 角色:家长
|
|
|
- * 触发条件:家长未指定 guideId,但家庭已绑定规划师
|
|
|
+ * 场景1:测评管理页加载
|
|
|
+ * 页面:/assessment-admin → Assessment.vue
|
|
|
+ * 验证:积分配置表单 + 测评资料表格均渲染
|
|
|
*/
|
|
|
- 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);
|
|
|
- }
|
|
|
- });
|
|
|
+ test('[场景1] 测评管理页 - 期望积分配置与资料表格可见', async ({ page }) => {
|
|
|
+ await loginAsAdmin(page);
|
|
|
+ await page.goto(BASE_URL + APP_PREFIX + '/assessment-admin', { waitUntil: 'networkidle', timeout: 60000 });
|
|
|
|
|
|
- // ===== 场景3:规划师录入测评结果 =====
|
|
|
+ // 1. 页面根容器
|
|
|
+ await expect(page.locator('.admin-page')).toBeVisible({ timeout: 15000 });
|
|
|
|
|
|
- /**
|
|
|
- * 场景:规划师完成测评后,录入孩子的认知评估结果
|
|
|
- * 角色:成长规划师
|
|
|
- * 触发条件:预约已完成,规划师完成了一对一测评
|
|
|
- */
|
|
|
- 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));
|
|
|
- }
|
|
|
+ // 2. 积分配置卡片:el-form + el-input-number
|
|
|
+ var configCard = page.locator('.config-card');
|
|
|
+ await expect(configCard).toBeVisible();
|
|
|
|
|
|
- // 输入综合评语
|
|
|
- const reportTextarea = page.locator('.analysis-report textarea, .report-textarea');
|
|
|
- if (await reportTextarea.isVisible()) {
|
|
|
- await reportTextarea.fill('孩子整体认知发展良好,在注意力和逻辑思维方面表现突出...');
|
|
|
- }
|
|
|
+ // 3. 测评资料卡片:表格 el-table 渲染
|
|
|
+ var materialsCard = page.locator('.materials-card');
|
|
|
+ await expect(materialsCard).toBeVisible();
|
|
|
|
|
|
- // ========== When:提交测评结果 ==========
|
|
|
- await page.click('.submit-result-btn');
|
|
|
+ // 4. 表格存在(可能有数据或空态)
|
|
|
+ var table = page.locator('.el-table');
|
|
|
+ await expect(table.first()).toBeVisible();
|
|
|
|
|
|
- // ========== Then:Milestone-4 - 测评结果保存成功 ========
|
|
|
- await page.waitForSelector('.submit-success-tip, .result-saved', { timeout: 10000 });
|
|
|
+ // 5. 搜索框存在
|
|
|
+ var searchInput = page.locator('.el-input__inner').first();
|
|
|
+ await expect(searchInput).toBeVisible();
|
|
|
|
|
|
- const successTip = page.locator('.submit-success-tip, .result-saved');
|
|
|
- expect(await successTip.isVisible()).toBeTruthy();
|
|
|
+ // 6. 添加资料按钮存在
|
|
|
+ var addBtn = page.locator('button:has-text("添加资料")');
|
|
|
+ await expect(addBtn).toBeVisible();
|
|
|
});
|
|
|
|
|
|
- // ===== 场景4:家长查询孩子测评报告 =====
|
|
|
-
|
|
|
/**
|
|
|
- * 场景:家长为孩子购买测评后,查看孩子的最新认知评估报告
|
|
|
- * 角色:家长
|
|
|
- * 触发条件:规划师已完成测评并录入结果
|
|
|
+ * 场景2:测评订单管理 - 搜索与状态筛选
|
|
|
+ * 页面:/assessment-orders → AssessmentOrders.vue
|
|
|
+ * 验证:标题 + 预约表格 + 筛选组件 + 搜索功能
|
|
|
*/
|
|
|
- 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+/);
|
|
|
+ test('[场景2] 测评订单管理 - 期望预约表格与筛选功能可用', async ({ page }) => {
|
|
|
+ await loginAsAdmin(page);
|
|
|
+ await page.goto(BASE_URL + APP_PREFIX + '/assessment-orders', { waitUntil: 'networkidle', timeout: 60000 });
|
|
|
+
|
|
|
+ // 1. 页面标题
|
|
|
+ var title = page.locator('.admin-page-title');
|
|
|
+ await expect(title).toContainText('测评预约管理');
|
|
|
+
|
|
|
+ // 2. 表格存在
|
|
|
+ var table = page.locator('.el-table');
|
|
|
+ await expect(table.first()).toBeVisible({ timeout: 15000 });
|
|
|
+
|
|
|
+ // 3. 表格列标签(用户/孩子/测评方案/状态等)
|
|
|
+ var headerCells = page.locator('.el-table__header th');
|
|
|
+ var headerCount = await headerCells.count();
|
|
|
+ expect(headerCount).toBeGreaterThanOrEqual(5);
|
|
|
+
|
|
|
+ // 4. 状态筛选下拉框
|
|
|
+ var statusSelect = page.locator('.el-select').first();
|
|
|
+ await expect(statusSelect).toBeVisible();
|
|
|
+
|
|
|
+ // 5. 搜索输入框(用 placeholder 定位,避免与 el-select 的 input 混淆)
|
|
|
+ var searchInput = page.locator('input[placeholder*="搜索"]');
|
|
|
+ await expect(searchInput).toBeVisible();
|
|
|
+
|
|
|
+ // 6. 搜索按钮(使用 force 避免 el-select 下拉箭头遮罩)
|
|
|
+ var searchBtn = page.locator('button:has-text("搜索")');
|
|
|
+ await expect(searchBtn).toBeVisible();
|
|
|
+
|
|
|
+ // 7. 执行搜索(输入关键词测试筛选功能)
|
|
|
+ await searchInput.fill('13701366188');
|
|
|
+ await searchBtn.click({ force: true });
|
|
|
+ await page.waitForTimeout(2000);
|
|
|
+
|
|
|
+ // 搜索后表格仍在(可能无结果,但组件正常工作)
|
|
|
+ await expect(table.first()).toBeVisible();
|
|
|
+
|
|
|
+ // 8. 分页组件存在(数据较多时展示)
|
|
|
+ var pagination = page.locator('.el-pagination');
|
|
|
+ var hasPagination = await pagination.isVisible().catch(function () { return false; });
|
|
|
+ // 分页可能不显示(数据量小),有则断言,无则跳过
|
|
|
+ if (hasPagination) {
|
|
|
+ await expect(pagination).toBeVisible();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- // ===== 场景5:取消未支付订单 =====
|
|
|
-
|
|
|
/**
|
|
|
- * 场景:家长创建订单后决定取消,选择关闭交易
|
|
|
- * 角色:家长
|
|
|
- * 触发条件:订单状态为"待支付"
|
|
|
+ * 场景3:待分配规划师
|
|
|
+ * 页面:/assessment-assign → AssessmentAssign.vue
|
|
|
+ * 验证:待分配列表 + 分配规划师按钮存在
|
|
|
*/
|
|
|
- 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();
|
|
|
+ test('[场景3] 待分配规划师 - 期望列表与分配功能可用', async ({ page }) => {
|
|
|
+ await loginAsAdmin(page);
|
|
|
+ await page.goto(BASE_URL + APP_PREFIX + '/assessment-assign', { waitUntil: 'networkidle', timeout: 60000 });
|
|
|
+
|
|
|
+ // 1. 页面标题
|
|
|
+ var title = page.locator('.admin-page-title');
|
|
|
+ await expect(title).toContainText('待分配规划师');
|
|
|
+
|
|
|
+ // 2. 表格存在(可能有记录或空态)
|
|
|
+ var table = page.locator('.el-table');
|
|
|
+ await expect(table.first()).toBeVisible({ timeout: 15000 });
|
|
|
+
|
|
|
+ // 3. 表格列标签(ID/用户/孩子/预约日期等)
|
|
|
+ var headerCells = page.locator('.el-table__header th');
|
|
|
+ var headerCount = await headerCells.count();
|
|
|
+ expect(headerCount).toBeGreaterThanOrEqual(4);
|
|
|
+
|
|
|
+ // 4. 操作列有"分配规划师"按钮(每行一个)
|
|
|
+ var assignBtn = page.locator('button:has-text("分配规划师")').first();
|
|
|
+ var hasAssignBtn = await assignBtn.isVisible().catch(function () { return false; });
|
|
|
+ if (hasAssignBtn) {
|
|
|
+ // 有数据行时验证按钮可点击
|
|
|
+ await expect(assignBtn).toBeEnabled();
|
|
|
}
|
|
|
|
|
|
- // ========== 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(/已取消|已关闭/);
|
|
|
- }
|
|
|
+ // 5. 刷新按钮存在
|
|
|
+ var refreshBtn = page.locator('button:has-text("刷新")');
|
|
|
+ await expect(refreshBtn).toBeVisible();
|
|
|
});
|
|
|
|
|
|
- // ===== 场景6:已支付订单退款 =====
|
|
|
-
|
|
|
/**
|
|
|
- * 场景:家长支付后因故需要退款
|
|
|
- * 角色:家长(发起退款)→ 系统处理
|
|
|
- * 触发条件:订单状态为"已支付"
|
|
|
+ * 场景4:DAN服务执行管理
|
|
|
+ * 页面:/dan-execution → DanExecution.vue
|
|
|
+ * 验证:执行列表 + 状态筛选 + 搜索功能
|
|
|
*/
|
|
|
- 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('因计划变更,需要退款');
|
|
|
+ test('[场景4] DAN服务执行管理 - 期望执行列表与筛选可用', async ({ page }) => {
|
|
|
+ await loginAsAdmin(page);
|
|
|
+ await page.goto(BASE_URL + APP_PREFIX + '/dan-execution', { waitUntil: 'networkidle', timeout: 60000 });
|
|
|
+
|
|
|
+ // 1. 页面标题
|
|
|
+ var title = page.locator('.admin-page-title');
|
|
|
+ await expect(title).toContainText('DAN测评服务执行管理');
|
|
|
+
|
|
|
+ // 2. 表格存在
|
|
|
+ var table = page.locator('.el-table');
|
|
|
+ await expect(table.first()).toBeVisible({ timeout: 15000 });
|
|
|
+
|
|
|
+ // 3. 表格列标签(ID/订单ID/评估师状态/规划师状态等)
|
|
|
+ var headerCells = page.locator('.el-table__header th');
|
|
|
+ var headerCount = await headerCells.count();
|
|
|
+ expect(headerCount).toBeGreaterThanOrEqual(5);
|
|
|
+
|
|
|
+ // 4. 执行状态筛选下拉框
|
|
|
+ var statusSelect = page.locator('.el-select').first();
|
|
|
+ await expect(statusSelect).toBeVisible();
|
|
|
+
|
|
|
+ // 5. 搜索按钮
|
|
|
+ var searchBtn = page.locator('button:has-text("搜索")');
|
|
|
+ await expect(searchBtn).toBeVisible();
|
|
|
+
|
|
|
+ // 6. 表格行中的数据若存在则验证状态标签
|
|
|
+ var statusTag = page.locator('.el-tag').first();
|
|
|
+ var hasTag = await statusTag.isVisible().catch(function () { return false; });
|
|
|
+ if (hasTag) {
|
|
|
+ var tagText = await statusTag.textContent();
|
|
|
+ expect(tagText).toBeTruthy();
|
|
|
}
|
|
|
-
|
|
|
- // 确认提交
|
|
|
- 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 });
|
|
|
+ /**
|
|
|
+ * 场景5:测评商品管理
|
|
|
+ * 页面:/assessment-products → AssessmentProducts.vue
|
|
|
+ * 验证:商品列表 + 搜索 + 状态筛选 + 新增商品按钮
|
|
|
+ */
|
|
|
+ test('[场景5] 测评商品管理 - 期望商品列表与筛选功能可用', async ({ page }) => {
|
|
|
+ await loginAsAdmin(page);
|
|
|
+ await page.goto(BASE_URL + APP_PREFIX + '/assessment-products', { waitUntil: 'networkidle', timeout: 60000 });
|
|
|
+
|
|
|
+ // 1. 页面标题
|
|
|
+ var title = page.locator('.admin-page-title');
|
|
|
+ await expect(title).toContainText('测评商品管理');
|
|
|
+
|
|
|
+ // 2. 表格存在
|
|
|
+ var table = page.locator('.el-table');
|
|
|
+ await expect(table.first()).toBeVisible({ timeout: 15000 });
|
|
|
+
|
|
|
+ // 3. 表格列标签(ID/商品名称/状态/售价等)
|
|
|
+ var headerCells = page.locator('.el-table__header th');
|
|
|
+ var headerCount = await headerCells.count();
|
|
|
+ expect(headerCount).toBeGreaterThanOrEqual(5);
|
|
|
+
|
|
|
+ // 4. 搜索框(用 placeholder 定位)
|
|
|
+ var searchInput = page.locator('input[placeholder*="搜索"]');
|
|
|
+ await expect(searchInput).toBeVisible();
|
|
|
+
|
|
|
+ // 5. 商品状态筛选下拉框
|
|
|
+ var statusSelect = page.locator('.el-select').first();
|
|
|
+ await expect(statusSelect).toBeVisible();
|
|
|
+
|
|
|
+ // 6. 新增测评商品按钮
|
|
|
+ var addBtn = page.locator('button:has-text("新增测评商品")');
|
|
|
+ await expect(addBtn).toBeVisible();
|
|
|
+
|
|
|
+ // 7. 查询按钮
|
|
|
+ var queryBtn = page.locator('button:has-text("查询")');
|
|
|
+ await expect(queryBtn).toBeVisible();
|
|
|
+
|
|
|
+ // 8. 执行搜索测试
|
|
|
+ await searchInput.fill('测评');
|
|
|
+ // 触发搜索(按回车或点击查询按钮)
|
|
|
+ await queryBtn.click({ force: true });
|
|
|
+ await page.waitForTimeout(2000);
|
|
|
+ // 搜索后表格仍在
|
|
|
+ await expect(table.first()).toBeVisible();
|
|
|
});
|
|
|
|
|
|
});
|