From e1c91b16686e55d1431c3a7e9875b7c5c0564d00 Mon Sep 17 00:00:00 2001 From: Jaybe Date: Thu, 27 Nov 2025 11:39:33 +0900 Subject: [PATCH] =?UTF-8?q?feat:=2015.2=20=ED=91=B8=ED=84=B0/=EB=82=B4?= =?UTF-8?q?=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20Export=20=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20TDD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/api/export.spec.ts | 44 ++++++++++++++++++++ tests/unit/PublicPageRendererFooter.spec.tsx | 33 +++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 tests/unit/PublicPageRendererFooter.spec.tsx diff --git a/tests/api/export.spec.ts b/tests/api/export.spec.ts index 58c510c..d7522f6 100644 --- a/tests/api/export.spec.ts +++ b/tests/api/export.spec.ts @@ -7,6 +7,7 @@ import type { Block, ProjectConfig } from "@/features/editor/state/editorStore"; import { createHeroTemplateBlocks } from "@/app/editor/templates/heroTemplate"; import { createFeaturesTemplateBlocks } from "@/app/editor/templates/featuresTemplate"; import { createCtaTemplateBlocks } from "@/app/editor/templates/ctaTemplate"; +import { createFooterTemplateBlocks } from "@/app/editor/templates/footerTemplate"; import { buildStaticHtml } from "@/app/api/export/route"; const BASE_URL = "http://localhost"; @@ -1446,6 +1447,49 @@ describe("/api/export", () => { expect(html).toContain("지금 바로 행동을 유도하는 CTA 텍스트를 입력하세요."); expect(html).toContain("CTA 버튼"); }); + + it("Footer 템플릿 섹션은 export HTML 의 마지막 섹션으로 렌더되고 푸터 텍스트를 포함해야 한다", async () => { + const sectionId = "footer_section_export"; + const { blocks } = createFooterTemplateBlocks({ sectionId, createId: createIdFactory() }); + + const html = await exportTemplateHtml(blocks as Block[]); + + expect(html).toContain("MyLanding"); + expect(html).toContain("더 나은 웹사이트를 위한 최고의 선택."); + expect(html).toContain("서비스 소개"); + expect(html).toContain("문의하기"); + expect(html).toContain(" 2025 MyLanding."); + + const lastSectionIndex = html.lastIndexOf(" { + const blocks: Block[] = [ + { + id: "nav_btn_1", + type: "button", + props: { + label: "요금제", + href: "/pricing", + align: "left", + }, + } as any, + ]; + + const projectConfig: ProjectConfig = { + title: "내비게이션 링크 테스트", + slug: "nav-link-test", + canvasPreset: "full", + }; + + const html = buildStaticHtml(blocks, projectConfig); + + expect(html).toContain('요금제"); + }); }); describe("스타일 테스트", () => { diff --git a/tests/unit/PublicPageRendererFooter.spec.tsx b/tests/unit/PublicPageRendererFooter.spec.tsx new file mode 100644 index 0000000..ed657b3 --- /dev/null +++ b/tests/unit/PublicPageRendererFooter.spec.tsx @@ -0,0 +1,33 @@ +import { describe, it, expect, afterEach } from "vitest"; +import { render, screen, cleanup } from "@testing-library/react"; +import { PublicPageRenderer } from "@/features/editor/components/PublicPageRenderer"; +import { createFooterTemplateBlocks } from "@/app/editor/templates/footerTemplate"; +import type { Block } from "@/features/editor/state/editorStore"; + +// PublicPageRenderer 푸터 템플릿 TDD +// - footerTemplate 로 생성한 섹션이 프리뷰에서 섹션/텍스트 구조로 올바르게 렌더되는지 검증한다. + +describe("PublicPageRenderer - 푸터 템플릿", () => { + afterEach(() => { + cleanup(); + }); + + it("푸터 템플릿 섹션은 프리뷰에서 섹션과 푸터 텍스트들을 렌더해야 한다", () => { + const sectionId = "footer_preview_section"; + let i = 0; + const createId = () => `footer_${++i}`; + + const { blocks } = createFooterTemplateBlocks({ sectionId, createId }); + + render(); + + const section = screen.getByTestId("preview-section"); + expect(section.getAttribute("data-section-id")).toBe(sectionId); + + expect(screen.getByText("MyLanding")).toBeTruthy(); + expect(screen.getByText("더 나은 웹사이트를 위한 최고의 선택.")).toBeTruthy(); + expect(screen.getByText(/서비스 소개/)).toBeTruthy(); + expect(screen.getByText(/문의하기/)).toBeTruthy(); + expect(screen.getByText(/© 2025 MyLanding\./)).toBeTruthy(); + }); +});