diff --git a/tests/course-package.spec.ts b/tests/course-package.spec.ts index c3337ca..9c85ffc 100644 --- a/tests/course-package.spec.ts +++ b/tests/course-package.spec.ts @@ -257,3 +257,160 @@ test.describe('课包(course_package)', () => { await expect(page.getByText('声乐基础训练')).toBeVisible({ timeout: 10_000 }); }); }); + +test.describe('音乐教室端(huike-front)课包 UI', () => { + test.describe.configure({ timeout: 180_000 }); + + test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONID(Secret 或 .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 }); + }); +});