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:
@@ -64,39 +64,67 @@ async function loginAndDismissSelectors(page: any) {
|
|||||||
test.describe('单部门透明', () => {
|
test.describe('单部门透明', () => {
|
||||||
test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONID(Secret 或 .env.e2e)');
|
test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONID(Secret 或 .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('自动选中默认部门,不出现部门选择 UI', async ({ page }) => {
|
||||||
test.setTimeout(120_000);
|
test.setTimeout(180_000);
|
||||||
|
|
||||||
await loginAndDismissSelectors(page);
|
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 加载 + 部门自动选中
|
// 导航到排课页触发路由守卫中的 org 加载 + 部门自动选中
|
||||||
await page.goto('/clazz', {
|
await page.goto('/clazz', {
|
||||||
waitUntil: 'domcontentloaded',
|
waitUntil: 'networkidle',
|
||||||
timeout: 60_000,
|
timeout: 90_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
|
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
|
||||||
|
|
||||||
// 打印当前页面状态
|
// 打印当前页面状态
|
||||||
console.log('[DeptTest] path before', await page.evaluate(() => window.location.pathname));
|
const pageState = await page.evaluate(() => {
|
||||||
console.log('[DeptTest] has HtySudoToken:', await page.evaluate(() => !!window.localStorage.getItem('HtySudoerToken')));
|
const ls = (k: string) => window.localStorage.getItem(k);
|
||||||
console.log('[DeptTest] has CurrentOrgId:', await page.evaluate(() => window.localStorage.getItem('CurrentOrgId')));
|
return {
|
||||||
|
pathname: window.location.pathname,
|
||||||
// 等待异步的部门加载完成
|
CurrentOrgId: ls('CurrentOrgId'),
|
||||||
await page.waitForTimeout(3_000);
|
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
|
// 验证 localStorage 写入了 CurrentDepartmentId
|
||||||
const deptId = await page.evaluate(() =>
|
const deptId = pageState.CurrentDepartmentId;
|
||||||
window.localStorage.getItem('CurrentDepartmentId')
|
|
||||||
);
|
|
||||||
const pathnameAfter = await page.evaluate(() => window.location.pathname);
|
|
||||||
console.log('[DeptTest] path after wait:', pathnameAfter);
|
|
||||||
console.log('[DeptTest] CurrentDepartmentId:', deptId);
|
|
||||||
expect(deptId).toBeTruthy();
|
expect(deptId).toBeTruthy();
|
||||||
expect(deptId).toContain('dept_default_');
|
expect(deptId).toContain('dept_default_');
|
||||||
|
|
||||||
// 验证页面路径不包含 department 相关参数
|
// 验证页面路径不包含 department 相关参数
|
||||||
expect(pathnameAfter).not.toContain('department');
|
expect(pageState.pathname).not.toContain('department');
|
||||||
|
|
||||||
// 验证 token 中包含 department_id
|
// 验证 token 中包含 department_id
|
||||||
const authToken = await page.evaluate(() =>
|
const authToken = await page.evaluate(() =>
|
||||||
|
|||||||
Reference in New Issue
Block a user