From 0e09647f2fb843194f75160e877f59b72851b601 Mon Sep 17 00:00:00 2001 From: Jaybe Date: Sat, 15 Nov 2025 12:53:28 +0900 Subject: [PATCH] =?UTF-8?q?test(export-options):=20Export=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B5=9C=EC=86=8C=20UI=20=EB=B0=8F=20extras=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99=20TDD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/BuilderClientPage.tsx | 60 ++++++++++++++++++++++++++-- components/ExportOptions.ui.test.tsx | 46 +++++++++++++++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 components/ExportOptions.ui.test.tsx diff --git a/components/BuilderClientPage.tsx b/components/BuilderClientPage.tsx index 9729e2f..add69b6 100644 --- a/components/BuilderClientPage.tsx +++ b/components/BuilderClientPage.tsx @@ -6,6 +6,7 @@ import { pageSchema, type Page } from '@/lib/schema/page' import { exportPage } from '@/lib/exporter/html' import { AssetManager } from '@/lib/assets/assetManager' import { buildZip } from '@/lib/exporter/zip' +import { buildExtrasForPage } from '@/lib/exporter/extras' import type { Section } from '@/lib/state/store' import { createFormStore, type FormState } from '@/lib/state/formStore' import FormBuilderPanel from '@/components/FormBuilderPanel' @@ -47,6 +48,9 @@ export default function BuilderClientPage() { const [ogImage, setOgImage] = useState('') const [ga4MeasurementId, setGa4MeasurementId] = useState('') const [metaPixelId, setMetaPixelId] = useState('') + // Export Options (minimal set for tests) + const [manifestName, setManifestName] = useState('') + const [robotsDisallow, setRobotsDisallow] = useState('') const [viewport, setViewport] = useState<'desktop' | 'mobile'>(() => { if (typeof window !== 'undefined') { try { @@ -182,10 +186,23 @@ export default function BuilderClientPage() { } } } catch {} - }, [pageData, am]) + }, [pageData, am, manifestName, robotsDisallow]) const doExport = useCallback(async () => { - const valid = pageSchema.parse(pageData) + let valid: Page + try { + valid = pageSchema.parse(pageData) + } catch { + const fixed: Page = { + ...pageData, + form: { + actionUrl: pageData.form?.actionUrl ?? '', + fields: pageData.form?.fields ?? [], + spamProtection: pageData.form?.spamProtection ?? { honeypotFieldName: '_hp', minSubmitSeconds: 2 }, + }, + } as Page + valid = pageSchema.parse(fixed) + } const exported = exportPage(valid, { assetManager: am ?? undefined }) try { if (typeof window !== 'undefined') { @@ -196,9 +213,19 @@ export default function BuilderClientPage() { } } catch {} const assets = am ? am.toZipStructure() : {} - const zipBytes = await buildZip({ html: exported.html, css: exported.css, js: exported.js, assets }) + // Build minimal overrides for extras + const manifestOverride: { name?: string } = {} + if (manifestName && manifestName.trim().length > 0) manifestOverride.name = manifestName.trim() + const robotsTextOverride = (() => { + const lines = (robotsDisallow || '').split(/\n+/).map((s) => s.trim()).filter((s) => s.length > 0) + if (lines.length === 0) return undefined + const disallowLines = lines.map((l) => (l.startsWith('Disallow:') ? l : `Disallow: ${l}`)) + return `User-agent: *\n${disallowLines.join('\n')}` + })() + const extras = buildExtrasForPage(valid, { robotsText: robotsTextOverride, manifest: manifestOverride }) + const zipBytes = await buildZip({ html: exported.html, css: exported.css, js: exported.js, assets, extras }) download('landing.zip', zipBytes) - }, [pageData, am]) + }, [pageData, am, manifestName, robotsDisallow]) return (
@@ -266,6 +293,31 @@ export default function BuilderClientPage() { right={
+
+

Export Options

+ +