1차 싱크 완료
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
import { describe, it, expect, afterEach } from "vitest";
|
||||
import { render, cleanup } from "@testing-library/react";
|
||||
import { PublicPageRenderer } from "@/features/editor/components/PublicPageRenderer";
|
||||
import type { Block } from "@/features/editor/state/editorStore";
|
||||
|
||||
// 폼 필드 스타일 TDD
|
||||
// - formInput: 색상/패딩/너비/둥글기 스타일
|
||||
// - formSelect: 색상/패딩/너비/둥글기 스타일
|
||||
// - formCheckbox/formRadio: 옵션 컨테이너 색상/패딩/둥글기 스타일
|
||||
|
||||
function getFirstLabel(root: HTMLElement): HTMLLabelElement {
|
||||
const label = root.querySelector("label");
|
||||
if (!label) {
|
||||
throw new Error("label element not found");
|
||||
}
|
||||
return label as HTMLLabelElement;
|
||||
}
|
||||
|
||||
describe("PublicPageRenderer - 폼 필드 스타일", () => {
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
it("formInput 블록은 색상/패딩/너비/둥글기 스타일을 반영해야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_input_styles",
|
||||
type: "formInput",
|
||||
props: {
|
||||
label: "이메일",
|
||||
formFieldName: "email",
|
||||
align: "center",
|
||||
widthMode: "fixed",
|
||||
widthPx: 320,
|
||||
paddingX: 16,
|
||||
paddingY: 8,
|
||||
textColorCustom: "#112233",
|
||||
fillColorCustom: "#123456",
|
||||
strokeColorCustom: "#ff0000",
|
||||
borderRadius: "lg",
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
|
||||
const wrapper = getByTestId("preview-form-input-wrapper") as HTMLElement;
|
||||
const input = wrapper.querySelector('[data-testid="preview-form-input"]') as HTMLElement | null;
|
||||
expect(input).not.toBeNull();
|
||||
|
||||
// 정렬
|
||||
expect((input as HTMLInputElement).style.textAlign).toBe("center");
|
||||
// width: 320px / 16 = 20em
|
||||
expect((input as HTMLInputElement).style.width).toBe("20em");
|
||||
// padding-inline/block: 16px/8px -> 1em / 0.5em
|
||||
expect((input as HTMLInputElement).style.paddingInline).toBe("1em");
|
||||
expect((input as HTMLInputElement).style.paddingBlock).toBe("0.5em");
|
||||
// 색상: hex -> rgb 변환
|
||||
expect((input as HTMLInputElement).style.color).toBe("rgb(17, 34, 51)");
|
||||
expect((input as HTMLInputElement).style.backgroundColor).toBe("rgb(18, 52, 86)");
|
||||
expect((input as HTMLInputElement).style.borderColor).toBe("rgb(255, 0, 0)");
|
||||
// borderRadius: lg -> 6px
|
||||
expect((input as HTMLInputElement).style.borderRadius).toBe("6px");
|
||||
});
|
||||
|
||||
it("formSelect 블록은 색상/패딩/너비/둥글기 스타일을 반영해야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_select_styles",
|
||||
type: "formSelect",
|
||||
props: {
|
||||
label: "카테고리",
|
||||
formFieldName: "category",
|
||||
options: [
|
||||
{ label: "A", value: "a" },
|
||||
{ label: "B", value: "b" },
|
||||
],
|
||||
widthMode: "fixed",
|
||||
widthPx: 240,
|
||||
paddingX: 16,
|
||||
paddingY: 8,
|
||||
textColorCustom: "#00ff00",
|
||||
fillColorCustom: "#123456",
|
||||
strokeColorCustom: "#ff0000",
|
||||
borderRadius: "lg",
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
|
||||
const wrapper = getByTestId("preview-form-select") as HTMLElement;
|
||||
const select = wrapper.querySelector("select") as HTMLSelectElement | null;
|
||||
expect(select).not.toBeNull();
|
||||
|
||||
// width: 240px / 16 = 15em
|
||||
expect(wrapper.style.width).toBe("15em");
|
||||
// padding-inline/block: 16px/8px -> 1em / 0.5em
|
||||
expect(select!.style.paddingInline).toBe("1em");
|
||||
expect(select!.style.paddingBlock).toBe("0.5em");
|
||||
// 색상
|
||||
expect(select!.style.color).toBe("rgb(0, 255, 0)");
|
||||
expect(select!.style.backgroundColor).toBe("rgb(18, 52, 86)");
|
||||
expect(select!.style.borderColor).toBe("rgb(255, 0, 0)");
|
||||
// 둥글기
|
||||
expect(select!.style.borderRadius).toBe("6px");
|
||||
});
|
||||
|
||||
it("formCheckbox 블록은 옵션 컨테이너에 색상/패딩/둥글기 스타일을 반영해야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_checkbox_styles",
|
||||
type: "formCheckbox",
|
||||
props: {
|
||||
groupLabel: "옵션들",
|
||||
formFieldName: "features",
|
||||
options: [{ label: "옵션 1", value: "opt1" }],
|
||||
widthMode: "fixed",
|
||||
widthPx: 320,
|
||||
paddingX: 8,
|
||||
paddingY: 4,
|
||||
optionGapPx: 16,
|
||||
textColorCustom: "#ffffff",
|
||||
fillColorCustom: "#123456",
|
||||
strokeColorCustom: "#ff0000",
|
||||
borderRadius: "lg",
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
|
||||
const group = getByTestId("preview-form-checkbox-group") as HTMLElement;
|
||||
const firstLabel = getFirstLabel(group);
|
||||
|
||||
// width: 320px / 16 = 20em
|
||||
expect(group.style.width).toBe("20em");
|
||||
// 옵션 간 간격: 16px -> 1em
|
||||
const optionsContainer = group.querySelector('[data-testid="preview-form-checkbox-options"]') as HTMLElement | null;
|
||||
expect(optionsContainer).not.toBeNull();
|
||||
expect(optionsContainer!.style.rowGap).toBe("1em");
|
||||
|
||||
// 옵션 컨테이너 스타일: padding, 배경, 보더, 둥글기
|
||||
expect(firstLabel.style.paddingInline).toBe("0.5em");
|
||||
expect(firstLabel.style.paddingBlock).toBe("0.25em");
|
||||
expect(firstLabel.style.backgroundColor).toBe("rgb(18, 52, 86)");
|
||||
expect(firstLabel.style.borderColor).toBe("rgb(255, 0, 0)");
|
||||
expect(firstLabel.style.borderRadius).toBe("6px");
|
||||
});
|
||||
|
||||
it("formRadio 블록은 옵션 컨테이너에 색상/패딩/둥글기 스타일을 반영해야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_radio_styles",
|
||||
type: "formRadio",
|
||||
props: {
|
||||
groupLabel: "플랜",
|
||||
formFieldName: "plan",
|
||||
options: [{ label: "플랜 A", value: "a" }],
|
||||
widthMode: "fixed",
|
||||
widthPx: 320,
|
||||
paddingX: 8,
|
||||
paddingY: 4,
|
||||
optionGapPx: 16,
|
||||
textColorCustom: "#ffffff",
|
||||
fillColorCustom: "#123456",
|
||||
strokeColorCustom: "#ff0000",
|
||||
borderRadius: "lg",
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
|
||||
const group = getByTestId("preview-form-radio-group") as HTMLElement;
|
||||
const firstLabel = getFirstLabel(group);
|
||||
|
||||
// width: 320px / 16 = 20em
|
||||
expect(group.style.width).toBe("20em");
|
||||
// 옵션 간 간격: 16px -> 1em
|
||||
const optionsContainer = group.querySelector('[data-testid="preview-form-radio-options"]') as HTMLElement | null;
|
||||
expect(optionsContainer).not.toBeNull();
|
||||
expect(optionsContainer!.style.rowGap).toBe("1em");
|
||||
|
||||
// 옵션 컨테이너 스타일: padding, 배경, 보더, 둥글기
|
||||
expect(firstLabel.style.paddingInline).toBe("0.5em");
|
||||
expect(firstLabel.style.paddingBlock).toBe("0.25em");
|
||||
expect(firstLabel.style.backgroundColor).toBe("rgb(18, 52, 86)");
|
||||
expect(firstLabel.style.borderColor).toBe("rgb(255, 0, 0)");
|
||||
expect(firstLabel.style.borderRadius).toBe("6px");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user