import { expect, test } from './fixtures'; const moicenUnionid = process.env.MOICEN_E2E_UNIONID?.trim(); test.skip(!moicenUnionid, 'MOICEN_E2E_UNIONID 未设置'); /** * 角色选择器在 action-sheet 中的索引: * ["测试员","学生","教师","管理员","主管教师"] */ const ROLE_TEACHER = 2; const ROLE_SUPERVISOR = 4; const SUBSIDIARY_TEACHER_NAME = '周晓慧'; test.describe('主管老师矩阵视图', () => { async function loginAsTeacher(page: any) { const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' }); await page.goto(`/?${q.toString()}`, { waitUntil: 'domcontentloaded', timeout: 120_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(ROLE_TEACHER).click(); } else { await items.first().click(); } await page.waitForTimeout(3000); } catch { // No role dialog — proceed with default role } } async function switchToRole(page: any, roleIndex: number): Promise { const roleSwitcher = page.locator('.van-icon-exchange'); try { await roleSwitcher.waitFor({ state: 'visible', timeout: 15_000 }); } catch { return false; } await roleSwitcher.click(); await page.locator('.van-action-sheet').waitFor({ state: 'visible', timeout: 10_000 }); await page.waitForTimeout(1500); const roleBtn = page.locator('.van-action-sheet__item').nth(roleIndex); await expect(roleBtn).toBeVisible(); await roleBtn.click(); await page.waitForTimeout(2000); // Wait for role switch confirm dialog if visible const confirmDialog = page.locator('.van-dialog__confirm'); try { await confirmDialog.waitFor({ state: 'visible', timeout: 5000 }); await confirmDialog.click(); await page.waitForTimeout(3000); } catch { // No confirm dialog needed } // Wait for role switch to take effect await page.waitForTimeout(3000); return true; } async function switchToMatrixView(page: any) { const matrixBtn = page.locator('.view-toolbar button', { hasText: '矩阵' }); await expect(matrixBtn).toBeVisible({ timeout: 10_000 }); await matrixBtn.click(); await page.waitForTimeout(1500); await expect(page.locator('.matrix-container')).toBeVisible({ timeout: 10_000 }); } test('教师角色下矩阵视图不显示下属老师(周晓慧)的课程', async ({ page }) => { test.setTimeout(120_000); 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 switchToMatrixView(page); // Collect all teacher names from event blocks const teacherNames = await page.evaluate(() => { return Array.from(document.querySelectorAll('.ev-teacher')) .map(el => el.textContent?.trim()) .filter(Boolean); }); // In TEACHER role, 周晓慧's courses should NOT appear const hasZhouXiaohui = teacherNames.includes(SUBSIDIARY_TEACHER_NAME); expect(hasZhouXiaohui).toBe(false); // footer-subsidiary should not exist in TEACHER role const footerSubsidiary = page.locator('.footer-subsidiary'); await expect(footerSubsidiary).not.toBeVisible(); }); test('切换到主管老师角色后矩阵视图显示周晓慧的课程(不同颜色)', async ({ page }) => { test.setTimeout(120_000); await loginAsTeacher(page); // Go to TEACHER profile to open role switcher await page.goto('/teacher/profile', { waitUntil: 'domcontentloaded', timeout: 60_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); await page.waitForTimeout(3000); // Switch to SUPERVISOR role const switched = await switchToRole(page, ROLE_SUPERVISOR); if (!switched) { test.skip(true, '当前用户无多角色切换能力'); return; } // Navigate to clazz page await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); await page.waitForTimeout(5000); // Wait for subsidiary data to load await page.waitForTimeout(3000); // Verify subsidiary teacher tags in footer const footerSubsidiary = page.locator('.footer-subsidiary'); await expect(footerSubsidiary).toBeVisible({ timeout: 15_000 }); const tagCount = await footerSubsidiary.locator('.van-tag').count(); expect(tagCount).toBeGreaterThanOrEqual(1); // Verify 周晓慧 tag is present const zhouTag = footerSubsidiary.locator('.van-tag', { hasText: SUBSIDIARY_TEACHER_NAME }); await expect(zhouTag).toBeVisible(); // Switch to matrix view await switchToMatrixView(page); // Verify 周晓慧's courses appear in matrix view (data-dependent — skip if no courses this week) const teacherNames = await page.evaluate(() => { return Array.from(document.querySelectorAll('.ev-teacher')) .map(el => el.textContent?.trim()) .filter(Boolean); }); if (teacherNames.length === 0) { test.skip(true, '排课数据为空'); return; } if (!teacherNames.includes(SUBSIDIARY_TEACHER_NAME)) { test.skip(true, '本周无周晓慧的排课数据'); return; } // Verify different courses have different background colors (own vs subsidiary) const teacherColorMap = await page.evaluate(() => { const map: Record = {}; document.querySelectorAll('.event-block').forEach(block => { const teacher = block.querySelector('.ev-teacher')?.textContent?.trim(); const bgColor = getComputedStyle(block).backgroundColor; if (teacher && bgColor && teacher !== '未设置老师') { map[teacher] = map[teacher] || bgColor; } }); return map; }); const colorSet = new Set(Object.values(teacherColorMap)); expect(colorSet.size).toBeGreaterThanOrEqual(2); }); test('从主管老师切回教师角色后周晓慧的课程消失', async ({ page }) => { test.setTimeout(180_000); await loginAsTeacher(page); // Switch to SUPERVISOR first await page.goto('/teacher/profile', { waitUntil: 'domcontentloaded', timeout: 60_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); await page.waitForTimeout(3000); const switched = await switchToRole(page, ROLE_SUPERVISOR); if (!switched) { test.skip(true, '当前用户无多角色切换能力'); return; } await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); await page.waitForTimeout(5000); const footerSubsidiary = page.locator('.footer-subsidiary'); await expect(footerSubsidiary).toBeVisible({ timeout: 15_000 }); // Switch back to TEACHER via supervisor profile await page.goto('/supervisor/profile', { waitUntil: 'domcontentloaded', timeout: 60_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); await page.waitForTimeout(3000); const switched2 = await switchToRole(page, ROLE_TEACHER); if (!switched2) { test.skip(true, '切换回教师角色失败(无多角色能力)'); return; } await page.goto('/clazz', { waitUntil: 'domcontentloaded', timeout: 60_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); await page.waitForTimeout(5000); await expect(footerSubsidiary).not.toBeVisible(); // 周晓慧's name should not appear in event blocks const teacherNames = await page.evaluate(() => { return Array.from(document.querySelectorAll('.ev-teacher')) .map(el => el.textContent?.trim()) .filter(Boolean); }); expect(teacherNames).not.toContain(SUBSIDIARY_TEACHER_NAME); }); });