kindergarten_java/reading-platform-frontend/tests/e2e/schedule/schedule-comprehensive.spec.ts

354 lines
12 KiB
TypeScript
Raw Normal View History

import { test, expect, Page } from '@playwright/test';
/**
*
* Tab导航4
*/
const BASE_URL = 'http://localhost:5174';
const LOGIN_CREDS = {
username: 'school1',
password: '123456'
};
test.describe('学校端排课功能测试', () => {
let page: Page;
let authToken: string;
test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
// 登录获取 token
const loginResponse = await page.request.post(`${BASE_URL}/api/v1/auth/login`, {
data: {
username: LOGIN_CREDS.username,
password: LOGIN_CREDS.password
}
});
const loginData = await loginResponse.json();
expect(loginData.code).toBe(200);
authToken = loginData.data.token;
// 设置 localStorage
await page.goto(BASE_URL);
await page.evaluate(([token, user]) => {
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
}, [authToken, loginData.data]);
});
test.afterAll(async () => {
await page.close();
});
test.describe('Tab 导航切换', () => {
test('应该能访问排课页面', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 验证页面标题
const title = await page.textContent('.page-header h2, h1');
expect(title).toContain('课程排期');
});
test('应该显示三个Tab导航', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 验证Tab存在
const tabs = await page.locator('a[role="tab"], .ant-tabs-tab').all();
expect(tabs.length).toBeGreaterThanOrEqual(3);
const tabTexts = await Promise.all(tabs.map(tab => tab.textContent()));
console.log('✅ 找到Tab:', tabTexts);
});
test('应该能切换到列表视图', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 点击列表视图Tab
const listTab = page.locator('a[role="tab"], .ant-tabs-tab').filter({ hasText: '列表' }).first();
await listTab.click();
await page.waitForTimeout(500);
// 验证列表视图内容
const table = page.locator('.ant-table');
await expect(table.first()).toBeVisible();
});
test('应该能切换到课表视图', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 点击课表视图Tab
const timetableTab = page.locator('a[role="tab"], .ant-tabs-tab').filter({ hasText: '课表' }).first();
await timetableTab.click();
await page.waitForTimeout(500);
// 验证课表视图内容
const timetableHeader = page.locator('.timetable-header, .day-header');
await expect(timetableHeader.first()).toBeVisible();
});
test('应该能切换到日历视图', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 点击日历视图Tab
const calendarTab = page.locator('a[role="tab"], .ant-tabs-tab').filter({ hasText: '日历' }).first();
await calendarTab.click();
await page.waitForTimeout(500);
// 验证日历视图内容
const calendarView = page.locator('.ant-picker-calendar');
await expect(calendarView.first()).toBeVisible();
});
});
test.describe('列表视图功能', () => {
test('应该显示排课列表数据', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 确保在列表视图
const listTab = page.locator('a[role="tab"], .ant-tabs-tab').filter({ hasText: '列表' }).first();
await listTab.click();
await page.waitForTimeout(1000);
// 检查表格是否存在
const table = page.locator('.ant-table');
await expect(table.first()).toBeVisible();
// 尝试获取排课数据
const rows = await table.locator('.ant-table-tbody tr').all();
console.log(`✅ 列表视图找到 ${rows.length} 行数据`);
});
test('应该有筛选功能', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 检查筛选器
const classSelect = page.locator('select[placeholder*="班级"], .ant-select').first();
const teacherSelect = page.locator('.filter-section .ant-select').nth(1);
// 筛选器可能存在,记录日志
const hasClassFilter = await classSelect.count() > 0;
const hasTeacherFilter = await teacherSelect.count() > 0;
console.log(`✅ 班级筛选: ${hasClassFilter ? '存在' : '不存在'}`);
console.log(`✅ 教师筛选: ${hasTeacherFilter ? '存在' : '不存在'}`);
});
});
test.describe('课表视图功能', () => {
test('应该显示周次导航', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 切换到课表视图
const timetableTab = page.locator('a[role="tab"], .ant-tabs-tab').filter({ hasText: '课表' }).first();
await timetableTab.click();
await page.waitForTimeout(1000);
// 检查周次导航按钮
const prevWeekBtn = page.locator('button:has-text("上一周")');
const nextWeekBtn = page.locator('button:has-text("下一周")');
const currentWeekBtn = page.locator('button:has-text("本周")');
const hasPrevBtn = await prevWeekBtn.count() > 0;
const hasNextBtn = await nextWeekBtn.count() > 0;
const hasCurrentBtn = await currentWeekBtn.count() > 0;
console.log(`✅ 上一周按钮: ${hasPrevBtn ? '存在' : '不存在'}`);
console.log(`✅ 下一周按钮: ${hasNextBtn ? '存在' : '不存在'}`);
console.log(`✅ 本周按钮: ${hasCurrentBtn ? '存在' : '不存在'}`);
});
test('应该显示周一到周日的列', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
const timetableTab = page.locator('a[role="tab"], .ant-tabs-tab').filter({ hasText: '课表' }).first();
await timetableTab.click();
await page.waitForTimeout(1000);
// 检查周次显示
const dayHeaders = page.locator('.day-header, .timetable-header > div');
const count = await dayHeaders.count();
console.log(`✅ 找到 ${count} 个日期列`);
});
});
test.describe('新建排课功能', () => {
test('应该能打开新建排课弹窗', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 点击新建排课按钮
const createBtn = page.locator('button:has-text("新建排课")');
const btnCount = await createBtn.count();
if (btnCount > 0) {
await createBtn.first().click();
await page.waitForTimeout(1000);
// 检查弹窗是否打开
const modal = page.locator('.ant-modal').filter({ hasText: /新建|创建|排课/ });
const isVisible = await modal.isVisible();
console.log(`✅ 新建排课弹窗: ${isVisible ? '已打开' : '未打开'}`);
} else {
console.log('⚠️ 未找到新建排课按钮');
}
});
test('步骤1应该能选择课程套餐', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 打开新建排课弹窗
const createBtn = page.locator('button:has-text("新建排课")');
if (await createBtn.count() > 0) {
await createBtn.first().click();
await page.waitForTimeout(1000);
// 检查课程套餐下拉框
const collectionSelect = page.locator('.ant-modal .ant-select').first();
const hasSelect = await collectionSelect.count() > 0;
console.log(`✅ 课程套餐选择器: ${hasSelect ? '存在' : '不存在'}`);
}
});
test('步骤3应该支持为每个班级分配教师', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
// 打开新建排课弹窗
const createBtn = page.locator('button:has-text("新建排课")');
if (await createBtn.count() > 0) {
await createBtn.first().click();
await page.waitForTimeout(1000);
// 尝试找到教师分配相关元素
const teacherLabel = page.locator('.ant-modal label:has-text("教师")');
const count = await teacherLabel.count();
console.log(`✅ 教师分配相关元素: 找到 ${count}`);
}
});
});
test.describe('API 后端测试', () => {
test('应该能获取课程套餐列表', async () => {
const response = await page.request.get(`${BASE_URL}/api/v1/school/packages`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.code).toBe(200);
console.log(`✅ 获取课程套餐列表成功:`, data.data ? JSON.stringify(data.data).substring(0, 100) + '...' : '无数据');
});
test('应该能获取课表数据', async () => {
const today = new Date().toISOString().split('T')[0];
const startDate = today;
const endDate = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const response = await page.request.get(`${BASE_URL}/api/v1/school/schedules/timetable?startDate=${startDate}&endDate=${endDate}`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.code).toBe(200);
console.log(`✅ 获取课表数据成功:`, data.data ? '有数据' : '无数据');
});
test('应该能获取排课列表', async () => {
const response = await page.request.get(`${BASE_URL}/api/v1/school/schedules?pageNum=1&pageSize=10`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.code).toBe(200);
if (data.data && data.data.list) {
console.log(`✅ 获取排课列表成功: ${data.data.list.length} 条记录`);
} else {
console.log(`✅ 获取排课列表成功: 无数据`);
}
});
test('应该能获取班级列表', async () => {
const response = await page.request.get(`${BASE_URL}/api/v1/school/classes`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.code).toBe(200);
console.log(`✅ 获取班级列表成功:`, Array.isArray(data.data) ? `${data.data.length} 个班级` : '数据格式正确');
});
test('应该能获取教师列表', async () => {
const response = await page.request.get(`${BASE_URL}/api/v1/school/teachers?pageNum=1&pageSize=50`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.code).toBe(200);
if (data.data && data.data.list) {
console.log(`✅ 获取教师列表成功: ${data.data.list.length} 位教师`);
}
});
});
test.describe('创建排课时序测试E2E', () => {
test('完整流程测试:从登录到创建排课', async () => {
// 已登录,直接跳转到排课页面
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
console.log('📍 当前页面:', page.url());
console.log('✅ 成功访问排课页面');
});
test('截图:当前排课页面状态', async () => {
await page.goto(`${BASE_URL}/school/schedule`);
await page.waitForLoadState('networkidle');
await page.waitForTimeout(2000);
// 截图
await page.screenshot({
path: 'screenshots/schedule-page-current.png',
fullPage: true
});
console.log('✅ 已保存截图: screenshots/schedule-page-current.png');
});
});
});