前后端目录重命名: - reading-platform-java/ → lesingle-edu-reading-platform-backend/ - reading-platform-frontend/ → lesingle-edu-reading-platform-frontend/ 更新相关文件: - 所有 shell 脚本中的目录引用 - pom.xml 和 application.yml 中的项目名称 - package.json 中的项目名称 - .claude/CLAUDE.md 中的路径引用 - README 文档中的路径引用
273 lines
8.8 KiB
TypeScript
273 lines
8.8 KiB
TypeScript
/**
|
|
* 学校端 E2E 测试 - 校本课程包功能
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
import { loginAsSchool, clickSubMenu } from './helpers';
|
|
import { SCHOOL_CONFIG } from './fixtures';
|
|
|
|
test.describe('学校端校本课程包功能', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginAsSchool(page);
|
|
});
|
|
|
|
test('测试 1: 访问校本课程包页面', async ({ page }) => {
|
|
// 1. 点击教学管理 → 校本课程包
|
|
await clickSubMenu(page, '教学管理', '校本课程包');
|
|
await page.waitForURL('**/school-courses*', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 验证页面标题
|
|
await expect(page.locator('text=我的校本课程包').or(page.locator('text=校本课程包')).first()).toBeVisible({ timeout: 5000 });
|
|
|
|
// 3. 检查课程列表
|
|
const courseCards = page.locator('.ant-card, [class*="course-card"]');
|
|
const courseCount = await courseCards.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `校本课程包数量:${courseCount}`,
|
|
});
|
|
|
|
// 截图
|
|
await page.screenshot({ path: 'test-results/school-courses-list.png' });
|
|
});
|
|
|
|
test('测试 2: 创建校本课程包', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入课程中心
|
|
await clickSubMenu(page, '教学管理', '课程管理');
|
|
await page.waitForURL('**/courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 点击第一个课程卡片
|
|
const firstCourseCard = page.locator('.course-card').first();
|
|
const cardCount = await firstCourseCard.count();
|
|
|
|
if (cardCount > 0) {
|
|
await firstCourseCard.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 3. 检查"创建校本版本"按钮
|
|
const createBtn = page.locator('button:has-text("创建校本版本")');
|
|
if (await createBtn.count() > 0) {
|
|
const beforeUrl = page.url();
|
|
|
|
// 4. 点击创建
|
|
await createBtn.click();
|
|
|
|
// 5. 等待跳转到编辑页面
|
|
await page.waitForURL('**/school-courses/**/edit', { timeout: 15000 });
|
|
await page.waitForTimeout(2000);
|
|
|
|
const currentUrl = page.url();
|
|
test.info().annotations.push({
|
|
type: 'success',
|
|
description: `创建成功:从 ${beforeUrl} 跳转到 ${currentUrl}`,
|
|
});
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到"创建校本版本"按钮',
|
|
});
|
|
}
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到课程卡片',
|
|
});
|
|
}
|
|
});
|
|
|
|
test('测试 3: 编辑校本课程包', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入校本课程包页面
|
|
await clickSubMenu(page, '教学管理', '校本课程包');
|
|
await page.waitForURL('**/school-courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 查找编辑按钮
|
|
const editBtn = page.locator('button:has-text("编辑")').first();
|
|
if (await editBtn.count() > 0) {
|
|
await editBtn.click();
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 3. 验证进入编辑页面
|
|
const url = page.url();
|
|
expect(url).toContain('/edit');
|
|
|
|
// 4. 检查步骤导航
|
|
const steps = page.locator('.ant-steps-item, [class*="step"]');
|
|
const stepCount = await steps.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `编辑步骤数量:${stepCount}`,
|
|
});
|
|
|
|
// 5. 保存修改
|
|
const saveBtn = page.locator('button:has-text("保存")').or(page.locator('button:has-text("保存到个人")'));
|
|
if (await saveBtn.count() > 0) {
|
|
await saveBtn.first().click();
|
|
await page.waitForTimeout(2000);
|
|
}
|
|
|
|
// 截图
|
|
await page.screenshot({ path: 'test-results/school-course-edit.png' });
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到可编辑的课程',
|
|
});
|
|
}
|
|
});
|
|
|
|
test('测试 4: 查看校本课程详情', async ({ page }) => {
|
|
// 1. 进入校本课程包页面
|
|
await clickSubMenu(page, '教学管理', '校本课程包');
|
|
await page.waitForURL('**/school-courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 查找查看按钮
|
|
const viewBtn = page.locator('button:has-text("查看")').first();
|
|
if (await viewBtn.count() > 0) {
|
|
await viewBtn.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 3. 验证详情页
|
|
const url = page.url();
|
|
expect(url).toContain('/school-courses/');
|
|
|
|
// 4. 检查详情页内容
|
|
const detailElements = page.locator('text=开始备课').or(page.locator('text=课程介绍'));
|
|
await expect(detailElements.first()).toBeVisible({ timeout: 5000 });
|
|
|
|
// 截图
|
|
await page.screenshot({ path: 'test-results/school-course-detail.png' });
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到可查看的课程',
|
|
});
|
|
}
|
|
});
|
|
|
|
test('测试 5: 备课模式', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入校本课程包页面
|
|
await clickSubMenu(page, '教学管理', '校本课程包');
|
|
await page.waitForURL('**/school-courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 查找"开始备课"按钮
|
|
const prepareBtn = page.locator('button:has-text("开始备课")').first();
|
|
if (await prepareBtn.count() > 0) {
|
|
await prepareBtn.click();
|
|
await page.waitForTimeout(3000);
|
|
|
|
// 3. 验证进入备课模式
|
|
const url = page.url();
|
|
expect(url).toContain('/prepare');
|
|
|
|
// 4. 检查备课模式布局
|
|
const navigation = page.locator('aside, [class*="navigation"], [class*="sidebar"]');
|
|
await expect(navigation.first()).toBeVisible({ timeout: 5000 });
|
|
|
|
// 5. 检查课程列表
|
|
const lessonItems = page.locator('[class*="lesson"], [class*="course"]');
|
|
const lessonCount = await lessonItems.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `备课模式课程数量:${lessonCount}`,
|
|
});
|
|
|
|
// 截图
|
|
await page.screenshot({ path: 'test-results/school-prepare-mode.png' });
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到"开始备课"按钮',
|
|
});
|
|
}
|
|
});
|
|
|
|
test('测试 6: 删除校本课程包', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入校本课程包页面
|
|
await clickSubMenu(page, '教学管理', '校本课程包');
|
|
await page.waitForURL('**/school-courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 记录删除前的课程数量
|
|
const courseCards = page.locator('.ant-card, [class*="course"]');
|
|
const beforeCount = await courseCards.count();
|
|
|
|
// 3. 查找删除按钮
|
|
const deleteBtn = page.locator('button:has-text("删除")').first();
|
|
if (await deleteBtn.count() > 0) {
|
|
await deleteBtn.click();
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 4. 确认删除
|
|
const confirmBtn = page.locator('button:has-text("确定")').or(page.locator('button:has-text("确认")'));
|
|
if (await confirmBtn.count() > 0) {
|
|
await confirmBtn.first().click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 5. 验证删除
|
|
const afterCount = await courseCards.count();
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `删除前:${beforeCount}, 删除后:${afterCount}`,
|
|
});
|
|
}
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到删除按钮',
|
|
});
|
|
}
|
|
});
|
|
|
|
test('测试 7: 筛选功能', async ({ page }) => {
|
|
// 1. 进入校本课程包页面
|
|
await clickSubMenu(page, '教学管理', '校本课程包');
|
|
await page.waitForURL('**/school-courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 2. 查找筛选器
|
|
const personalFilter = page.locator('text=个人').or(page.locator('[role="tab"]:has-text("个人")'));
|
|
const schoolFilter = page.locator('text=校本').or(page.locator('[role="tab"]:has-text("校本")'));
|
|
|
|
if (await personalFilter.count() > 0) {
|
|
// 3. 点击"个人"筛选
|
|
await personalFilter.first().click();
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 4. 点击"校本"筛选
|
|
if (await schoolFilter.count() > 0) {
|
|
await schoolFilter.first().click();
|
|
await page.waitForTimeout(1000);
|
|
}
|
|
|
|
test.info().annotations.push({
|
|
type: 'success',
|
|
description: '筛选功能测试完成',
|
|
});
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到筛选器',
|
|
});
|
|
}
|
|
|
|
// 截图
|
|
await page.screenshot({ path: 'test-results/school-course-filter.png' });
|
|
});
|
|
});
|