diff --git a/tests/supervisor-features.spec.ts b/tests/supervisor-features.spec.ts new file mode 100644 index 0000000..104e3f8 --- /dev/null +++ b/tests/supervisor-features.spec.ts @@ -0,0 +1,111 @@ +import { expect, test } from './fixtures'; + +const moicenUnionid = process.env.MOICEN_E2E_UNIONID?.trim(); + +/** + * 登录并选择指定角色(支持多角色用户场景) + */ +async function loginAndSelectRole(page: any, roleText: string) { + 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 }); + + // 等待 auth tokens + await expect(async () => { + const auth = await page.evaluate(() => + window.localStorage.getItem('Authorization') + ); + expect(auth).toBeTruthy(); + }).toPass({ timeout: 30_000 }); + + // 逐层处理选择页:机构选择 → 身份选择(可能有 0~n 层) + let roleSelected = false; + for (let i = 0; i < 5 && !roleSelected; i++) { + const path = await page.evaluate(() => window.location.pathname); + + if (path === '/org/select') { + await page.locator('.van-cell').first().click(); + await page.waitForTimeout(3_000); + } else if (path === '/') { + const rs = page.getByText('请选择您的登录身份'); + try { + await rs.waitFor({ state: 'visible', timeout: 10_000 }); + await page.locator('.van-grid-item').filter({ hasText: roleText }).click(); + await page.waitForTimeout(3_000); + roleSelected = true; + } catch { + // 无角色选择器 → 角色已自动选中 + break; + } + } else { + // 已在目标页面 + break; + } + } +} + +test.describe('主管老师 功能验证', () => { + test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONID(Secret 或 .env.e2e)'); + + test('SUPERVISOR 登录后首页为本机构工作台 /teacher/home', async ({ page }) => { + await loginAndSelectRole(page, '主管教师'); + + // 主管教师与教师共享首页,不跳到"我的下属老师" + const path = await page.evaluate(() => window.location.pathname); + expect(path).toBe('/teacher/home'); + + // 页面应正常渲染(无 JS 崩溃) + await expect(page.locator('#app')).toBeVisible({ timeout: 15_000 }); + }); + + test('打卡页面加载无服务器错误', async ({ page }) => { + // 收集请求失败 + const failedRequests: string[] = []; + page.on('requestfailed', (req) => { + failedRequests.push(`${req.method()} ${req.url()} ${req.failure()?.errorText ?? ''}`); + }); + + await loginAndSelectRole(page, '主管教师'); + + // 导航到打卡页 + await page.goto('/daka', { waitUntil: 'networkidle', timeout: 60_000 }); + await expect(page.locator('#app')).toBeVisible({ timeout: 15_000 }); + + // 不应有服务器内部错误 + const serverErrors = failedRequests.filter( + r => r.includes('500') || r.includes('Internal Server Error') + ); + expect(serverErrors).toEqual([]); + + // 打卡页应显示日期选择器 + await expect(page.getByText('打卡起始')).toBeVisible({ timeout: 15_000 }); + }); + + test('vConsole 可见性取决于 SYS_CAN_SUDO tag', async ({ page }) => { + await loginAndSelectRole(page, '主管教师'); + + // 等待 tags 异步加载 + vConsole 渲染 + await page.waitForTimeout(5_000); + + const state = await page.evaluate(() => { + const el = document.getElementById('__vconsole'); + return { exists: !!el, hidden: el?.hidden ?? null }; + }); + + // 检测用户是否有 SYS_CAN_SUDO tag + const hasSudoTag = await page.evaluate(() => { + return !!window.localStorage.getItem('HtySudoerToken'); + }); + + console.log('[vConsole] state:', JSON.stringify(state), 'hasSudoTag:', hasSudoTag); + + if (hasSudoTag) { + expect(state.exists).toBeTruthy(); + expect(state.hidden).toBeFalsy(); + } + // 无 tag 时仅验证页面正常,不做 vConsole 断言 + }); +});