런타임 계약과 학습자 흐름 보강

This commit is contained in:
Yun Chan 2026-06-29 08:12:14 +09:00
parent f456b8997a
commit 206018b088
56 changed files with 4306 additions and 1008 deletions

View file

@ -110,6 +110,44 @@ test.describe("learner app shell and session launcher", () => {
expect(await page.evaluate(() => window.localStorage.getItem("vignette.dev-auth"))).toBeNull();
});
test("redirects to login when a protected learner API returns 401 after boot", async ({ page }) => {
await page.route("**/api/auth/me", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
user_id: "stale-learner",
email: "stale.learner@hs.ac.kr",
display_name: "Stale Learner",
role: "learner",
admin_access: false,
super_admin: false,
account_status: "approved",
approval_required: false,
cohort_ids: [],
consent_at: 1,
onboarding_completed_at: 1,
nickname: "Stale Learner",
self_introduction: "",
avatar_url: "",
}),
});
});
await page.route(/\/api\/(personas|sessions(?:\/dashboard)?)$/, async (route) => {
await route.fulfill({
status: 401,
contentType: "application/json",
body: JSON.stringify({ detail: "not authenticated" }),
});
});
await page.goto("/learn/practice");
await expect(page).toHaveURL(/\/login$/);
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
await expect(page.getByText("내담자 목록을 불러오지 못했습니다.")).toHaveCount(0);
});
test("renders API personas without legacy session rows", async ({ page }) => {
await signInAsLearnerEmail(page, `learner.catalog.${Date.now()}@hs.ac.kr`, "Catalog Learner");
await page.goto("/learn/practice");