fix(department): comprehensive debug logging for CI department test failure

Add JWT payload inspection, networkidle wait, and full localStorage snapshot
to diagnose why loadMyDepartments fails to set CurrentDepartmentId on CI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-02 21:48:54 +08:00
parent 08659f28ce
commit 39f22ca0da
+44 -16
View File
@@ -64,39 +64,67 @@ async function loginAndDismissSelectors(page: any) {
test.describe('单部门透明', () => {
test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONIDSecret 或 .env.e2e');
function decodeJwtPayloadCompact(token: string): Record<string, unknown> {
const parts = token.split('.');
if (parts.length < 2) return {};
const raw = parts[1].replace(/-/g, '+').replace(/_/g, '/');
const padded = raw.padEnd(Math.ceil(raw.length / 4) * 4, '=');
const decoded = decodeURIComponent(
atob(padded)
.split('')
.map(c => `%${(`00${c.charCodeAt(0).toString(16)}`).slice(-2)}`)
.join('')
);
return JSON.parse(decoded);
}
test('自动选中默认部门,不出现部门选择 UI', async ({ page }) => {
test.setTimeout(120_000);
test.setTimeout(180_000);
await loginAndDismissSelectors(page);
// 检查登录后的 JWT
const loginJwt = await page.evaluate(() => window.localStorage.getItem('Authorization'));
if (loginJwt) {
const payload = decodeJwtPayloadCompact(loginJwt);
let sub: Record<string, unknown> = {};
if (typeof payload.sub === 'string') sub = JSON.parse(payload.sub);
console.log('[DeptTest JWT before] top-level keys:', Object.keys(payload));
console.log('[DeptTest JWT before] payload.current_org_id:', payload.current_org_id);
console.log('[DeptTest JWT before] sub.current_org_id:', (sub as any).current_org_id);
console.log('[DeptTest JWT before] sub.current_department_id:', (sub as any).current_department_id);
}
// 导航到排课页触发路由守卫中的 org 加载 + 部门自动选中
await page.goto('/clazz', {
waitUntil: 'domcontentloaded',
timeout: 60_000,
waitUntil: 'networkidle',
timeout: 90_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
// 打印当前页面状态
console.log('[DeptTest] path before', await page.evaluate(() => window.location.pathname));
console.log('[DeptTest] has HtySudoToken:', await page.evaluate(() => !!window.localStorage.getItem('HtySudoerToken')));
console.log('[DeptTest] has CurrentOrgId:', await page.evaluate(() => window.localStorage.getItem('CurrentOrgId')));
// 等待异步的部门加载完成
await page.waitForTimeout(3_000);
const pageState = await page.evaluate(() => {
const ls = (k: string) => window.localStorage.getItem(k);
return {
pathname: window.location.pathname,
CurrentOrgId: ls('CurrentOrgId'),
CurrentDepartmentId: ls('CurrentDepartmentId'),
hasAuth: !!ls('Authorization'),
hasSudo: !!ls('HtySudoerToken'),
guardError: ls('__guardError'),
orgSwitchDebug: ls('OrgSwitchDebug'),
};
});
console.log('[DeptTest] state after goto:', JSON.stringify(pageState, null, 2));
// 验证 localStorage 写入了 CurrentDepartmentId
const deptId = await page.evaluate(() =>
window.localStorage.getItem('CurrentDepartmentId')
);
const pathnameAfter = await page.evaluate(() => window.location.pathname);
console.log('[DeptTest] path after wait:', pathnameAfter);
console.log('[DeptTest] CurrentDepartmentId:', deptId);
const deptId = pageState.CurrentDepartmentId;
expect(deptId).toBeTruthy();
expect(deptId).toContain('dept_default_');
// 验证页面路径不包含 department 相关参数
expect(pathnameAfter).not.toContain('department');
expect(pageState.pathname).not.toContain('department');
// 验证 token 中包含 department_id
const authToken = await page.evaluate(() =>