From 27ba562f391afa7324ba9c69502e2ea8738f06ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E7=94=B7?= Date: Thu, 30 Apr 2026 10:36:20 +0800 Subject: [PATCH] test(course-package): add teacher UI test verifying nav link and page render MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Navigate to teacher.moicen.com, verify "课包" nav link is visible for teacher/supervisor, click through to /course-packages, assert seeded data renders. Catches frontend build/deploy regressions. Co-Authored-By: Claude Opus 4.7 --- .env.e2e.example | 2 ++ tests/course-package.spec.ts | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/.env.e2e.example b/.env.e2e.example index b98d881..948b4ae 100644 --- a/.env.e2e.example +++ b/.env.e2e.example @@ -9,6 +9,8 @@ MOICEN_ADMIN_PASSWORD= # 课包(course_package)测试依赖 MOICEN_E2E_UNIONID(共用 teacher/student unionid) # 测试通过 JWT roles 验证只有 TEACHER/SUPERVISOR 角色可访问课包 API。 +# 教师端 UI 测试需要教师应用基址(默认 https://teacher.moicen.com) +HTYTEACHER_BASE_URL=https://teacher.moicen.com # 可选:任意 HTTP 200 健康检查 URL(CI 可在仓库 Settings → Variables 配置 MOICEN_HEALTHCHECK_URL) MOICEN_HEALTHCHECK_URL= diff --git a/tests/course-package.spec.ts b/tests/course-package.spec.ts index fd68656..d252b57 100644 --- a/tests/course-package.spec.ts +++ b/tests/course-package.spec.ts @@ -4,6 +4,8 @@ import { decodeJwtPayload } from './helpers/music-room-session'; const moicenUnionid = process.env.MOICEN_E2E_UNIONID?.trim(); const kcBase = process.env.HUIKE_ADMIN_BASE_URL?.trim() || 'https://admin.moicen.com'; +const teacherBase = + process.env.HTYTEACHER_BASE_URL?.trim() || 'https://teacher.moicen.com'; /** * 从 JWT payload 中提取 role_key 字符串数组(可能嵌在 `sub` JSON 字段内)。 @@ -210,4 +212,43 @@ test.describe('课包(course_package)', () => { expect(typeof orgBody.d?.[1] === 'number').toBe(true); expect(typeof orgBody.d?.[2] === 'number').toBe(true); }); + + test('教师端 UI:导航栏出现"课包"入口,页面加载种子数据', async ({ + page, + }) => { + // 在 teacher.moicen.com 域上独立登录(不同 origin,localStorage 不共享) + const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' }); + await page.goto(`${teacherBase}/?${q.toString()}`, { + waitUntil: 'domcontentloaded', + timeout: 60_000, + }); + await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 }); + if ( + await page.getByText('请选择您的登录身份').isVisible().catch(() => false) + ) { + await page.locator('.van-grid-item').first().click(); + } + await expect( + page.getByText(/请选择您的登录身份|欢迎回来|进入工作台/), + ).toBeVisible({ timeout: 120_000 }); + + if ( + await page.getByText('请返回微信小程序完成登录').isVisible().catch(() => false) + ) { + test.skip(true, '当前 unionid 会话未处于可用登录态'); + } + + // 导航栏出现"课包"入口(仅 TEACHER / SUPERVISOR 可见) + const navLink = page.locator('nav a').filter({ hasText: '课包' }); + await expect(navLink).toBeVisible({ timeout: 30_000 }); + + // 点击"课包"进入课包管理页 + await navLink.click(); + await page.waitForURL('**/course-packages', { timeout: 30_000 }); + await expect(page.locator('#app')).toBeVisible({ timeout: 30_000 }); + + // 页面应渲染课包列表(含预置种子数据) + await expect(page.getByText('钢琴一对一课程')).toBeVisible({ timeout: 30_000 }); + await expect(page.getByText('声乐基础训练')).toBeVisible({ timeout: 10_000 }); + }); });