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"; // PublicPageRenderer 버튼 스타일 TDD // - fillColorCustom / strokeColorCustom / textColorCustom // - widthMode=fixed + widthPx, paddingX/paddingY // - borderRadius 토큰에 따른 둥글기 describe("PublicPageRenderer - 버튼 블록 스타일", () => { afterEach(() => { cleanup(); }); it("버튼 색상 커스텀 값은 배경/외곽선/텍스트 색상 스타일에 반영되어야 한다", () => { const blocks: Block[] = [ { id: "btn_colors", type: "button", props: { label: "컬러 버튼", href: "#", align: "center", fillColorCustom: "#123456", strokeColorCustom: "#ff0000", textColorCustom: "#00ff00", } as any, }, ]; const { container } = render(); const link = container.querySelector("a") as HTMLAnchorElement | null; expect(link).not.toBeNull(); const wrapper = link!.parentElement as HTMLElement | null; expect(wrapper).not.toBeNull(); // 정렬/버튼 베이스는 pb-* 토큰 클래스로 렌더된다. expect(wrapper!.className).toContain("pb-text-center"); expect(link!.className).toContain("pb-btn-base"); expect(link!.className).toContain("pb-btn-size-md"); expect(link!.className).toContain("pb-btn-variant-solid-primary"); expect(link!.className).toContain("pb-btn-radius-md"); // 배경색: #123456 → rgb(18, 52, 86) expect(link!.style.backgroundColor).toBe("rgb(18, 52, 86)"); // 외곽선 색상: #ff0000 → rgb(255, 0, 0) expect(link!.style.borderColor).toBe("rgb(255, 0, 0)"); // strokeColorCustom 이 있을 때 border-width/style 도 설정되어야 한다. expect(link!.style.borderWidth).toBe("1px"); expect(link!.style.borderStyle).toBe("solid"); // 텍스트 색상: #00ff00 → rgb(0, 255, 0) expect(link!.style.color).toBe("rgb(0, 255, 0)"); }); it("widthMode=fixed 인 버튼은 widthPx/paddingX/paddingY 가 em 단위 스타일로 반영되어야 한다", () => { const blocks: Block[] = [ { id: "btn_layout", type: "button", props: { label: "레이아웃 버튼", href: "#", align: "left", widthMode: "fixed", widthPx: 320, paddingX: 16, paddingY: 8, } as any, }, ]; const { container } = render(); const link = container.querySelector("a") as HTMLAnchorElement | null; expect(link).not.toBeNull(); // width: 320px / 16 = 20em expect(link!.style.width).toBe("20em"); // padding-inline: 16px / 16 = 1em expect(link!.style.paddingInline).toBe("1em"); // padding-block: 8px / 16 = 0.5em expect(link!.style.paddingBlock).toBe("0.5em"); }); it("borderRadius 토큰은 em 단위 둥글기로 반영되어야 한다", () => { const blocks: Block[] = [ { id: "btn_radius", type: "button", props: { label: "둥근 버튼", href: "#", borderRadius: "lg", } as any, }, ]; const { container } = render(); const link = container.querySelector("a") as HTMLAnchorElement | null; expect(link).not.toBeNull(); // lg → 12px → 12 / 16 = 0.75em expect(link!.style.borderRadius).toBe("0.75em"); }); });