test(course-package): add music-room frontend UI tests for course-package

Verify: nav link from summary page, list page with tabs/search/add button,
and form fields on add page.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-30 13:58:44 +08:00
parent 3cf0d2901b
commit 524c27c278
+157
View File
@@ -257,3 +257,160 @@ test.describe('课包(course_package', () => {
await expect(page.getByText('声乐基础训练')).toBeVisible({ timeout: 10_000 }); await expect(page.getByText('声乐基础训练')).toBeVisible({ timeout: 10_000 });
}); });
}); });
test.describe('音乐教室端(huike-front)课包 UI', () => {
test.describe.configure({ timeout: 180_000 });
test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONIDSecret 或 .env.e2e');
test('教学资源库导航:课包入口可见,列表页加载种子数据', async ({ page }) => {
// 登录音乐教室前端
const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' });
await page.goto(`/?${q.toString()}`, {
waitUntil: 'domcontentloaded',
timeout: 60_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
// 等待登录 redirect 完成(status=2 消失)
await page.waitForFunction(
() => !window.location.search.includes('status=2'),
{ timeout: 90_000 },
);
// 角色选择(Vant 风格网格,仅多角色时出现)
if (await page.getByText('请选择您的登录身份').isVisible().catch(() => false)) {
await page.locator('.van-grid-item').first().click();
// 选择后可能 reload
await page.waitForFunction(
() => !window.location.search.includes('status=2'),
{ timeout: 30_000 },
);
}
// 导航到教学资源库
await page.goto('/course/summary', {
waitUntil: 'domcontentloaded',
timeout: 60_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
// 如果是多机构用户,可能进入机构选择页
if (page.url().includes('/org/select')) {
const cell = page.locator('.van-cell-group .van-cell').first();
await expect(cell).toBeVisible({ timeout: 30_000 });
await cell.click();
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
}
// 验证"课包"入口链接
const coursePkgLink = page.locator('.van-cell').filter({ hasText: '课包' });
await expect(coursePkgLink).toBeVisible({ timeout: 10_000 });
// 点击进入课包列表
await coursePkgLink.click();
await expect(page.locator('#app')).toBeVisible({ timeout: 30_000 });
// 应该导航到 /course/course-package
await expect(page).toHaveURL(/\/course\/course-package/);
// 验证列表渲染种子数据
await expect(page.getByText('钢琴一对一课程')).toBeVisible({ timeout: 30_000 });
await expect(page.getByText('声乐基础训练')).toBeVisible({ timeout: 10_000 });
});
test('课包列表页:Tab 切换、搜索框、新增按钮可见', async ({ page }) => {
// 登录并解析机构上下文
const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' });
await page.goto(`/?${q.toString()}`, {
waitUntil: 'domcontentloaded',
timeout: 60_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForFunction(
() => !window.location.search.includes('status=2'),
{ timeout: 90_000 },
);
if (await page.getByText('请选择您的登录身份').isVisible().catch(() => false)) {
await page.locator('.van-grid-item').first().click();
await page.waitForFunction(
() => !window.location.search.includes('status=2'),
{ timeout: 30_000 },
);
}
// 直接导航到课包列表页(resolveOrgContextForCoursePage 会处理机构选择)
const { resolveOrgContextForCoursePage } = await import('./helpers/music-room-session');
await resolveOrgContextForCoursePage(page);
// 导航到课包列表
await page.goto('/course/course-package', {
waitUntil: 'domcontentloaded',
timeout: 60_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 30_000 });
// 验证搜索框
await expect(page.locator('.van-search')).toBeVisible({ timeout: 10_000 });
// 验证 Tab 切换
const myTab = page.locator('.van-tab').filter({ hasText: '我的课包' });
await expect(myTab).toBeVisible({ timeout: 10_000 });
const orgTab = page.locator('.van-tab').filter({ hasText: '机构课包' });
await expect(orgTab).toBeVisible({ timeout: 10_000 });
// 验证新增按钮
await expect(page.locator('.btn-add')).toBeVisible({ timeout: 10_000 });
// 默认 Tab 是我的课包,应有种子数据
await expect(page.getByText('钢琴一对一课程')).toBeVisible({ timeout: 30_000 });
// 切换到机构课包 Tab
await orgTab.click();
await expect(page.getByText('钢琴一对一课程')).toBeVisible({ timeout: 30_000 });
});
test('课包新增页面:表单字段完整,可提交', async ({ page }) => {
// 登录
const q = new URLSearchParams({ unionid: moicenUnionid!, status: '2' });
await page.goto(`/?${q.toString()}`, {
waitUntil: 'domcontentloaded',
timeout: 60_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
await page.waitForFunction(
() => !window.location.search.includes('status=2'),
{ timeout: 90_000 },
);
if (await page.getByText('请选择您的登录身份').isVisible().catch(() => false)) {
await page.locator('.van-grid-item').first().click();
await page.waitForFunction(
() => !window.location.search.includes('status=2'),
{ timeout: 30_000 },
);
}
// 处理机构选择
const { resolveOrgContextForCoursePage } = await import('./helpers/music-room-session');
await resolveOrgContextForCoursePage(page);
// 导航到新增页
await page.goto('/course/course-package/add', {
waitUntil: 'domcontentloaded',
timeout: 60_000,
});
await expect(page.locator('#app')).toBeVisible({ timeout: 30_000 });
// 验证表单字段存在
await expect(page.locator('input[name="package_name"]')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('textarea[name="description"]')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('input[name="total_lessons"]')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('input[name="original_price"]')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('input[name="selling_price"]')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('input[name="validity_days"]')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('input[name="sort_order"]')).toBeVisible({ timeout: 10_000 });
// 验证提交按钮
await expect(page.getByText('保存')).toBeVisible({ timeout: 10_000 });
});
});