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' }); }); });