136 lines
5.4 KiB
TypeScript
136 lines
5.4 KiB
TypeScript
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<boolean> {
|
|
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<void>((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<void>((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);
|
|
});
|