diff --git a/lib/exporter/zip.validation.integrated.test.ts b/lib/exporter/zip.validation.integrated.test.ts new file mode 100644 index 0000000..0244912 --- /dev/null +++ b/lib/exporter/zip.validation.integrated.test.ts @@ -0,0 +1,53 @@ +import { describe, it, expect } from 'vitest' +import JSZip from 'jszip' +import { exportPage } from '@/lib/exporter/html' +import { buildZip } from '@/lib/exporter/zip' +import { AssetManager } from '@/lib/assets/assetManager' +import { pageSchema, type Page } from '@/lib/schema/page' + +function makePageWithLocalAsset(): { page: Page; am: AssetManager } { + const am = new AssetManager({ maxBytes: 1024 * 1024, allowedExts: ['png','svg','jpg','jpeg','webp'] }) + // simulate adding a local image and referencing it by original name via local: prefix + const bytes = new Uint8Array([7,8,9]) + // add as "hero.png" + am.add({ name: 'hero.png', type: 'image/png', bytes }) + + const base: Page = pageSchema.parse({ + title: 'Integrated ZIP', + locale: 'en', + theme: { primaryColor: '#2563eb', fontFamily: 'Inter' }, + sections: [ + { type: 'hero', props: { heading: 'Hello', subheading: 'World', imageUrl: 'local:hero.png' } }, + { type: 'cta', props: { text: 'Go', href: '#' } }, + ], + form: { actionUrl: '', fields: [], spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 } }, + analytics: { ga4MeasurementId: 'G-TEST', metaPixelId: '', customHeadHtml: '' }, + seo: { title: 't', description: 'd' }, + }) + return { page: base, am } +} + +describe('Export ZIP 통합 검증', () => { + it('exportPage 출력 + buildZip 결과에서 assets 경로/메타가 보존된다', async () => { + const { page, am } = makePageWithLocalAsset() + const out = exportPage(page, { assetManager: am }) + const assets = am.toZipStructure() + const zipBytes = await buildZip({ html: out.html, css: out.css, js: out.js, assets }) + + const zip = await JSZip.loadAsync(zipBytes) + const names = Object.keys(zip.files) + // assets 파일이 존재해야 함 + const assetKey = Object.keys(assets)[0] + expect(names).toContain(assetKey) + + // index.html에 canonical/meta/ga4 스니펫 보존 + const html = await zip.files['index.html'].async('string') + expect(html).toMatch(/]*src="([^"]+)"/) + expect(match && match[1]).toBe(assetKey) + }) +}) diff --git a/lib/exporter/zip.validation.meta.test.ts b/lib/exporter/zip.validation.meta.test.ts new file mode 100644 index 0000000..5934287 --- /dev/null +++ b/lib/exporter/zip.validation.meta.test.ts @@ -0,0 +1,28 @@ +import { describe, it, expect } from 'vitest' +import JSZip from 'jszip' +import { buildZip } from '@/lib/exporter/zip' + +describe('Export ZIP 메타 보존 검증', () => { + it('index.html의 SEO/OG/Analytics 메타가 그대로 보존된다', async () => { + const html = `
+ + + + + + + ok` + const css = 'body{color:#222}' + const js = 'console.log("ok")' + + const zipBytes = await buildZip({ html, css, js, assets: {} }) + const zip = await JSZip.loadAsync(zipBytes) + const htmlContent = await zip.files['index.html'].async('string') + + expect(htmlContent).toMatch(/