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 }) => { // 1. 进入课程中心 await page.click('text=课程中心'); await page.waitForURL('**/courses', { timeout: 10000 }); await page.waitForTimeout(1000); // 2. 选择第一个课程 const firstCourseCard = page.locator('.course-card').or(page.locator('[class*="course-card"]')).first(); await firstCourseCard.click(); await page.waitForTimeout(2000); // 3. 点击开始备课 const prepareButton = page.locator('button:has-text("开始备课")'); await prepareButton.click(); // 4. 验证跳转 await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 5. 验证备课模式结构 await expect(page.locator('aside, [class*="navigation"], [class*="sidebar"]').first()).toBeVisible(); await expect(page.locator('[class*="preview"], [class*="content"]').first()).toBeVisible(); test.info().annotations.push({ type: 'success', description: '成功进入备课模式', }); await page.screenshot({ path: 'test-results/prepare-mode-layout.png' }); }); test('测试2: 左侧导航 - 课程包概览', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 点击课程包概览 const overviewNav = page.locator('text=课程包概览').or(page.locator('[class*="overview"]')); if (await overviewNav.count() > 0) { await overviewNav.first().click(); await page.waitForTimeout(1000); } // 2. 验证基本信息展示 const basicInfo = page.locator('[class*="basic"], [class*="info"]'); if (await basicInfo.count() > 0) { await expect(basicInfo.first()).toBeVisible(); } // 3. 验证统计数据 const stats = page.locator('[class*="stat"], [class*="count"]'); const statCount = await stats.count(); test.info().annotations.push({ type: 'info', description: `统计项数量: ${statCount}`, }); await page.screenshot({ path: 'test-results/prepare-overview.png' }); }); test('测试3: 左侧导航 - 包含课程', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 点击包含课程 const lessonsNav = page.locator('text=包含课程').or(page.locator('[class*="lessons"]')); if (await lessonsNav.count() > 0) { await lessonsNav.first().click(); await page.waitForTimeout(1000); } // 2. 验证课程列表 const lessonList = page.locator('[class*="lesson"], [class*="course-item"]'); const lessonCount = await lessonList.count(); test.info().annotations.push({ type: 'info', description: `课程数量: ${lessonCount}`, }); expect(lessonCount).toBeGreaterThan(0); // 3. 点击第一个课程 if (lessonCount > 0) { await lessonList.first().click(); await page.waitForTimeout(1000); } await page.screenshot({ path: 'test-results/prepare-lessons.png' }); }); test('测试4: 右侧内容预览 - 课程介绍', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 点击课程介绍Tab const introTab = page.locator('text=课程介绍').or(page.locator('[class*="intro"]')); if (await introTab.count() > 0) { await introTab.first().click(); await page.waitForTimeout(1000); } // 2. 验证介绍内容展示 const introContent = page.locator('[class*="intro"], [class*="content"]'); expect(await introContent.count()).toBeGreaterThan(0); // 3. 验证8个介绍字段 const introFields = ['简介', '亮点', '目标', '安排', '重难点', '方法', '评价', '注意事项']; let visibleFieldCount = 0; for (const field of introFields) { const fieldLocator = page.locator(`text=${field}`); if (await fieldLocator.count() > 0) { visibleFieldCount++; } } test.info().annotations.push({ type: 'info', description: `介绍字段: ${visibleFieldCount}/${introFields.length}`, }); await page.screenshot({ path: 'test-results/prepare-intro-content.png', fullPage: true }); }); test('测试5: 右侧内容预览 - 排课参考', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 点击排课参考Tab const scheduleTab = page.locator('text=排课参考').or(page.locator('[class*="schedule"]')); if (await scheduleTab.count() > 0) { await scheduleTab.first().click(); await page.waitForTimeout(1000); } // 2. 验证排课表格或内容 const scheduleTable = page.locator('table').or(page.locator('[class*="table"]')); const scheduleContent = page.locator('[class*="schedule-content"]'); const hasTable = await scheduleTable.count() > 0; const hasContent = await scheduleContent.count() > 0; test.info().annotations.push({ type: 'info', description: hasTable ? '显示排课表格' : (hasContent ? '显示排课内容' : '未找到排课参考'), }); await page.screenshot({ path: 'test-results/prepare-schedule.png' }); }); test('测试6: 右侧内容预览 - 环创建设', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 点击环创建设Tab const envTab = page.locator('text=环创建设').or(page.locator('[class*="environment"]')); if (await envTab.count() > 0) { await envTab.first().click(); await page.waitForTimeout(1000); } // 2. 验证环创建设内容 const envContent = page.locator('text=主题环境').or(page.locator('text=区域活动')).or(page.locator('[class*="environment"]')); const hasContent = await envContent.count() > 0; test.info().annotations.push({ type: 'info', description: hasContent ? '显示环创建设内容' : '未找到环创建设', }); await page.screenshot({ path: 'test-results/prepare-environment.png' }); }); test('测试7: 教学目标展示', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 选择导入课 const introLesson = page.locator('text=导入课').or(page.locator('[class*="introduction"]')); if (await introLesson.count() > 0) { await introLesson.first().click(); await page.waitForTimeout(1000); } // 2. 验证教学目标展示 const objectives = page.locator('text=教学目标').or(page.locator('[class*="objective"]')); if (await objectives.count() > 0) { await expect(objectives.first()).toBeVisible(); } // 3. 验证教学准备展示 const preparation = page.locator('text=教学准备').or(page.locator('[class*="preparation"]')); if (await preparation.count() > 0) { await expect(preparation.first()).toBeVisible(); } await page.screenshot({ path: 'test-results/prepare-objectives.png' }); }); test('测试8: 教学过程展示', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 选择导入课 const introLesson = page.locator('text=导入课').or(page.locator('[class*="introduction"]')); if (await introLesson.count() > 0) { await introLesson.first().click(); await page.waitForTimeout(1000); } // 2. 验证教学过程展示 const process = page.locator('text=教学过程').or(page.locator('[class*="process"], [class*="steps"]')); if (await process.count() > 0) { await expect(process.first()).toBeVisible(); } // 3. 验证环节列表 const steps = page.locator('[class*="step"], [class*="stage"]'); const stepCount = await steps.count(); test.info().annotations.push({ type: 'info', description: `教学环节数量: ${stepCount}`, }); // 4. 展开第一个环节查看详情 if (stepCount > 0) { await steps.first().click(); await page.waitForTimeout(500); } await page.screenshot({ path: 'test-results/prepare-process.png', fullPage: true }); }); test('测试9: 核心资源展示', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 选择导入课 const introLesson = page.locator('text=导入课').or(page.locator('[class*="introduction"]')); if (await introLesson.count() > 0) { await introLesson.first().click(); await page.waitForTimeout(1000); } // 2. 验证核心资源展示 const resources = page.locator('text=核心资源').or(page.locator('[class*="resource"]')); const resourceCount = await resources.count(); test.info().annotations.push({ type: 'info', description: resourceCount > 0 ? `找到 ${resourceCount} 个资源区域` : '未找到核心资源区域', }); // 3. 验证资源类型(视频、PPT、PDF等) const resourceTypes = ['视频', 'PPT', 'PDF', '音频', '图片']; const foundTypes: string[] = []; for (const type of resourceTypes) { const typeLocator = page.locator(`text=${type}`); if (await typeLocator.count() > 0) { foundTypes.push(type); } } test.info().annotations.push({ type: 'info', description: `资源类型: ${foundTypes.join(', ') || '无'}`, }); await page.screenshot({ path: 'test-results/prepare-resources.png' }); }); test('测试10: 教学延伸和反思', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 选择导入课 const introLesson = page.locator('text=导入课').or(page.locator('[class*="introduction"]')); if (await introLesson.count() > 0) { await introLesson.first().click(); await page.waitForTimeout(1000); } // 2. 验证教学延伸 const extension = page.locator('text=教学延伸').or(page.locator('[class*="extension"]')); if (await extension.count() > 0) { await expect(extension.first()).toBeVisible(); } // 3. 验证教学反思 const reflection = page.locator('text=教学反思').or(page.locator('[class*="reflection"]')); if (await reflection.count() > 0) { await expect(reflection.first()).toBeVisible(); } await page.screenshot({ path: 'test-results/prepare-extension.png' }); }); test('测试11: 备课笔记功能', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 点击备课笔记Tab const notesTab = page.locator('text=备课笔记').or(page.locator('[class*="notes"]')); if (await notesTab.count() > 0) { await notesTab.first().click(); await page.waitForTimeout(1000); } // 2. 验证笔记编辑器 const editor = page.locator('[contenteditable="true"], .ant-input, textarea'); const hasEditor = await editor.count() > 0; if (hasEditor) { // 3. 尝试输入笔记内容 await editor.first().fill('这是测试笔记内容'); 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/prepare-notes.png' }); }); test('测试12: 从备课模式进入上课', async ({ page }) => { test.slow(); // 进入备课模式 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); await page.click('button:has-text("开始备课")'); await page.waitForURL('**/prepare', { timeout: 10000 }); await page.waitForTimeout(2000); // 1. 查找开始上课按钮 const startClassButton = page.locator('button:has-text("开始上课")').or(page.locator('button:has-text("进入上课")')); const buttonExists = await startClassButton.count() > 0; if (buttonExists) { await startClassButton.first().click(); await page.waitForTimeout(2000); // 2. 验证跳转到上课模式或课程选择弹窗 const url = page.url(); test.info().annotations.push({ type: 'info', description: `点击后URL: ${url}`, }); // 3. 如果显示课程选择弹窗,选择所有课程 const selectModal = page.locator('[class*="modal"], [class*="select"]'); if (await selectModal.count() > 0) { const confirmButton = page.locator('button:has-text("确定")').or(page.locator('button:has-text("开始上课")')); if (await confirmButton.count() > 0) { await confirmButton.first().click(); await page.waitForTimeout(2000); } } } else { test.info().annotations.push({ type: 'warning', description: '未找到"开始上课"按钮', }); } await page.screenshot({ path: 'test-results/prepare-to-class.png' }); }); });