케이스 이어하기 UI와 공통 탭·이미지 복구를 반영

This commit is contained in:
Yun Chan 2026-09-01 11:45:23 +09:00
parent 72353ecd82
commit f1b80676c1
38 changed files with 3581 additions and 455 deletions

View file

@ -141,6 +141,14 @@ async function mountSettingsFixtures(
await routeUnmockedApi(page);
await page.route("**/api/static/avatars/*.png", (route) =>
route.fulfill({
status: 200,
contentType: "image/png",
body: Buffer.from(PNG_1X1_BASE64, "base64"),
}),
);
await page.route("**/api/auth/me", (route) =>
route.fulfill(
jsonRoute({
@ -471,6 +479,44 @@ test.describe("설정·동의 관리 유스케이스", () => {
await expect(account.locator(".vg-set__saved")).toHaveCount(0);
});
// usecase: DB에 남은 아바타 경로의 실제 파일이 사라져 404여도 깨진 이미지 아이콘 대신 이니셜을 유지한다
test("아바타 파일 404 시 톱바와 설정 미리보기 모두 이니셜 폴백을 유지한다", async ({ page }) => {
const staleAvatar = "/uploads/profile-avatars/stale-avatar.jpg";
await mountSettingsFixtures(page, { avatarUrl: staleAvatar });
await page.route("**/api/uploads/profile-avatars/stale-avatar.jpg", (route) =>
route.fulfill(jsonRoute({ detail: "Not Found" }, 404)),
);
await openLoadedSettings(page);
const avatarFrames = page.locator(
".vg-topbar__avatar, .vg-set__rail-avatar, .vg-set__avatar",
);
await expect(avatarFrames).toHaveCount(3);
for (const frame of await avatarFrames.all()) {
await expect(frame.locator("[data-image-fallback='failed']")).toHaveText("설");
await expect(frame.locator("img")).toHaveCount(0);
}
});
// usecase: 저장값이 웹 이미지가 아닌 scheme이면 요청하지 않고 즉시 안전한 이니셜 상태로 닫힌다
test("빈 URL과 비웹 scheme은 네트워크 요청 없이 이니셜 폴백으로 정규화한다", async ({ page }) => {
let unsafeRequestCount = 0;
page.on("request", (request) => {
if (/javascript:|data:|file:/i.test(request.url())) unsafeRequestCount += 1;
});
await mountSettingsFixtures(page, { avatarUrl: " javascript:alert(1) " });
await openLoadedSettings(page);
const avatarFrames = page.locator(
".vg-topbar__avatar, .vg-set__rail-avatar, .vg-set__avatar",
);
for (const frame of await avatarFrames.all()) {
await expect(frame.locator("[data-image-fallback='empty']")).toHaveText("설");
await expect(frame.locator("img")).toHaveCount(0);
}
expect(unsafeRequestCount).toBe(0);
});
// usecase: 학습자가 표시 이름을 빈값으로 저장 시도했다가 서버 거절을 받는다
test("표시 이름을 빈값으로 저장하면 거짓 저장됨 표시 없이 입력 상태가 유지된다", async ({
page,