From 39f22ca0da6fa59c409f1ce407376f9d2d0f8a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E7=94=B7?= Date: Sat, 2 May 2026 21:48:54 +0800 Subject: [PATCH] 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 --- tests/department-single-transparent.spec.ts | 60 +++++++++++++++------ 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/tests/department-single-transparent.spec.ts b/tests/department-single-transparent.spec.ts index 5b65661..7b26f41 100644 --- a/tests/department-single-transparent.spec.ts +++ b/tests/department-single-transparent.spec.ts @@ -64,39 +64,67 @@ async function loginAndDismissSelectors(page: any) { test.describe('单部门透明', () => { test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONID(Secret 或 .env.e2e)'); + function decodeJwtPayloadCompact(token: string): Record { + 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 = {}; + 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(() =>