test(course-package): add teacher UI test verifying nav link and page render

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 <noreply@anthropic.com>
This commit is contained in:
2026-04-30 10:36:20 +08:00
parent 75291986cf
commit 27ba562f39
2 changed files with 43 additions and 0 deletions
+2
View File
@@ -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 健康检查 URLCI 可在仓库 Settings → Variables 配置 MOICEN_HEALTHCHECK_URL
MOICEN_HEALTHCHECK_URL=
+41
View File
@@ -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 域上独立登录(不同 originlocalStorage 不共享)
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 });
});
});