import { expect, test } from "@playwright/test"; import type { Page } from "@playwright/test"; import { apiBaseUrl } from "./api-base-url"; const authSession = JSON.stringify({ token: "admin-token", role: "ADMIN" }); async function hasMockWorker(page: Page): Promise { return page.evaluate(async () => { const registrations = await navigator.serviceWorker.getRegistrations(); return registrations.some((registration) => registration.active?.scriptURL.endsWith("/mockServiceWorker.js"), ); }); } test("keeps server mode requests outside browser MSW", async ({ page }) => { // Given await page.goto("/"); // When const registeredMockWorker = await hasMockWorker(page); // Then expect(registeredMockWorker).toBe(false); }); test("retries a server 404 without falling back to browser MSW", async ({ page }) => { // Given await page.addInitScript((session) => { sessionStorage.setItem("ai-character-admin-auth-session", session); }, authSession); const protectedRouteUrl = `${apiBaseUrl}/api/v2/admin/ai-characters?page=0&size=20`; let retryRequestCount = 0; let releaseRetryResponse: () => void = () => undefined; const retryResponseGate = new Promise((resolve) => { releaseRetryResponse = resolve; }); await page.route(protectedRouteUrl, async (route) => { await route.fulfill({ contentType: "application/json", json: { success: false, message: "없습니다.", data: null, errorProperty: null }, status: 404, }); }); await page.goto("/ai-characters"); const retryButton = page.getByRole("button", { name: "보호 route 다시 시도" }); await expect(retryButton).toBeVisible(); await expect(page.getByRole("alert")).toContainText("없습니다."); await expect(page.getByRole("main", { name: "AI 캐릭터 관리" })).toHaveCount(0); await expect(page.getByRole("button", { name: "로그아웃" })).toHaveCount(0); await page.unroute(protectedRouteUrl); await page.route(protectedRouteUrl, async (route) => { retryRequestCount += 1; await retryResponseGate; await route.fulfill({ contentType: "application/json", json: { success: true, message: null, data: null, errorProperty: null }, status: 200, }); }); // When await retryButton.click(); // Then await expect.poll(() => retryRequestCount).toBe(1); await expect(page.getByRole("status")).toContainText("보호 route 확인 중"); await expect(page.getByRole("main", { name: "AI 캐릭터 관리" })).toHaveCount(0); await expect(page.getByRole("button", { name: "로그아웃" })).toHaveCount(0); releaseRetryResponse(); await expect(page.getByRole("main", { name: "AI 캐릭터 관리" })).toBeVisible(); await expect(page.getByRole("button", { name: "로그아웃" })).toBeVisible(); expect(await hasMockWorker(page)).toBe(false); }); test("keeps a network error from falling back to browser MSW", async ({ page }) => { // Given await page.addInitScript((session) => { sessionStorage.setItem("ai-character-admin-auth-session", session); }, authSession); await page.route(`${apiBaseUrl}/api/v2/admin/ai-characters?page=0&size=20`, async (route) => { await route.abort("failed"); }); // When await page.goto("/ai-characters"); // Then await expect(page.getByRole("alert")).toContainText("알 수 없는 오류가 발생했습니다."); await expect(page.getByRole("main", { name: "AI 캐릭터 관리" })).toHaveCount(0); await expect(page.getByRole("button", { name: "로그아웃" })).toHaveCount(0); expect(await hasMockWorker(page)).toBe(false); }); test("keeps retry available after a server network retry fails", async ({ page }) => { // Given await page.addInitScript((session) => { sessionStorage.setItem("ai-character-admin-auth-session", session); }, authSession); const protectedRouteUrl = `${apiBaseUrl}/api/v2/admin/ai-characters?page=0&size=20`; let retryRequestCount = 0; let releaseRetryFailure: () => void = () => undefined; const retryFailureGate = new Promise((resolve) => { releaseRetryFailure = resolve; }); await page.route(protectedRouteUrl, async (route) => { await route.abort("failed"); }); await page.goto("/ai-characters"); const retryButton = page.getByRole("button", { name: "보호 route 다시 시도" }); await expect(retryButton).toBeVisible(); await expect(page.getByRole("alert")).toContainText("알 수 없는 오류가 발생했습니다."); await page.unroute(protectedRouteUrl); await page.route(protectedRouteUrl, async (route) => { retryRequestCount += 1; await retryFailureGate; await route.abort("failed"); }); // When await retryButton.click(); // Then await expect.poll(() => retryRequestCount).toBe(1); await expect(page.getByRole("status")).toContainText("보호 route 확인 중"); await expect(page.getByRole("main", { name: "AI 캐릭터 관리" })).toHaveCount(0); await expect(page.getByRole("button", { name: "로그아웃" })).toHaveCount(0); releaseRetryFailure(); await expect(page.getByRole("button", { name: "보호 route 다시 시도" })).toBeVisible(); await expect(page.getByRole("alert")).toContainText("알 수 없는 오류가 발생했습니다."); await expect(page.getByRole("main", { name: "AI 캐릭터 관리" })).toHaveCount(0); await expect(page.getByRole("button", { name: "로그아웃" })).toHaveCount(0); expect(await hasMockWorker(page)).toBe(false); });