- 修改后端目录从 reading-platform-backend 改为 reading-platform-java - 修改后端端口从 3000 改为 8080 - 修改启动命令从 npm run start:dev 改为 mvn spring-boot:run - 添加 JAVA_HOME 自动检测和设置(默认使用 /f/Java/jdk-17) - 修改日志文件从 reading-platform-backend.log 改为 reading-platform-java.log - 修改健康检查接口为 /actuator/health - 增加启动等待超时时间到 60 秒(Java 启动较慢) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
510 lines
24 KiB
TypeScript
510 lines
24 KiB
TypeScript
/**
|
||
* 课程包创建 E2E 测试 - 基于"折耳兔奇奇测试课程 01"模板
|
||
*
|
||
* 测试流程:
|
||
* 1. 超管登录
|
||
* 2. 进入课程管理页面
|
||
* 3. 新建课程包
|
||
* 4. 完成 7 个步骤(基本信息、课程介绍、排课参考、导入课、集体课、领域课、环创建设)
|
||
* 5. 验证创建成功
|
||
*
|
||
* 数据来源:基于提供的 JSON 模板数据简化
|
||
*/
|
||
|
||
import { test, expect } from '@playwright/test';
|
||
import { loginAsAdmin, waitForTable, waitForSuccess } from './helpers';
|
||
|
||
// 测试数据 - 基于 JSON 模板
|
||
const TEST_COURSE = {
|
||
// 基本信息
|
||
name: '折耳兔奇奇测试课程 01',
|
||
theme: '社会认知', // 使用实际存在的主题
|
||
grades: ['小班'] as string[],
|
||
domainTags: ['社会适应'] as string[],
|
||
pictureBookName: '折耳兔奇奇',
|
||
coreContent: '通过折耳兔奇奇的故事,帮助孩子理解友谊和分享的重要性',
|
||
duration: 25,
|
||
|
||
// 课程介绍
|
||
introSummary: '本课程以绘本《折耳兔奇奇》为核心载体,面向幼儿园小班幼儿,紧扣"接受认同自己"的核心主题,帮助幼儿建立自信、乐观的心态。',
|
||
introHighlights: '1. 主题鲜明,情感真挚\n2. 领域融合,全面发展\n3. 形式多样,趣味十足\n4. 家园协同,全程联动\n5. 环创赋能,延伸教育',
|
||
introGoals: '1. 认知目标:理解《折耳兔奇奇》绘本核心情节\n2. 能力目标:提升幼儿语言表达、社会交往能力\n3. 情感目标:感受奇奇从自卑到自信的情绪变化',
|
||
introSchedule: '周一:导入课认识奇奇;周二:语言领域绘本解读;周三:社会领域夸夸我和你;周四:健康领域保护耳朵;周五:科学领域兔子的小秘密',
|
||
introKeyPoints: '1. 掌握绘本核心内容\n2. 落实五大领域目标\n3. 推动家校协同',
|
||
introMethods: '1. 绘本阅读法\n2. 课件演示法\n3. 互动游戏法\n4. 情境教学法',
|
||
introEvaluation: '1. 过程性评价\n2. 作品评价\n3. 家园评价\n4. 总结性评价',
|
||
introNotes: '1. 尊重幼儿个体差异\n2. 严格控制各环节课时时长\n3. 注重安全保障',
|
||
|
||
// 排课参考
|
||
totalLessons: 5,
|
||
lessonDuration: 25,
|
||
scheduleAdvice: '建议每周 1-2 课时,按导入课→集体课→五大领域主题课顺序推进',
|
||
|
||
// 导入课
|
||
introLessonName: '导入课——认识奇奇,发现我的特别之处',
|
||
introLessonDuration: 10,
|
||
introLessonObjectives: '1. 认知目标:认识绘本主角折耳兔奇奇,能准确说出奇奇最明显的外形特点(折耳朵)\n2. 能力目标:能大胆、主动地说出自己的一个特别之处\n3. 情感目标:乐于参与集体互动,愿意分享自己的特点',
|
||
introLessonPreparation: '1. 物质准备:折耳兔奇奇毛绒玩具 1 个、绘本封面放大图 1 张、轻音乐\n2. 经验准备:幼儿有观察自己和同伴外貌、爱好的经验',
|
||
|
||
// 集体课
|
||
collectiveLessonName: '集体课——折耳兔奇奇绘本阅读',
|
||
collectiveLessonDuration: 25,
|
||
collectiveLessonObjectives: '1. 认知:完整观看绘本动画,熟悉绘本主要情节和角色\n2. 能力:能跟随教师朗读简单的绘本对话\n3. 情感:感受绘本的趣味性,初步体会奇奇的烦恼',
|
||
|
||
// 领域课 - 健康领域
|
||
healthLessonName: '健康领域——保护我的"小耳朵"',
|
||
healthLessonDuration: 25,
|
||
healthLessonObjectives: '1. 认知:知道耳朵是我们的重要器官,了解耳朵的作用\n2. 能力:学习保护耳朵的正确方法\n3. 情感:愿意主动保护自己的身体器官',
|
||
|
||
// 领域课 - 科学领域
|
||
scienceLessonName: '科学领域——兔子的小秘密',
|
||
scienceLessonDuration: 25,
|
||
scienceLessonObjectives: '1. 认知:了解兔子的基本特征和生活习性\n2. 能力:能通过观察、对比发现不同兔子的外形区别\n3. 情感:对兔子产生探究兴趣,爱护小动物',
|
||
|
||
// 环创建设
|
||
environmentConstruction: '1. 夸夸卡展示区:展示幼儿制作的夸夸卡\n2. "我的特别之处"展示墙:张贴幼儿分享的特别之处作品\n3. 兔子探秘墙:张贴兔子图片和观察记录\n4. 音乐角环创:张贴儿歌歌词图谱、兔子头饰\n5. 健康小卫士展示区:张贴保护耳朵方法海报',
|
||
};
|
||
|
||
test.describe('课程包创建 - 折耳兔奇奇测试课程 01', () => {
|
||
test('完整流程:创建课程包并验证', async ({ page }) => {
|
||
test.setTimeout(300000); // 5 分钟超时
|
||
|
||
// ==================== 步骤 1: 登录 ====================
|
||
console.log('\n========== 开始登录 ==========');
|
||
await loginAsAdmin(page);
|
||
await page.waitForURL('**/admin/**', { timeout: 15000 }).catch(() => {
|
||
console.log('警告:URL 等待超时,但继续执行');
|
||
});
|
||
await page.waitForTimeout(2000); // 增加等待时间确保页面完全加载
|
||
console.log('✅ 登录成功');
|
||
|
||
// ==================== 步骤 2: 进入课程管理页面 ====================
|
||
console.log('\n========== 进入课程管理页面 ==========');
|
||
// 直接导航到课程列表页
|
||
await page.goto('/admin/courses', { timeout: 30000, waitUntil: 'networkidle' });
|
||
await page.waitForTimeout(3000); // 等待数据加载
|
||
|
||
// 验证页面元素(不强制要求表格存在)
|
||
const pageContainer = page.locator('.package-list-page, .course-list-page, [class*="course"], [class*="package"]').first();
|
||
if (await pageContainer.isVisible({ timeout: 5000 })) {
|
||
console.log('✅ 课程管理页面加载完成');
|
||
} else {
|
||
console.log('⚠️ 未找到预期的页面容器,但继续执行');
|
||
}
|
||
|
||
// ==================== 步骤 3: 点击新建课程包按钮 ====================
|
||
console.log('\n========== 点击新建课程包 ==========');
|
||
// 使用 CSS 选择器定位 Ant Design Vue 按钮
|
||
const createButton = page.locator('button:has-text("新建课程包")').first();
|
||
await createButton.waitFor({ state: 'visible', timeout: 15000 });
|
||
await createButton.click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 点击新建课程包');
|
||
|
||
// 验证进入创建页面
|
||
await expect(page.getByText('创建课程包')).toBeVisible({ timeout: 5000 });
|
||
await expect(page.getByText('基本信息')).toBeVisible();
|
||
console.log('✅ 进入课程创建页面');
|
||
|
||
// ==================== 步骤 1: 基本信息 ====================
|
||
console.log('\n========== 步骤 1: 基本信息 ==========');
|
||
|
||
// 填写课程包名称
|
||
const nameInput = page.getByPlaceholder('请输入课程包名称');
|
||
await expect(nameInput).toBeVisible({ timeout: 3000 });
|
||
await nameInput.fill(TEST_COURSE.name);
|
||
console.log(` - 填写课程名称:${TEST_COURSE.name}`);
|
||
|
||
// 选择关联主题
|
||
await page.locator('.ant-select-selector').first().click();
|
||
await page.waitForTimeout(500);
|
||
await page.getByText(TEST_COURSE.theme, { exact: true }).first().click();
|
||
await page.waitForTimeout(300);
|
||
console.log(` - 选择主题:${TEST_COURSE.theme}`);
|
||
|
||
// 选择适用年级
|
||
await page.getByRole('checkbox', { name: TEST_COURSE.grades[0] }).click();
|
||
await page.waitForTimeout(300);
|
||
console.log(` - 选择年级:${TEST_COURSE.grades[0]}`);
|
||
|
||
// 填写核心内容
|
||
const coreContentInput = page.getByPlaceholder('请输入课程包核心内容');
|
||
await expect(coreContentInput).toBeVisible({ timeout: 3000 });
|
||
await coreContentInput.fill(TEST_COURSE.coreContent);
|
||
console.log(` - 填写核心内容:${TEST_COURSE.coreContent}`);
|
||
|
||
// 填写绘本名称
|
||
const bookNameInput = page.getByPlaceholder('请输入关联绘本名称(可选)');
|
||
await expect(bookNameInput).toBeVisible({ timeout: 3000 });
|
||
await bookNameInput.fill(TEST_COURSE.pictureBookName);
|
||
console.log(` - 填写绘本名称:${TEST_COURSE.pictureBookName}`);
|
||
|
||
// 选择领域标签
|
||
const domainSelector = page.locator('.ant-select-selector').last();
|
||
await domainSelector.click();
|
||
await page.waitForTimeout(800);
|
||
await page.getByText(TEST_COURSE.domainTags[0], { exact: true }).first().click({ force: true });
|
||
await page.waitForTimeout(300);
|
||
await page.keyboard.press('Escape');
|
||
console.log(` - 选择领域标签:${TEST_COURSE.domainTags[0]}`);
|
||
|
||
// 点击下一步
|
||
await page.getByRole('button', { name: '下一步' }).click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 步骤 1 完成 - 基本信息');
|
||
|
||
// ==================== 步骤 2: 课程介绍 ====================
|
||
console.log('\n========== 步骤 2: 课程介绍 ==========');
|
||
|
||
await expect(page.locator('.intro-header .title:has-text("课程介绍")')).toBeVisible({ timeout: 3000 });
|
||
|
||
// 填写课程简介 - 使用更精确的定位
|
||
await page.getByRole('tab', { name: '课程简介' }).click();
|
||
await page.waitForTimeout(1000);
|
||
// 使用 visible 选择器找到可见的 textarea
|
||
const summaryTextarea = page.locator('.tab-content textarea:visible').first();
|
||
await summaryTextarea.waitFor({ state: 'visible', timeout: 10000 });
|
||
await summaryTextarea.fill(TEST_COURSE.introSummary);
|
||
console.log(' - 填写课程简介');
|
||
|
||
// 填写课程亮点
|
||
await page.getByRole('tab', { name: '课程亮点' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introHighlights);
|
||
console.log(' - 填写课程亮点');
|
||
|
||
// 填写课程总目标
|
||
await page.getByRole('tab', { name: '课程总目标' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introGoals);
|
||
console.log(' - 填写课程目标');
|
||
|
||
// 填写内容安排
|
||
await page.getByRole('tab', { name: '内容安排' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introSchedule);
|
||
console.log(' - 填写内容安排');
|
||
|
||
// 填写重难点
|
||
await page.getByRole('tab', { name: '重难点' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introKeyPoints);
|
||
console.log(' - 填写重难点');
|
||
|
||
// 填写教学方法
|
||
await page.getByRole('tab', { name: '教学方法' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introMethods);
|
||
console.log(' - 填写教学方法');
|
||
|
||
// 填写评价方式
|
||
await page.getByRole('tab', { name: '评价方式' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introEvaluation);
|
||
console.log(' - 填写评价方式');
|
||
|
||
// 填写注意事项
|
||
await page.getByRole('tab', { name: '注意事项' }).click();
|
||
await page.waitForTimeout(500);
|
||
await page.locator('.tab-content textarea:visible').first().fill(TEST_COURSE.introNotes);
|
||
console.log(' - 填写注意事项');
|
||
|
||
// 点击下一步
|
||
await page.getByRole('button', { name: '下一步' }).click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 步骤 2 完成 - 课程介绍');
|
||
|
||
// ==================== 步骤 3: 排课参考 ====================
|
||
console.log('\n========== 步骤 3: 排课参考 ==========');
|
||
|
||
await expect(page.locator('.step3-schedule-ref .title:has-text("排课计划参考")')).toBeVisible({ timeout: 3000 });
|
||
|
||
// 使用快速填充模板(可选步骤,跳过详细填写)
|
||
const fillWeekButton = page.getByText('填充一周模板');
|
||
if (await fillWeekButton.isVisible({ timeout: 5000 })) {
|
||
await fillWeekButton.click();
|
||
await page.waitForTimeout(500);
|
||
console.log(' - 使用快速填充模板');
|
||
}
|
||
|
||
// 点击下一步
|
||
await page.getByRole('button', { name: '下一步' }).click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 步骤 3 完成 - 排课参考');
|
||
|
||
// ==================== 步骤 4: 导入课 ====================
|
||
console.log('\n========== 步骤 4: 导入课 ==========');
|
||
|
||
await expect(page.locator('.step4-intro-lesson .title:has-text("导入课")')).toBeVisible({ timeout: 3000 });
|
||
|
||
// 点击创建导入课按钮(如果需要)
|
||
const createIntroButton = page.getByText('创建导入课');
|
||
if (await createIntroButton.isVisible({ timeout: 3000 })) {
|
||
await createIntroButton.click();
|
||
await page.waitForTimeout(1000);
|
||
console.log(' - 点击创建导入课');
|
||
}
|
||
|
||
// 填写导入课名称
|
||
const introLessonNameInput = page.locator('input[placeholder*="课程名称"]').first();
|
||
if (await introLessonNameInput.isVisible({ timeout: 3000 })) {
|
||
await introLessonNameInput.fill(TEST_COURSE.introLessonName);
|
||
console.log(` - 填写导入课名称:${TEST_COURSE.introLessonName}`);
|
||
}
|
||
|
||
// 填写课时时长
|
||
const introLessonDurationInput = page.locator('input[placeholder*="时长"]').first();
|
||
if (await introLessonDurationInput.isVisible({ timeout: 3000 })) {
|
||
await introLessonDurationInput.fill(String(TEST_COURSE.introLessonDuration));
|
||
console.log(` - 填写导入课时长:${TEST_COURSE.introLessonDuration}分钟`);
|
||
}
|
||
|
||
// 填写教学目标
|
||
const introLessonObjectivesTextarea = page.locator('textarea[placeholder*="教学目标"]').first();
|
||
if (await introLessonObjectivesTextarea.isVisible({ timeout: 3000 })) {
|
||
await introLessonObjectivesTextarea.fill(TEST_COURSE.introLessonObjectives);
|
||
console.log(' - 填写导入课教学目标');
|
||
}
|
||
|
||
// 填写教学准备
|
||
const introLessonPreparationTextarea = page.locator('textarea[placeholder*="教学准备"]').first();
|
||
if (await introLessonPreparationTextarea.isVisible({ timeout: 3000 })) {
|
||
await introLessonPreparationTextarea.fill(TEST_COURSE.introLessonPreparation);
|
||
console.log(' - 填写导入课教学准备');
|
||
}
|
||
|
||
// 点击下一步
|
||
await page.getByRole('button', { name: '下一步' }).click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 步骤 4 完成 - 导入课');
|
||
|
||
// ==================== 步骤 5: 集体课 ====================
|
||
console.log('\n========== 步骤 5: 集体课 ==========');
|
||
|
||
await expect(page.locator('.step5-collective-lesson .title:has-text("集体课")')).toBeVisible({ timeout: 3000 });
|
||
|
||
// 点击创建集体课按钮(如果需要)
|
||
const createCollectiveButton = page.getByText('创建集体课');
|
||
if (await createCollectiveButton.isVisible({ timeout: 3000 })) {
|
||
await createCollectiveButton.click();
|
||
await page.waitForTimeout(1000);
|
||
console.log(' - 点击创建集体课');
|
||
}
|
||
|
||
// 填写集体课名称
|
||
const collectiveLessonNameInput = page.locator('input[placeholder*="课程名称"]').first();
|
||
if (await collectiveLessonNameInput.isVisible({ timeout: 3000 })) {
|
||
await collectiveLessonNameInput.fill(TEST_COURSE.collectiveLessonName);
|
||
console.log(` - 填写集体课名称:${TEST_COURSE.collectiveLessonName}`);
|
||
}
|
||
|
||
// 填写课时时长
|
||
const collectiveLessonDurationInput = page.locator('input[placeholder*="时长"]').first();
|
||
if (await collectiveLessonDurationInput.isVisible({ timeout: 3000 })) {
|
||
await collectiveLessonDurationInput.fill(String(TEST_COURSE.collectiveLessonDuration));
|
||
console.log(` - 填写集体课时长:${TEST_COURSE.collectiveLessonDuration}分钟`);
|
||
}
|
||
|
||
// 填写教学目标
|
||
const collectiveLessonObjectivesTextarea = page.locator('textarea[placeholder*="教学目标"]').first();
|
||
if (await collectiveLessonObjectivesTextarea.isVisible({ timeout: 3000 })) {
|
||
await collectiveLessonObjectivesTextarea.fill(TEST_COURSE.collectiveLessonObjectives);
|
||
console.log(' - 填写集体课教学目标');
|
||
}
|
||
|
||
// 点击下一步
|
||
await page.getByRole('button', { name: '下一步' }).click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 步骤 5 完成 - 集体课');
|
||
|
||
// ==================== 步骤 6: 领域课 ====================
|
||
console.log('\n========== 步骤 6: 领域课 ==========');
|
||
|
||
await expect(page.locator('.step6-domain-lessons .title:has-text("五大领域课")')).toBeVisible({ timeout: 3000 });
|
||
|
||
// 填写健康领域课程
|
||
console.log(' - 填写健康领域课程');
|
||
|
||
// 展开健康领域卡片
|
||
const healthDomainCard = page.locator('.domain-card').filter({ hasText: /健康/ }).first();
|
||
const healthSwitch = healthDomainCard.locator('.ant-switch').first();
|
||
if (await healthSwitch.isVisible({ timeout: 3000 })) {
|
||
await healthSwitch.click();
|
||
await page.waitForTimeout(500);
|
||
}
|
||
|
||
// 点击展开按钮
|
||
const healthExpandButton = healthDomainCard.locator('button:has-text("展开")').first();
|
||
if (await healthExpandButton.isVisible({ timeout: 3000 })) {
|
||
await healthExpandButton.click();
|
||
await page.waitForTimeout(1000);
|
||
}
|
||
|
||
// 填写健康领域课程名称
|
||
const healthLessonNameInput = healthDomainCard.locator('input[placeholder*="课程名称"]').first();
|
||
if (await healthLessonNameInput.isVisible({ timeout: 3000 })) {
|
||
await healthLessonNameInput.fill(TEST_COURSE.healthLessonName);
|
||
console.log(` 课程名称:${TEST_COURSE.healthLessonName}`);
|
||
}
|
||
|
||
// 填写课时时长
|
||
const healthLessonDurationInput = healthDomainCard.locator('input[placeholder*="时长"]').first();
|
||
if (await healthLessonDurationInput.isVisible({ timeout: 3000 })) {
|
||
await healthLessonDurationInput.fill(String(TEST_COURSE.healthLessonDuration));
|
||
console.log(` 课时时长:${TEST_COURSE.healthLessonDuration}分钟`);
|
||
}
|
||
|
||
// 填写教学目标
|
||
const healthLessonObjectivesTextarea = healthDomainCard.locator('textarea[placeholder*="教学目标"]').first();
|
||
if (await healthLessonObjectivesTextarea.isVisible({ timeout: 3000 })) {
|
||
await healthLessonObjectivesTextarea.fill(TEST_COURSE.healthLessonObjectives);
|
||
console.log(' 教学目标:已填写');
|
||
}
|
||
|
||
// 填写科学领域课程
|
||
console.log(' - 填写科学领域课程');
|
||
|
||
// 展开科学领域卡片
|
||
const scienceDomainCard = page.locator('.domain-card').filter({ hasText: /科学/ }).first();
|
||
const scienceSwitch = scienceDomainCard.locator('.ant-switch').first();
|
||
if (await scienceSwitch.isVisible({ timeout: 3000 })) {
|
||
await scienceSwitch.click();
|
||
await page.waitForTimeout(500);
|
||
}
|
||
|
||
// 点击展开按钮
|
||
const scienceExpandButton = scienceDomainCard.locator('button:has-text("展开")').first();
|
||
if (await scienceExpandButton.isVisible({ timeout: 3000 })) {
|
||
await scienceExpandButton.click();
|
||
await page.waitForTimeout(1000);
|
||
}
|
||
|
||
// 填写科学领域课程名称
|
||
const scienceLessonNameInput = scienceDomainCard.locator('input[placeholder*="课程名称"]').first();
|
||
if (await scienceLessonNameInput.isVisible({ timeout: 3000 })) {
|
||
await scienceLessonNameInput.fill(TEST_COURSE.scienceLessonName);
|
||
console.log(` 课程名称:${TEST_COURSE.scienceLessonName}`);
|
||
}
|
||
|
||
// 填写课时时长
|
||
const scienceLessonDurationInput = scienceDomainCard.locator('input[placeholder*="时长"]').first();
|
||
if (await scienceLessonDurationInput.isVisible({ timeout: 3000 })) {
|
||
await scienceLessonDurationInput.fill(String(TEST_COURSE.scienceLessonDuration));
|
||
console.log(` 课时时长:${TEST_COURSE.scienceLessonDuration}分钟`);
|
||
}
|
||
|
||
// 填写教学目标
|
||
const scienceLessonObjectivesTextarea = scienceDomainCard.locator('textarea[placeholder*="教学目标"]').first();
|
||
if (await scienceLessonObjectivesTextarea.isVisible({ timeout: 3000 })) {
|
||
await scienceLessonObjectivesTextarea.fill(TEST_COURSE.scienceLessonObjectives);
|
||
console.log(' 教学目标:已填写');
|
||
}
|
||
|
||
// 点击下一步
|
||
await page.getByRole('button', { name: '下一步' }).click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ 步骤 6 完成 - 领域课');
|
||
|
||
// ==================== 步骤 7: 环创建设 ====================
|
||
console.log('\n========== 步骤 7: 环创建设 ==========');
|
||
|
||
await expect(page.locator('.step7-environment .title:has-text("环创建设")')).toBeVisible({ timeout: 3000 });
|
||
|
||
// 填写环创建设内容
|
||
const envTextarea = page.locator('.step7-environment textarea').first();
|
||
await expect(envTextarea).toBeVisible({ timeout: 3000 });
|
||
await envTextarea.fill(TEST_COURSE.environmentConstruction);
|
||
console.log(' - 填写环创建设内容');
|
||
|
||
// 点击提交/创建按钮 - 使用 CSS 选择器定位
|
||
const submitButton = page.locator('.step-actions button.ant-btn-primary').last();
|
||
await submitButton.waitFor({ state: 'visible', timeout: 10000 });
|
||
await submitButton.click();
|
||
console.log(' - 点击创建按钮');
|
||
console.log('✅ 步骤 7 完成 - 环创建设');
|
||
|
||
// 等待一段时间让保存操作完成
|
||
await page.waitForTimeout(5000);
|
||
|
||
// ==================== 验证创建成功 ====================
|
||
console.log('\n========== 验证创建结果 ==========');
|
||
|
||
// 等待成功提示
|
||
try {
|
||
await page.waitForSelector('.ant-message-success', { timeout: 10000 });
|
||
console.log('✅ 成功提示显示');
|
||
} catch (e) {
|
||
console.log('⚠️ 未找到成功提示,检查是否有错误提示');
|
||
const errorMsg = await page.locator('.ant-message-error').textContent().catch(() => '');
|
||
if (errorMsg) {
|
||
console.error('❌ 错误信息:', errorMsg);
|
||
}
|
||
}
|
||
|
||
// 给页面一些时间执行跳转逻辑
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 等待跳转到列表页 - 使用精确匹配(排除 edit 页面)
|
||
console.log('⏳ 等待页面跳转到课程列表...');
|
||
await page.waitForURL((url) => {
|
||
const urlStr = url.toString();
|
||
if (urlStr.includes('/edit')) {
|
||
console.log(' - 仍在编辑页面,URL:', urlStr);
|
||
return false;
|
||
}
|
||
if (urlStr.includes('/admin/courses')) {
|
||
console.log(' - 已跳转到课程列表页,URL:', urlStr);
|
||
return true;
|
||
}
|
||
return false;
|
||
}, { timeout: 15000 });
|
||
console.log('✅ 页面跳转到课程列表');
|
||
|
||
// 等待表格加载完成
|
||
await page.waitForTimeout(3000);
|
||
|
||
// 检查当前 URL
|
||
const currentUrl = page.url();
|
||
console.log('📍 当前 URL:', currentUrl);
|
||
|
||
// 使用更宽松的等待策略
|
||
const table = page.locator('.ant-table').first();
|
||
await table.waitFor({ state: 'attached', timeout: 10000 });
|
||
await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 检查表格是否为空
|
||
const isEmpty = await table.locator('.ant-empty').isVisible().catch(() => false);
|
||
console.log('📊 表格是否为空:', isEmpty);
|
||
|
||
// 获取表格行数
|
||
const rowCount = await table.locator('.ant-table-tbody tr').count();
|
||
console.log('📊 表格行数:', rowCount);
|
||
|
||
// 获取所有课程包名称
|
||
const courseNames = await page.locator('.ant-table-tbody tr td:first-child').allTextContents();
|
||
console.log('📊 当前课程包列表:', courseNames);
|
||
|
||
// 查找新课程包
|
||
const courseRow = table.getByText(TEST_COURSE.name);
|
||
try {
|
||
await expect(courseRow).toBeVisible({ timeout: 10000 });
|
||
console.log(`✅ 新课程包 "${TEST_COURSE.name}" 在列表中显示`);
|
||
} catch {
|
||
// 如果找不到,刷新页面后再试一次
|
||
console.log(' - 第一次尝试未找到,刷新页面...');
|
||
await page.reload({ waitUntil: 'networkidle' });
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 再次检查课程包列表
|
||
const courseNamesAfterRefresh = await page.locator('.ant-table-tbody tr td:first-child').allTextContents();
|
||
console.log('📊 刷新后课程包列表:', courseNamesAfterRefresh);
|
||
|
||
await expect(table.getByText(TEST_COURSE.name)).toBeVisible({ timeout: 10000 });
|
||
console.log(`✅ 新课程包 "${TEST_COURSE.name}" 在列表中显示(刷新后)`);
|
||
}
|
||
|
||
console.log('\n🎉 课程包创建测试全部通过!');
|
||
});
|
||
});
|