import { describe, it, expect } from 'vitest' import { pageSchema, type Page } from '@/lib/schema/page' import { exportPage } from '@/lib/exporter/html' const makePage = (withAction = false): Page => pageSchema.parse({ title: 'Form Test', locale: 'en', theme: { primaryColor: '#0ea5e9', fontFamily: 'Inter' }, sections: [], form: { actionUrl: withAction ? 'https://example.com/submit' : '', fields: [ { type: 'text', name: 'name', label: 'Name', required: true }, { type: 'email', name: 'email', label: 'Email', required: true }, { type: 'select', name: 'plan', label: 'Plan', required: false, options: ['A','B'] }, { type: 'radio', name: 'size', label: 'Size', required: false, options: ['S','M','L'] }, { type: 'checkbox', name: 'agree', label: 'Agree', required: true }, { type: 'textarea', name: 'msg', label: 'Message', required: false }, ], spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 }, }, seo: { title: 'Form Test', description: 'desc' }, }) describe('Exporter - form rendering', () => { it('필드 라벨/required/옵션 및 스팸 방지 요소를 렌더링한다 (action 미지정)', () => { const page = makePage(false) const out = exportPage(page) // 필수 required expect(out.html).toContain('name="name"') expect(out.html).toContain('required') expect(out.html).toContain('name="email"') // select/radio 옵션 존재 expect(out.html).toContain('A') // 라디오 인풋은 id 속성이 먼저 오므로 type만으로 확인 expect(out.html).toContain('type="radio"') // checkbox/textarea expect(out.html).toContain('type="checkbox"') expect(out.html).toContain(' { const page = makePage(true) const out = exportPage(page) expect(out.html).toContain('action="https://example.com/submit"') expect(out.html).not.toContain('data-sheets-fallback="true"') }) })