前后端目录重命名: - 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 文档中的路径引用
416 lines
14 KiB
TypeScript
416 lines
14 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('课程进度追踪', () => {
|
|
let baseURL = 'http://localhost:5173';
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto(baseURL);
|
|
await page.waitForLoadState('networkidle');
|
|
await page.click('text=教师');
|
|
await page.waitForTimeout(500);
|
|
|
|
const accountInput = page.locator('input[placeholder*="账号"]').or(page.locator('input[name="account"]'));
|
|
await accountInput.fill('teacher1');
|
|
|
|
const passwordInput = page.locator('input[placeholder*="密码"]').or(page.locator('input[type="password"]'));
|
|
await passwordInput.fill('123456');
|
|
|
|
const loginButton = page.locator('button[type="submit"]').or(page.locator('.login-btn')).or(page.locator('button:has-text("登录")'));
|
|
await loginButton.click();
|
|
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 }).catch(() => {
|
|
return page.waitForURL('**/courses', { timeout: 5000 });
|
|
});
|
|
await page.waitForTimeout(1000);
|
|
});
|
|
|
|
test('测试1: 进度自动保存', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入课程中心并开始上课
|
|
await page.click('text=课程中心');
|
|
await page.waitForURL('**/courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
const firstCourseCard = page.locator('.course-card').or(page.locator('[class*="course-card"]')).first();
|
|
await firstCourseCard.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 点击"选择课程上课"
|
|
const selectLessonsButton = page.locator('button:has-text("选择课程上课")');
|
|
if (await selectLessonsButton.count() > 0) {
|
|
await selectLessonsButton.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const confirmButton = page.locator('button:has-text("确定")');
|
|
if (await confirmButton.count() > 0) {
|
|
await confirmButton.click();
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
}
|
|
|
|
// 3. 等待上课页面加载
|
|
await page.waitForTimeout(3000);
|
|
|
|
// 4. 切换到下一个环节(触发进度保存)
|
|
const nextButton = page.locator('button:has-text("下一")').or(page.locator('button:has-text("下一步")'));
|
|
let progressSaved = false;
|
|
|
|
if (await nextButton.count() > 0) {
|
|
await nextButton.first().click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 检查是否有进度保存提示
|
|
const saveMessage = page.locator('text=保存').or(page.locator('[class*="progress"]'));
|
|
progressSaved = await saveMessage.count() > 0;
|
|
}
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: progressSaved ? '检测到进度保存' : '未检测到明显的进度保存提示',
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-auto-save.png' });
|
|
});
|
|
|
|
test('测试2: 进度恢复功能', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课记录
|
|
await page.click('text=上课记录');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 查找有进度的课程记录
|
|
const recordItems = page.locator('[class*="record"], [class*="lesson"], [class*="item"]');
|
|
const recordCount = await recordItems.count();
|
|
|
|
if (recordCount > 0) {
|
|
// 3. 点击第一个记录
|
|
await recordItems.first().click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 4. 检查是否显示进度恢复提示
|
|
const resumeMessage = page.locator('text=继续').or(page.locator('text=恢复')).or(page.locator('text=上次'));
|
|
const hasResumeMessage = await resumeMessage.count() > 0;
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: hasResumeMessage ? '显示进度恢复提示' : '未显示进度恢复提示',
|
|
});
|
|
|
|
// 5. 如果有恢复按钮,点击继续
|
|
const resumeButton = page.locator('button:has-text("继续上课")').or(page.locator('button:has-text("继续")'));
|
|
if (await resumeButton.count() > 0) {
|
|
await resumeButton.first().click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
test.info().annotations.push({
|
|
type: 'success',
|
|
description: '点击继续上课按钮',
|
|
});
|
|
}
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'warning',
|
|
description: '未找到上课记录',
|
|
});
|
|
}
|
|
|
|
await page.screenshot({ path: 'test-results/progress-resume.png' });
|
|
});
|
|
|
|
test('测试3: 进度条显示', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课模式
|
|
await page.click('text=上课记录');
|
|
await page.waitForTimeout(2000);
|
|
|
|
const recordItems = page.locator('[class*="record"], [class*="lesson"]');
|
|
if (await recordItems.count() > 0) {
|
|
await recordItems.first().click();
|
|
await page.waitForTimeout(2000);
|
|
} else {
|
|
await page.click('text=课程中心');
|
|
await page.waitForTimeout(1000);
|
|
|
|
const firstCourseCard = page.locator('.course-card').or(page.locator('[class*="course-card"]')).first();
|
|
await firstCourseCard.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const selectLessonsButton = page.locator('button:has-text("选择课程上课")');
|
|
if (await selectLessonsButton.count() > 0) {
|
|
await selectLessonsButton.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const confirmButton = page.locator('button:has-text("确定")');
|
|
if (await confirmButton.count() > 0) {
|
|
await confirmButton.click();
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. 查找进度条元素
|
|
const progressBar = page.locator('[class*="progress"], .ant-progress');
|
|
const progressCount = await progressBar.count();
|
|
|
|
// 3. 查找步骤指示器
|
|
const stepIndicator = page.locator('[class*="step"], .ant-steps');
|
|
const stepCount = await stepIndicator.count();
|
|
|
|
// 4. 查找当前环节标记
|
|
const currentStep = page.locator('[class*="current"], .ant-steps-item-active');
|
|
const currentCount = await currentStep.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `进度条: ${progressCount}, 步骤指示: ${stepCount}, 当前环节: ${currentCount}`,
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-bar.png' });
|
|
});
|
|
|
|
test('测试4: 课程列表进度显示', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课记录
|
|
await page.click('text=上课记录');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 查找课程列表中的进度标记
|
|
const progressMarkers = page.locator('[class*="progress"], [class*="status"]');
|
|
const markerCount = await progressMarkers.count();
|
|
|
|
// 3. 检查是否有完成状态标记
|
|
const completedMarkers = page.locator('text=已完成').or(page.locator('text=完成')).or(page.locator('[class*="done"]'));
|
|
const completedCount = await completedMarkers.count();
|
|
|
|
// 4. 检查是否有进行中标记
|
|
const inProgressMarkers = page.locator('text=进行中').or(page.locator('text=上课中')).or(page.locator('[class*="ing"]'));
|
|
const inProgressCount = await inProgressMarkers.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `进度标记: ${markerCount}, 已完成: ${completedCount}, 进行中: ${inProgressCount}`,
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-list.png' });
|
|
});
|
|
|
|
test('测试5: 环节完成状态追踪', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课模式
|
|
await page.click('text=课程中心');
|
|
await page.waitForURL('**/courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
const firstCourseCard = page.locator('.course-card').or(page.locator('[class*="course-card"]')).first();
|
|
await firstCourseCard.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const selectLessonsButton = page.locator('button:has-text("选择课程上课")');
|
|
if (await selectLessonsButton.count() > 0) {
|
|
await selectLessonsButton.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const confirmButton = page.locator('button:has-text("确定")');
|
|
if (await confirmButton.count() > 0) {
|
|
await confirmButton.click();
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
}
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 查找步骤指示器
|
|
const steps = page.locator('.ant-steps-item, [class*="step"]');
|
|
const stepCount = await steps.count();
|
|
|
|
// 3. 检查已完成步骤的样式
|
|
const completedSteps = page.locator('.ant-steps-item-finish, [class*="completed"], [class*="done"]');
|
|
const completedCount = await completedSteps.count();
|
|
|
|
// 4. 检查当前进行中的步骤
|
|
const activeSteps = page.locator('.ant-steps-item-active, [class*="current"], [class*="active"]');
|
|
const activeCount = await activeSteps.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `总步骤: ${stepCount}, 已完成: ${completedCount}, 进行中: ${activeCount}`,
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-steps.png' });
|
|
});
|
|
|
|
test('测试6: 进度统计展示', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入首页或统计页面
|
|
await page.click('text=首页');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 查找统计卡片
|
|
const statCards = page.locator('[class*="stat"], [class*="card"]');
|
|
const statCount = await statCards.count();
|
|
|
|
// 3. 查找课程相关统计
|
|
const courseStats = page.locator('text=课程').or(page.locator('text=授课')).or(page.locator('text=上课'));
|
|
const courseStatCount = await courseStats.count();
|
|
|
|
// 4. 查找进度百分比
|
|
const percentage = page.locator('[class*="percent"]');
|
|
const percentCount = await percentage.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `统计卡片: ${statCount}, 课程统计: ${courseStatCount}, 进度百分比: ${percentCount}`,
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-stats.png' });
|
|
});
|
|
|
|
test('测试7: 进度重置功能', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课记录
|
|
await page.click('text=上课记录');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 选择一个有进度的记录
|
|
const recordItems = page.locator('[class*="record"], [class*="lesson"]');
|
|
if (await recordItems.count() > 0) {
|
|
await recordItems.first().click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 3. 查找重置进度按钮
|
|
const resetButton = page.locator('button:has-text("重置")').or(page.locator('button:has-text("重新开始")'));
|
|
const hasResetButton = await resetButton.count() > 0;
|
|
|
|
if (hasResetButton) {
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: '找到重置进度按钮',
|
|
});
|
|
|
|
// 注意:不实际点击,避免影响数据
|
|
} else {
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: '未找到重置进度按钮',
|
|
});
|
|
}
|
|
}
|
|
|
|
await page.screenshot({ path: 'test-results/progress-reset.png' });
|
|
});
|
|
|
|
test('测试8: 多课程进度管理', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入首页
|
|
await page.click('text=首页');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 查找正在进行的课程列表
|
|
const ongoingLessons = page.locator('[class*="ongoing"], [class*="current"]');
|
|
const ongoingCount = await ongoingLessons.count();
|
|
|
|
// 3. 查找今日课程
|
|
const todayLessons = page.locator('text=今日').or(page.locator('[class*="today"]'));
|
|
const todayCount = await todayLessons.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `进行中课程: ${ongoingCount}, 今日课程: ${todayCount}`,
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-multi.png' });
|
|
});
|
|
|
|
test('测试9: 进度历史记录', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课记录页面
|
|
await page.click('text=上课记录');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 查找日期分组或历史记录标记
|
|
const dateGroups = page.locator('[class*="date"], [class*="group"]');
|
|
const dateCount = await dateGroups.count();
|
|
|
|
// 3. 查找历史记录列表
|
|
const historyList = page.locator('[class*="list"], [class*="history"]');
|
|
const historyCount = await historyList.count();
|
|
|
|
// 4. 检查是否有筛选或排序功能
|
|
const filterControls = page.locator('[class*="filter"], .ant-select');
|
|
const filterCount = await filterControls.count();
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: `日期分组: ${dateCount}, 历史列表: ${historyCount}, 筛选控件: ${filterCount}`,
|
|
});
|
|
|
|
await page.screenshot({ path: 'test-results/progress-history.png' });
|
|
});
|
|
|
|
test('测试10: 进度数据持久化', async ({ page }) => {
|
|
test.slow();
|
|
|
|
// 1. 进入上课模式并记录进度
|
|
await page.click('text=课程中心');
|
|
await page.waitForURL('**/courses', { timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
const firstCourseCard = page.locator('.course-card').or(page.locator('[class*="course-card"]')).first();
|
|
await firstCourseCard.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const selectLessonsButton = page.locator('button:has-text("选择课程上课")');
|
|
if (await selectLessonsButton.count() > 0) {
|
|
await selectLessonsButton.click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
const confirmButton = page.locator('button:has-text("确定")');
|
|
if (await confirmButton.count() > 0) {
|
|
await confirmButton.click();
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
}
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 2. 切换环节触发进度保存
|
|
const nextButton = page.locator('button:has-text("下一")').or(page.locator('button:has-text("下一步")'));
|
|
if (await nextButton.count() > 0) {
|
|
await nextButton.first().click();
|
|
await page.waitForTimeout(2000);
|
|
}
|
|
|
|
// 3. 返回列表页
|
|
await page.click('text=上课记录');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 4. 重新进入同一个课程
|
|
const recordItems = page.locator('[class*="record"], [class*="lesson"]');
|
|
if (await recordItems.count() > 0) {
|
|
const firstRecordText = await recordItems.first().textContent();
|
|
await recordItems.first().click();
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 5. 验证进度是否恢复
|
|
const currentStep = page.locator('[class*="current"], .ant-steps-item-active');
|
|
const hasProgress = await currentStep.count() > 0;
|
|
|
|
test.info().annotations.push({
|
|
type: 'info',
|
|
description: hasProgress ? '进度已恢复' : '未检测到进度恢复',
|
|
});
|
|
}
|
|
|
|
await page.screenshot({ path: 'test-results/progress-persistence.png' });
|
|
});
|
|
});
|