test(ai-character): 리소스 운영 E2E 보강
This commit is contained in:
93
tests/e2e/resource-workflows.spec.ts
Normal file
93
tests/e2e/resource-workflows.spec.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
type ApiRequest = {
|
||||
readonly method: string;
|
||||
readonly path: string;
|
||||
readonly search: string;
|
||||
};
|
||||
|
||||
async function loginThroughMockMode(page: Page): Promise<void> {
|
||||
await page.goto("/login");
|
||||
await page.getByLabel("이메일").fill("admin@test.com");
|
||||
await page.getByLabel("비밀번호").fill("password");
|
||||
await page.getByRole("button", { name: "로그인" }).click();
|
||||
await expect(page).toHaveURL(/\/ai-characters$/);
|
||||
}
|
||||
|
||||
function collectAdminApiRequests(page: Page): ApiRequest[] {
|
||||
const requests: ApiRequest[] = [];
|
||||
page.on("request", (request) => {
|
||||
const url = new URL(request.url());
|
||||
if (url.pathname.startsWith("/api/v2/admin/")) {
|
||||
requests.push({ method: request.method(), path: url.pathname, search: url.search });
|
||||
}
|
||||
});
|
||||
|
||||
return requests;
|
||||
}
|
||||
|
||||
test("active mock resources complete the cross-domain journey without uncontracted requests", async ({ page }, testInfo) => {
|
||||
test.skip(testInfo.project.name.startsWith("mobile-"), "Desktop-only mutation journey.");
|
||||
|
||||
// Given
|
||||
const requests = collectAdminApiRequests(page);
|
||||
await page.setViewportSize({ width: 1280, height: 900 });
|
||||
await loginThroughMockMode(page);
|
||||
|
||||
// When / Then
|
||||
await page.getByRole("link", { name: "루나 선택" }).click();
|
||||
await expect(page.getByRole("heading", { name: "루나", exact: true })).toBeVisible();
|
||||
|
||||
await page.goto("/ai-characters/101/audio-contents");
|
||||
await expect(page.getByRole("group", { name: "달빛 상담 오디오 오디오 플레이어" })).toBeVisible();
|
||||
await page.getByRole("link", { name: "달빛 상담 오디오 상세 보기" }).click();
|
||||
await expect(page.getByRole("heading", { name: "달빛 상담 오디오", exact: true })).toBeVisible();
|
||||
|
||||
await page.goto("/ai-characters/101/series/5001");
|
||||
await expect(page.getByRole("heading", { name: "연결된 오디오", exact: true })).toBeVisible();
|
||||
await page.getByRole("searchbox", { name: "검색어" }).fill("아침");
|
||||
await page.getByRole("checkbox", { name: /아침 안내 오디오/ }).click();
|
||||
await page.getByRole("button", { name: "선택한 오디오 연결" }).click();
|
||||
await expect(page.getByRole("button", { name: "아침 안내 오디오 연결 해제" })).toBeVisible();
|
||||
await page.getByRole("link", { name: "전체 시리즈 순서 관리" }).click();
|
||||
await page.getByRole("button", { name: "아침 루틴 시리즈 위로" }).click();
|
||||
await page.getByRole("button", { name: "순서 저장" }).click();
|
||||
await expect(page.getByText("시리즈 순서를 저장했습니다")).toBeVisible();
|
||||
|
||||
await page.goto("/ai-characters/101/community-posts");
|
||||
await page.getByRole("button", { name: "오늘의 상담 기록입니다. 게시글 열기" }).click();
|
||||
const communityDialog = page.getByRole("dialog", { name: "커뮤니티 게시글" });
|
||||
await communityDialog.getByRole("textbox", { name: "내용" }).fill("교차 회귀 수정 내용입니다.");
|
||||
await communityDialog.getByRole("button", { name: "수정 저장" }).click();
|
||||
await expect.poll(() => requests.some((request) => request.method === "PUT" && request.path.includes("/community-posts/"))).toBe(true);
|
||||
|
||||
await page.goto("/ai-characters/101/fan-talks");
|
||||
await page.getByRole("button", { name: "첫 번째 응원입니다. 답변하기" }).click();
|
||||
const fanTalkDialog = page.getByRole("dialog", { name: "FanTalk 답변" });
|
||||
await fanTalkDialog.getByLabel("답변 내용").fill("교차 회귀 답변입니다.");
|
||||
await fanTalkDialog.getByRole("button", { name: "답변 등록" }).click();
|
||||
await expect(fanTalkDialog.getByRole("status", { name: "답변 저장 성공" })).toBeVisible();
|
||||
|
||||
expect(requests.some((request) => /\/community-posts\/\d+$/.test(request.path) && request.method === "GET")).toBe(false);
|
||||
expect(requests.some((request) => request.path.includes("/fan-talks/7001") && request.method === "GET")).toBe(false);
|
||||
expect(requests.every((request) => !request.search.includes("status=") && !request.search.includes("sort="))).toBe(true);
|
||||
});
|
||||
|
||||
test("inactive character workspace blocks child mutation requests", async ({ page }) => {
|
||||
// Given
|
||||
const requests = collectAdminApiRequests(page);
|
||||
await page.setViewportSize({ width: 1280, height: 900 });
|
||||
await loginThroughMockMode(page);
|
||||
|
||||
// When / Then
|
||||
await page.goto("/ai-characters/202/community-posts/new");
|
||||
await expect(page.getByRole("heading", { name: "커뮤니티 게시글 생성 차단" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "생성" })).toBeHidden();
|
||||
|
||||
await page.goto("/ai-characters/202/fan-talks");
|
||||
await expect(page.getByRole("heading", { name: "FanTalk", exact: true })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /답변하기/ })).toBeHidden();
|
||||
|
||||
expect(requests.some((request) => request.method !== "GET" && request.path.includes("/ai-characters/202/"))).toBe(false);
|
||||
});
|
||||
Reference in New Issue
Block a user