kindergarten_java/reading-platform-frontend/tests/e2e/admin/course-create-from-template.spec.ts
En 938503f2b8 chore: 更新启动脚本使用 Java (Spring Boot) 后端
- 修改后端目录从 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>
2026-03-16 10:35:30 +08:00

239 lines
9.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 课程包创建 E2E 测试 - 基于"折耳兔奇奇"模板
*
* 测试流程:
* 1. 超管登录
* 2. 进入课程管理页面
* 3. 新建课程包
* 4. 完成 7 个步骤
* 5. 验证创建成功
*/
import { test, expect } from '@playwright/test';
import { loginAsAdmin, waitForTable } from './helpers';
// 测试数据 - 基于 JSON 模板简化(使用实际存在的主题和领域)
const TEST_COURSE = {
name: '折耳兔奇奇测试课程 01',
theme: '社会认知', // 使用实际存在的主题
grades: ['小班'],
bookName: '折耳兔奇奇',
coreContent: '通过折耳兔奇奇的故事,帮助孩子理解友谊和分享的重要性',
domainTags: ['倾听与表达'], // 使用实际存在的选项文本
};
test.describe('课程包创建 - 折耳兔奇奇模板', () => {
test('完整流程:创建课程包并验证', async ({ page }) => {
test.setTimeout(180000); // 设置更长的超时时间3 分钟)
// 步骤 1: 登录
await loginAsAdmin(page);
console.log('✅ 登录成功');
// 验证登录成功 - 检查是否跳转到 admin 页面
await page.waitForURL('**/admin/**', { timeout: 15000 }).catch(() => {
console.log('警告URL 等待超时,但继续执行');
});
await page.waitForTimeout(1000);
// 步骤 2: 进入课程管理页面
await page.goto('/admin/courses', { timeout: 30000, waitUntil: 'commit' });
await waitForTable(page, 15000);
await page.waitForTimeout(500);
console.log('✅ 进入课程管理页面');
// 步骤 3: 点击新建课程包按钮
const createButton = page.getByText(/新建|创建|新增课程/);
await createButton.click();
await page.waitForTimeout(1000);
console.log('✅ 点击新建课程包');
// 验证进入创建页面
await expect(page.getByText('创建课程包')).toBeVisible({ timeout: 5000 });
await expect(page.getByText('基本信息')).toBeVisible();
// ==================== 步骤 1: 基本信息 ====================
console.log('开始步骤 1: 基本信息');
// 填写课程包名称
await page.getByPlaceholder('请输入课程包名称').fill(TEST_COURSE.name);
console.log(' - 填写课程名称');
// 选择关联主题 - 先点击 selector 打开下拉框
await page.locator('.ant-select-selector').first().click();
await page.waitForTimeout(500);
// 选择主题(主题选项在页面底部,直接使用 getByText
await page.getByText(TEST_COURSE.theme, { exact: true }).first().click();
await page.waitForTimeout(300);
console.log(' - 选择主题');
// 选择适用年级 - 使用 checkbox
await page.getByRole('checkbox', { name: TEST_COURSE.grades[0] }).click();
await page.waitForTimeout(300);
console.log(' - 选择年级');
// 填写核心内容
await page.getByPlaceholder('请输入课程包核心内容').fill(TEST_COURSE.coreContent);
console.log(' - 填写核心内容');
// 填写绘本名称
await page.getByPlaceholder('请输入关联绘本名称(可选)').fill(TEST_COURSE.bookName);
console.log(' - 填写绘本名称');
// 选择领域标签 - 使用 selector 组件
const domainSelector = page.locator('.ant-select-selector').last();
await domainSelector.click();
await page.waitForTimeout(800);
// 选择领域标签(使用实际存在的选项文本)
for (const tag of TEST_COURSE.domainTags) {
await page.getByText(tag, { exact: true }).first().click({ force: true });
await page.waitForTimeout(300);
}
// 关闭下拉
await page.keyboard.press('Escape');
await page.waitForTimeout(300);
console.log(' - 选择领域标签');
// 点击下一步
await page.getByRole('button', { name: '下一步' }).click();
await page.waitForTimeout(1000);
console.log('✅ 步骤 1 完成');
// ==================== 步骤 2: 课程介绍 ====================
console.log('开始步骤 2: 课程介绍');
// 验证步骤标题(使用更精确的选择器)
await expect(page.locator('.ant-steps-item-title').nth(1)).toBeVisible();
// 切换到课程简介标签页并填写
await page.getByRole('tab', { name: '课程简介' }).click();
await page.waitForTimeout(1000);
const summaryTextarea = page.locator('.tab-content textarea:visible').first();
await summaryTextarea.waitFor({ state: 'visible', timeout: 10000 });
await summaryTextarea.fill('这是一门专为小班幼儿设计的课程,通过有趣的故事情节,培养孩子的语言表达能力和社交技能。');
console.log(' - 填写课程简介');
// 切换到课程亮点标签页
await page.getByRole('tab', { name: '课程亮点' }).click();
await page.waitForTimeout(500);
await page.locator('.tab-content textarea:visible').first().fill('1. 故事情节生动有趣\n2. 互动性强\n3. 培养分享意识');
console.log(' - 填写课程亮点');
// 切换到课程目标标签页
await page.getByRole('tab', { name: '课程总目标' }).click();
await page.waitForTimeout(500);
await page.locator('.tab-content textarea:visible').first().fill('1. 理解故事内容\n2. 学会分享\n3. 培养语言表达能力');
console.log(' - 填写课程目标');
// 点击下一步
await page.getByRole('button', { name: '下一步' }).click();
await page.waitForTimeout(1000);
console.log('✅ 步骤 2 完成');
// ==================== 步骤 3: 排课参考 ====================
console.log('开始步骤 3: 排课参考');
// 验证步骤标题
await expect(page.getByText('排课参考')).toBeVisible();
// 填写总课时
await page.locator('input[placeholder="请输入总课时"]').fill('8');
console.log(' - 填写总课时');
// 填写课时时长 (分钟)
await page.locator('input[placeholder="请输入课时时长"]').fill('30');
console.log(' - 填写课时时长');
// 填写排课建议
const scheduleTextarea = page.locator('textarea[placeholder*="排课建议"]').first();
await scheduleTextarea.fill('建议每周 1-2 课时,可根据实际情况调整');
console.log(' - 填写排课建议');
// 点击下一步
await page.getByRole('button', { name: '下一步' }).click();
await page.waitForTimeout(1000);
console.log('✅ 步骤 3 完成');
// ==================== 步骤 4: 导入课 ====================
console.log('开始步骤 4: 导入课');
// 验证步骤标题
await expect(page.getByText('导入课')).toBeVisible();
// 跳过导入课配置(可选步骤)
console.log(' - 跳过导入课(可选)');
// 点击下一步
await page.getByRole('button', { name: '下一步' }).click();
await page.waitForTimeout(1000);
console.log('✅ 步骤 4 完成');
// ==================== 步骤 5: 集体课 ====================
console.log('开始步骤 5: 集体课');
// 验证步骤标题
await expect(page.getByText('集体课')).toBeVisible();
// 跳过集体课配置(可选步骤)
console.log(' - 跳过集体课(可选)');
// 点击下一步
await page.getByRole('button', { name: '下一步' }).click();
await page.waitForTimeout(1000);
console.log('✅ 步骤 5 完成');
// ==================== 步骤 6: 领域课 ====================
console.log('开始步骤 6: 领域课');
// 验证步骤标题
await expect(page.getByText('领域课')).toBeVisible();
// 跳过领域课配置(可选步骤)
console.log(' - 跳过领域课(可选)');
// 点击下一步
await page.getByRole('button', { name: '下一步' }).click();
await page.waitForTimeout(1000);
console.log('✅ 步骤 6 完成');
// ==================== 步骤 7: 环创建设 ====================
console.log('开始步骤 7: 环创建设');
// 验证步骤标题
await expect(page.getByText('环创建设')).toBeVisible();
// 填写环创建设内容
const envTextarea = page.locator('textarea').filter({ hasText: '主题墙布置建议' }).first();
await envTextarea.fill('主题墙布置建议:\n1. 展示折耳兔奇奇的故事图片\n2. 设置分享主题墙\n3. 展示幼儿作品');
console.log(' - 填写环创建设内容');
// 点击提交
await page.getByRole('button', { name: '提交' }).click();
console.log('✅ 步骤 7 完成');
// ==================== 验证创建成功 ====================
console.log('验证创建结果...');
// 等待成功提示
await page.waitForSelector('.ant-message-success', { timeout: 5000 });
await expect(page.getByText('创建成功')).toBeVisible({ timeout: 5000 });
console.log('✅ 创建成功提示显示');
// 等待跳转到列表页
await page.waitForURL('**/admin/courses**', { timeout: 10000 });
console.log('✅ 页面跳转到课程列表');
// 验证新课程包在列表中显示
await page.waitForTimeout(2000);
const table = page.locator('.ant-table').first();
await expect(table).toBeVisible();
// 查找新课程包
const courseRow = table.getByText(TEST_COURSE.name);
await expect(courseRow).toBeVisible({ timeout: 5000 });
console.log(`✅ 新课程包 "${TEST_COURSE.name}" 在列表中显示`);
console.log('\n🎉 课程包创建测试全部通过!');
});
});