From 527c0849426832924aab0b22af059a94b12b66e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E7=94=B7?= Date: Thu, 30 Apr 2026 10:50:44 +0800 Subject: [PATCH] fix(course-package): inject JWT cookie for teacher app UI test teacher.moicen.com Nginx has no AuthCore middleware, so ?unionid= login doesn't work there. Login on music-room first, extract JWT, then inject HtyTeacherToken/CurrentUserRole cookies + localStorage on teacher domain before navigating to /course-packages. Co-Authored-By: Claude Opus 4.7 --- tests/course-package.spec.ts | 59 +++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/tests/course-package.spec.ts b/tests/course-package.spec.ts index d252b57..9ea94cd 100644 --- a/tests/course-package.spec.ts +++ b/tests/course-package.spec.ts @@ -216,9 +216,17 @@ test.describe('课包(course_package)', () => { test('教师端 UI:导航栏出现"课包"入口,页面加载种子数据', async ({ page, }) => { - // 在 teacher.moicen.com 域上独立登录(不同 origin,localStorage 不共享) + // teacher.moicen.com 无 AuthCore 中间件,不支持 ?unionid= 登录; + // 先在 music-room 域名登录获取 JWT,再注入 teacher 域名的 cookie+localStorage。 + await page.goto(`${teacherBase}/`, { + waitUntil: 'domcontentloaded', + timeout: 60_000, + }); + await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); + + // Step 1: 在 music-room 域登录以获取 JWT const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' }); - await page.goto(`${teacherBase}/?${q.toString()}`, { + await page.goto(`/?${q.toString()}`, { waitUntil: 'domcontentloaded', timeout: 60_000, }); @@ -238,16 +246,57 @@ test.describe('课包(course_package)', () => { test.skip(true, '当前 unionid 会话未处于可用登录态'); } - // 导航栏出现"课包"入口(仅 TEACHER / SUPERVISOR 可见) + // Step 2: 从 music-room 提取 auth 数据 + const jwt = await page.evaluate(() => + window.localStorage.getItem('Authorization'), + ); + expect(jwt, '应有 JWT').toBeTruthy(); + + const currentRole = await page.evaluate(() => + window.localStorage.getItem('CurrentUserRole'), + ); + const currentOrgId = await page.evaluate(() => + window.localStorage.getItem('CurrentOrgId'), + ); + const currentUserName = await page.evaluate(() => + window.localStorage.getItem('CurrentUserName'), + ); + + // Step 3: 跳转到 teacher 域名,注入 cookie + localStorage + await page.goto(`${teacherBase}/`, { + waitUntil: 'domcontentloaded', + timeout: 60_000, + }); + + const teacherHost = new URL(teacherBase).hostname; + await page.context().addCookies([ + { name: 'HtyTeacherToken', value: jwt!, domain: teacherHost, path: '/' }, + { name: 'CurrentUserRole', value: currentRole || 'TEACHER', domain: teacherHost, path: '/' }, + { name: 'CurrentUserName', value: currentUserName || '', domain: teacherHost, path: '/' }, + ]); + await page.evaluate( + ({ orgId }) => { + if (orgId) window.localStorage.setItem('CurrentOrgId', orgId); + }, + { orgId: currentOrgId }, + ); + + // Step 4: 刷新页面,教师端应识别已登录态 + await page.reload({ waitUntil: 'domcontentloaded', timeout: 60_000 }); + await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); + + // Step 5: 等待导航栏渲染,检查"课包"入口(仅 TEACHER / SUPERVISOR 可见) + // 首次加载可能要等 useUser() 异步 fetch 完成 + await page.waitForTimeout(5000); const navLink = page.locator('nav a').filter({ hasText: '课包' }); await expect(navLink).toBeVisible({ timeout: 30_000 }); - // 点击"课包"进入课包管理页 + // Step 6: 点击进入课包管理页 await navLink.click(); await page.waitForURL('**/course-packages', { timeout: 30_000 }); await expect(page.locator('#app')).toBeVisible({ timeout: 30_000 }); - // 页面应渲染课包列表(含预置种子数据) + // Step 7: 页面应渲染课包列表(含预置种子数据) await expect(page.getByText('钢琴一对一课程')).toBeVisible({ timeout: 30_000 }); await expect(page.getByText('声乐基础训练')).toBeVisible({ timeout: 10_000 }); });