Files
huike-e2e-moicen/tests/clazz-dual-view.spec.ts
T
weli de2e258043 test: add regression tests for dual-view week alignment and data loading
- Verify matrix week starts on Monday (same as calendar)
- Verify data loads correctly after switching views multiple times

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 08:54:33 +08:00

272 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { expect, test } from './fixtures';
const moicenUnionid = process.env.MOICEN_E2E_UNIONID?.trim();
test.skip(!moicenUnionid, 'MOICEN_E2E_UNIONID 未设置');
async function loginAsTeacher(page: any) {
const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' });
await page.goto(`/?${q.toString()}`, { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
// Wait up to 15s for role selection dialog (may not appear if already logged in)
const rs = page.getByText('请选择您的登录身份');
try {
await rs.waitFor({ state: 'visible', timeout: 15_000 });
const items = page.locator('.van-grid-item');
const count = await items.count();
if (count >= 3) {
await items.nth(2).click(); // TEACHER role
} else {
await items.first().click();
}
await page.waitForTimeout(3000);
} catch {
// No role dialog — proceed with default role
}
}
test.describe('排课双视图切换(阿难账号)', () => {
test('教师端排课页显示视图切换按钮', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// Check toggle buttons exist
const toggleBar = page.locator('.view-toolbar');
await expect(toggleBar).toBeVisible({ timeout: 10_000 });
const calBtn = toggleBar.locator('button', { hasText: '日历' });
const matrixBtn = toggleBar.locator('button', { hasText: '矩阵' });
await expect(calBtn).toBeVisible();
await expect(matrixBtn).toBeVisible();
// Default is calendar — 日历 should be primary
await expect(calBtn).toHaveClass(/van-button--primary/);
});
test('切换到矩阵视图后显示时段列和日期行', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// Switch to matrix view
const matrixBtn = page.locator('.view-toolbar button', { hasText: '矩阵' });
await matrixBtn.click();
await page.waitForTimeout(1500);
// Matrix container should be visible
const matrixContainer = page.locator('.matrix-container');
await expect(matrixContainer).toBeVisible({ timeout: 10_000 });
// Header should show time slot labels (第一节 ~ 第四节)
const headerCells = page.locator('.header-cell');
await expect(headerCells.first()).toBeVisible();
const count = await headerCells.count();
await expect(count).toBeGreaterThanOrEqual(4);
// Each header cell should have slot label + time
const firstHeader = headerCells.first();
await expect(firstHeader.locator('.header-label')).toBeVisible();
await expect(firstHeader.locator('.header-time')).toBeVisible();
// Day sidebar should show weekday labels (周一 ~ 周日)
const dayCells = page.locator('.sidebar-row');
await expect(dayCells.first()).toBeVisible();
expect(await dayCells.count()).toBe(7);
// Each day cell should have day name + date
const firstDay = dayCells.first();
await expect(firstDay.locator('.day-name')).toBeVisible();
await expect(firstDay.locator('.day-date')).toBeVisible();
});
test('矩阵视图导航栏可操作(上一周/本周/下一周)', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// Switch to matrix
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
// Nav buttons should exist
const nav = page.locator('.view-toolbar__nav');
await expect(nav).toBeVisible({ timeout: 10_000 });
// Click "本周" to reset to current week
await nav.locator('button', { hasText: '本周' }).click();
await page.waitForTimeout(2000);
// Should show date range
const range = page.locator('.view-toolbar__range');
await expect(range).toBeVisible();
});
test('矩阵视图课块显示课程名、老师、学生信息', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// Switch to matrix
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
// Check event blocks exist in the grid
const eventBlocks = page.locator('.event-block');
const count = await eventBlocks.count();
if (count === 0) {
test.skip(true, '无排课数据');
return;
}
// First block should show course name
const first = eventBlocks.first();
await expect(first.locator('.ev-title')).toBeVisible();
// At least one block should have teacher name
const hasTeacher = await page.locator('.ev-teacher').count();
expect(hasTeacher).toBeGreaterThanOrEqual(0);
// At least one block should have student names
const hasStudents = await page.locator('.ev-students').count();
expect(hasStudents).toBeGreaterThanOrEqual(0);
});
test('矩阵视图同一时段多节课横向排列', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// Switch to matrix
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
// Find a cell with 2+ event blocks and verify it uses flex row
const isHorizontal = await page.evaluate(() => {
const cells = document.querySelectorAll('.event-cell');
for (const cell of cells) {
const blocks = cell.querySelectorAll('.event-block');
if (blocks.length >= 2) {
const style = window.getComputedStyle(cell);
return style.display === 'flex' && style.flexDirection === 'row';
}
}
return false;
});
if (!isHorizontal) {
const hasMulti = await page.evaluate(() => {
const cells = document.querySelectorAll('.event-cell');
return Array.from(cells).some(c => c.querySelectorAll('.event-block').length >= 2);
});
if (!hasMulti) {
test.skip(true, '无同一时段多节课数据');
return;
}
}
expect(isHorizontal).toBe(true);
});
test('从矩阵视图切换回日历视图后日历正常显示', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// Switch to matrix
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
await expect(page.locator('.matrix-container')).toBeVisible({ timeout: 10_000 });
// Switch back to calendar
await page.locator('.view-toolbar button', { hasText: '日历' }).click();
await page.waitForTimeout(1500);
// Calendar (FullCalendar) should be visible
await expect(page.locator('.fc')).toBeVisible({ timeout: 10_000 });
});
test('日历与矩阵视图起始日一致(周一)', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// 切换到矩阵
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
await expect(page.locator('.matrix-container')).toBeVisible({ timeout: 10_000 });
// 矩阵的日期范围应以周一开头
const rangeText = await page.locator('.view-toolbar__range').textContent();
expect(rangeText).toBeTruthy();
const startDate = rangeText?.split('~')[0]?.trim();
expect(startDate).toBeTruthy();
if (startDate) {
const day = new Date(startDate).getDay();
expect(day).toBe(1); // Monday = 1
}
});
test('来回切换视图后数据仍正常加载', async ({ page }) => {
await loginAsTeacher(page);
await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 });
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(3000);
// 日历应有事件
await expect(page.locator('.fc-event').first()).toBeVisible({ timeout: 10_000 });
// 切换到矩阵
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
await expect(page.locator('.matrix-container')).toBeVisible({ timeout: 10_000 });
// 矩阵应有事件
const matrixFirst = await page.locator('.event-block').count();
// 切回日历
await page.locator('.view-toolbar button', { hasText: '日历' }).click();
await page.waitForTimeout(1500);
await expect(page.locator('.fc')).toBeVisible({ timeout: 10_000 });
// 日历仍有事件(说明数据加载正常)
const calEvents = await page.locator('.fc-event').count();
expect(calEvents).toBeGreaterThan(0);
// 再次切到矩阵
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
await expect(page.locator('.matrix-container')).toBeVisible({ timeout: 10_000 });
// 矩阵仍有事件
const matrixSecond = await page.locator('.event-block').count();
expect(matrixSecond).toBeGreaterThanOrEqual(0);
// 导航到下一周再回来
await page.locator('.view-toolbar__nav button', { hasText: '' }).click();
await page.waitForTimeout(2000);
// 切回日历
await page.locator('.view-toolbar button', { hasText: '日历' }).click();
await page.waitForTimeout(1500);
// 再切回矩阵,回到本周
await page.locator('.view-toolbar button', { hasText: '矩阵' }).click();
await page.waitForTimeout(1500);
await page.locator('.view-toolbar__nav button', { hasText: '本周' }).click();
await page.waitForTimeout(2000);
// 回到本周后应有事件
const currentWeekEvents = await page.locator('.event-block').count();
expect(currentWeekEvents).toBeGreaterThanOrEqual(0);
});
});