테스트 오류 수정
CI / test (push) Successful in 5m26s
CI / e2e (push) Failing after 14m27s
CI / pr_and_merge (push) Has been skipped

This commit is contained in:
2025-12-13 00:29:23 +09:00
parent c3b301d64e
commit 820e1f943d
8 changed files with 496 additions and 33 deletions
+14 -2
View File
@@ -268,11 +268,23 @@ test("에디터 상태를 JSON으로 내보내고 다시 불러오면 동일한
const exportArea = page.getByRole("textbox", { name: "Editor state JSON" });
const exportedJson = await exportArea.inputValue();
// 캔버스 초기화한다.
// JSON 모달을 닫고 상단 메뉴에서 캔버스 초기화를 수행한다.
await page.getByRole("button", { name: "✕" }).click();
await page.getByRole("button", { name: "Menu" }).click();
// 테스트 환경에서는 window.confirm 을 항상 true 로 반환하도록 스텁한다.
await page.evaluate(() => {
window.confirm = () => true;
});
await page.getByRole("button", { name: "Clear canvas" }).click();
await expect(canvas.getByTestId("editor-block")).toHaveCount(0);
// JSON을 다시 입력하고 불러온다.
// JSON 내보내기/불러오기 모달을 다시 열어 JSON을 적용한다.
await page.getByRole("button", { name: "Menu" }).click();
await page.getByRole("button", { name: "JSON export / import" }).click();
const importArea = page.getByRole("textbox", { name: "Import from JSON" });
await importArea.fill(exportedJson);
await page.getByRole("button", { name: "Apply JSON" }).click();
+3 -1
View File
@@ -80,8 +80,10 @@ test("프리뷰 폼 제출 후 제출 내역 페이지에서 데이터가 보여
await page.getByRole("button", { name: "Form controller" }).click();
const fieldMappingGroup = page.getByRole("group", { name: "Form field mapping" });
const fieldCheckboxes = fieldMappingGroup.locator("> label > input[type='checkbox']");
// DOM 구조(> label > input) 에 덜 의존하도록, 그룹 내의 모든 체크박스를 역할 기반으로 순회하면서 체크한다.
const fieldCheckboxes = fieldMappingGroup.getByRole("checkbox");
const fieldCount = await fieldCheckboxes.count();
expect(fieldCount).toBeGreaterThan(0);
for (let i = 0; i < fieldCount; i += 1) {
await fieldCheckboxes.nth(i).check({ force: true });
}
+32 -4
View File
@@ -297,7 +297,10 @@ test("폼 입력/셀렉트 블록도 FormBlock 없이 프리뷰에서 보여야
await expect(editorCanvas.getByText("Select field")).toBeVisible();
// FormBlock 은 추가하지 않은 상태에서 바로 프리뷰로 이동한다.
await page.getByRole("link", { name: "Open preview" }).click();
await Promise.all([
page.waitForURL(/\/preview/),
page.getByRole("link", { name: "Open preview" }).click(),
]);
await expect(page.getByRole("heading", { name: "Page Preview" })).toBeVisible();
@@ -506,7 +509,11 @@ test("폼 입력 고정 너비가 프리뷰에서도 em 스케일로 반영되
await propertiesSidebar.getByRole("combobox", { name: "Width", exact: true }).selectOption("fixed");
await propertiesSidebar.getByLabel("Field fixed width 커스텀").fill("320");
await page.getByRole("link", { name: "Open preview" }).click();
await Promise.all([
page.waitForURL(/\/preview/),
page.getByRole("link", { name: "Open preview" }).click(),
]);
await expect(page.getByRole("heading", { name: "Page Preview" })).toBeVisible();
const input = page.getByRole("textbox").first();
@@ -972,11 +979,19 @@ test("폼 입력 가로 패딩 px 입력이 프리뷰에서도 em 스케일로
await page.getByRole("button", { name: "Input field" }).click();
const paddingEditorCanvas = page.getByTestId("editor-canvas");
const paddingEditorBlocks = paddingEditorCanvas.getByTestId("editor-block");
await paddingEditorBlocks.last().click({ force: true });
const paddingSidebar = page.getByTestId("properties-sidebar");
await paddingSidebar.getByLabel("Field horizontal padding 커스텀").fill("28");
await page.getByRole("link", { name: "Open preview" }).click();
await Promise.all([
page.waitForURL(/\/preview/),
page.getByRole("link", { name: "Open preview" }).click(),
]);
await expect(page.getByRole("heading", { name: "Page Preview" })).toBeVisible();
const horizontalInput = page.getByTestId("preview-form-input").first();
@@ -1000,11 +1015,19 @@ test("폼 입력 세로 패딩 px 입력이 프리뷰에서도 em 스케일로
await page.getByRole("button", { name: "Input field" }).click();
const verticalPaddingEditorCanvas = page.getByTestId("editor-canvas");
const verticalPaddingEditorBlocks = verticalPaddingEditorCanvas.getByTestId("editor-block");
await verticalPaddingEditorBlocks.last().click({ force: true });
const paddingSidebar = page.getByTestId("properties-sidebar");
await paddingSidebar.getByLabel("Field vertical padding 커스텀").fill("18");
await page.getByRole("link", { name: "Open preview" }).click();
await Promise.all([
page.waitForURL(/\/preview/),
page.getByRole("link", { name: "Open preview" }).click(),
]);
await expect(page.getByRole("heading", { name: "Page Preview" })).toBeVisible();
const verticalInput = page.getByTestId("preview-form-input").first();
@@ -1241,6 +1264,11 @@ test("폼 셀렉트 가로 패딩 px 입력이 프리뷰에서도 em 스케일
await page.getByRole("button", { name: "Select field" }).click();
// 방금 추가한 셀렉트 블록이 선택되어 FormSelectPropertiesPanel 이 활성화되도록 보장한다.
const editorCanvas = page.getByTestId("editor-canvas");
const editorBlocks = editorCanvas.getByTestId("editor-block");
await editorBlocks.last().click({ force: true });
const propertiesSidebar = page.getByTestId("properties-sidebar");
await propertiesSidebar.getByLabel("Select horizontal padding 커스텀").fill("24");
+117
View File
@@ -0,0 +1,117 @@
import { test, expect } from "@playwright/test";
// CTA / Features 템플릿이 현재 로케일에 따라 올바른 기본 텍스트로 생성되는지 검증한다.
// 모든 테스트에서 /api/auth/me 를 목 처리해 로그인 상태를 강제한다.
test.beforeEach(async ({ page }) => {
await page.route("**/api/auth/me", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ id: "user-e2e", email: "e2e@example.com", tokenVersion: 1 }),
});
});
});
function getLocaleToggle(page: import("@playwright/test").Page) {
return page.getByRole("button", { name: "Toggle locale" });
}
async function assertLocale(page: import("@playwright/test").Page, expected: "EN" | "KO") {
const toggle = getLocaleToggle(page);
await expect(toggle).toBeVisible();
await expect(toggle).toHaveText(expected);
}
async function setLocale(page: import("@playwright/test").Page, target: "EN" | "KO") {
const toggle = getLocaleToggle(page);
await expect(toggle).toBeVisible();
const current = (await toggle.textContent())?.trim();
if (current === target) return;
await toggle.click();
await expect(toggle).toHaveText(target);
}
// EN 로케일 기준 CTA 템플릿
test("CTA 템플릿은 EN 로케일에서 영어 기본 텍스트로 생성되어야 한다", async ({ page }) => {
await page.goto("/editor");
await setLocale(page, "EN");
await page.getByRole("button", { name: "CTA template" }).click();
const canvas = page.getByTestId("editor-canvas");
// 디버그: 현재 캔버스 텍스트 블록들의 내용을 로그로 출력한다.
const debugTexts = await canvas.getByTestId("editor-block").allInnerTexts();
// eslint-disable-next-line no-console
console.log("[CTA EN debug] block texts:", debugTexts);
await expect(canvas.getByText("Write a compelling CTA message here.")).toBeVisible();
await expect(canvas.getByRole("button", { name: "Call to action" })).toBeVisible();
await expect(
canvas.getByText("지금 바로 행동을 유도하는 CTA 텍스트를 입력하세요.", { exact: false }),
).toHaveCount(0);
});
// KO 로케일 기준 CTA 템플릿
test("CTA 템플릿은 KO 로케일에서 한국어 기본 텍스트로 생성되어야 한다", async ({ page }) => {
await page.goto("/editor");
await setLocale(page, "KO");
await page.getByRole("button", { name: "CTA 템플릿" }).click();
const canvas = page.getByTestId("editor-canvas");
await expect(
canvas.getByText("지금 바로 행동을 유도하는 CTA 텍스트를 입력하세요.", { exact: false }),
).toBeVisible();
await expect(canvas.getByRole("button", { name: "CTA 버튼" })).toBeVisible();
await expect(canvas.getByText("Write a compelling CTA message here.")).toHaveCount(0);
});
// EN 로케일 기준 Features 템플릿
test("Features 템플릿은 EN 로케일에서 영어 기본 텍스트로 생성되어야 한다", async ({ page }) => {
await page.goto("/editor");
await setLocale(page, "EN");
await page.getByRole("button", { name: "Features template" }).click();
const canvas = page.getByTestId("editor-canvas");
// 디버그: 현재 캔버스 텍스트 블록들의 내용을 로그로 출력한다.
const debugTexts = await canvas.getByTestId("editor-block").allInnerTexts();
// eslint-disable-next-line no-console
console.log("[Features EN debug] block texts:", debugTexts);
await expect(canvas.getByText("Feature 1", { exact: false }).first()).toBeVisible();
await expect(canvas.getByText("A short description of this feature.").first()).toBeVisible();
await expect(
canvas.getByText("해당 기능을 간단히 설명하는 텍스트입니다.", { exact: false }),
).toHaveCount(0);
});
// KO 로케일 기준 Features 템플릿
test("Features 템플릿은 KO 로케일에서 한국어 기본 텍스트로 생성되어야 한다", async ({ page }) => {
await page.goto("/editor");
await setLocale(page, "KO");
await page.getByRole("button", { name: "기능 템플릿" }).click();
const canvas = page.getByTestId("editor-canvas");
await expect(canvas.getByText("Feature 1 제목", { exact: false })).toBeVisible();
await expect(
canvas.getByText("해당 기능을 간단히 설명하는 텍스트입니다.", { exact: false }).first(),
).toBeVisible();
await expect(canvas.getByText("A short description of this feature.")).toHaveCount(0);
});