2026-04-28 11:53:48 +08:00
|
|
|
|
import { expect, test } from './fixtures';
|
|
|
|
|
|
import {
|
|
|
|
|
|
decodeJwtPayload,
|
|
|
|
|
|
establishSession,
|
|
|
|
|
|
extractOrgIdFromTokenPayload,
|
|
|
|
|
|
resolveOrgContextForCoursePage,
|
|
|
|
|
|
waitForCourseRealmVisible,
|
|
|
|
|
|
} from './helpers/music-room-session';
|
|
|
|
|
|
|
|
|
|
|
|
const moicenUnionid = process.env.MOICEN_E2E_UNIONID?.trim();
|
|
|
|
|
|
|
|
|
|
|
|
/** 可选:仓库 Variables `MOICEN_HEALTHCHECK_URL`(如 `https://api.example/health`),未配置则 skip */
|
|
|
|
|
|
const moicenHealthcheckUrl = process.env.MOICEN_HEALTHCHECK_URL?.trim();
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('核心全链路(访客)', () => {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* `main.ts`:未带 Registered 链时访问非 `/`、`/guest/*` 会 replace 到 `/`,最终应呈现访客占位。
|
|
|
|
|
|
*/
|
|
|
|
|
|
test('未登录深链 /course 最终回到访客首页', async ({ page }) => {
|
|
|
|
|
|
await page.goto('/course', {
|
|
|
|
|
|
waitUntil: 'domcontentloaded',
|
|
|
|
|
|
timeout: 60_000,
|
|
|
|
|
|
});
|
|
|
|
|
|
await expect(page.locator('#app')).toBeVisible({ timeout: 60_000 });
|
|
|
|
|
|
await page.waitForURL((u) => new URL(u).pathname === '/', {
|
|
|
|
|
|
timeout: 60_000,
|
|
|
|
|
|
});
|
2026-05-01 10:37:48 +08:00
|
|
|
|
// Guest home now shows the course package store instead of login prompt
|
|
|
|
|
|
await expect(page.locator('.course-package-store')).toBeVisible({ timeout: 60_000 });
|
2026-04-28 11:53:48 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('核心全链路(已登录 → 教学资源)', () => {
|
|
|
|
|
|
test.describe.configure({ timeout: 180_000 });
|
|
|
|
|
|
|
|
|
|
|
|
test.skip(!moicenUnionid, '需要 MOICEN_E2E_UNIONID(Secret 或 .env.e2e)');
|
|
|
|
|
|
|
|
|
|
|
|
test('黄金路径:会话建立 → 深链进入课程体系壳层 → JWT 与 CurrentOrgId 闭环', async ({
|
|
|
|
|
|
page,
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
await establishSession(page, moicenUnionid!);
|
|
|
|
|
|
if (
|
|
|
|
|
|
await page.getByText('请返回微信小程序完成登录').isVisible().catch(() => false)
|
|
|
|
|
|
) {
|
|
|
|
|
|
test.skip(true, '当前 unionid 会话未处于可用登录态');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await resolveOrgContextForCoursePage(page);
|
|
|
|
|
|
|
|
|
|
|
|
const storage = await page.evaluate(() => ({
|
|
|
|
|
|
currentOrgId: window.localStorage.getItem('CurrentOrgId'),
|
|
|
|
|
|
authorization: window.localStorage.getItem('Authorization'),
|
|
|
|
|
|
}));
|
|
|
|
|
|
expect(storage.authorization, '登录深链后应有 Authorization').toBeTruthy();
|
|
|
|
|
|
|
|
|
|
|
|
const payload = decodeJwtPayload(storage.authorization!);
|
|
|
|
|
|
expect(payload).not.toBeNull();
|
|
|
|
|
|
const jwtOrgId = extractOrgIdFromTokenPayload(payload);
|
|
|
|
|
|
expect(jwtOrgId).toBeTruthy();
|
|
|
|
|
|
if (storage.currentOrgId) {
|
|
|
|
|
|
expect(storage.currentOrgId).toBe(jwtOrgId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await page.goto('/course', {
|
|
|
|
|
|
waitUntil: 'domcontentloaded',
|
|
|
|
|
|
timeout: 90_000,
|
|
|
|
|
|
});
|
|
|
|
|
|
await expect(page.locator('#app')).toBeVisible({ timeout: 90_000 });
|
|
|
|
|
|
await waitForCourseRealmVisible(page);
|
|
|
|
|
|
|
|
|
|
|
|
await expect(page.getByText('请求失败,点击重新加载')).toHaveCount(0, {
|
|
|
|
|
|
timeout: 45_000,
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('可选:MOICEN_HEALTHCHECK_URL 可达', async ({ request }) => {
|
|
|
|
|
|
test.skip(!moicenHealthcheckUrl, '未配置 MOICEN_HEALTHCHECK_URL(仓库 Variables)');
|
|
|
|
|
|
const res = await request.get(moicenHealthcheckUrl!);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
res.ok(),
|
|
|
|
|
|
`HTTP ${res.status()} ${res.statusText()} ${moicenHealthcheckUrl}`
|
|
|
|
|
|
).toBeTruthy();
|
|
|
|
|
|
});
|