test(ci): add exporter heading levels and a11y typography smoke; update MAIN_PLAN
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { pageSchema, type Page } from '@/lib/schema/page'
|
||||
import { exportPage } from '@/lib/exporter/html'
|
||||
|
||||
const makeSamplePage = (): Page =>
|
||||
pageSchema.parse({
|
||||
title: 'Sample Landing',
|
||||
locale: 'en',
|
||||
theme: { primaryColor: '#0ea5e9', fontFamily: 'Inter' },
|
||||
sections: [
|
||||
{
|
||||
type: 'hero',
|
||||
props: {
|
||||
heading: 'Welcome',
|
||||
subheading: 'Build fast',
|
||||
imageUrl: 'https://cdn.example.com/hero.png',
|
||||
},
|
||||
},
|
||||
],
|
||||
form: {
|
||||
actionUrl: '',
|
||||
fields: [
|
||||
{ type: 'text', name: 'name', label: 'Name', required: true },
|
||||
{ type: 'email', name: 'email', label: 'Email', required: true },
|
||||
{ type: 'checkbox', name: 'agree', label: 'Agree', required: true },
|
||||
],
|
||||
spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 },
|
||||
},
|
||||
analytics: { ga4MeasurementId: '', metaPixelId: '' },
|
||||
seo: { title: 'Sample Landing', description: 'desc', ogImage: 'https://cdn.example.com/og.png' },
|
||||
})
|
||||
|
||||
|
||||
describe('HTML Exporter', () => {
|
||||
it('페이지를 정적 HTML/CSS/JS로 내보낸다', () => {
|
||||
const page = makeSamplePage()
|
||||
const out = exportPage(page)
|
||||
|
||||
expect(typeof out.html).toBe('string')
|
||||
expect(typeof out.css).toBe('string')
|
||||
expect(typeof out.js).toBe('string')
|
||||
|
||||
// 기본 요소 포함
|
||||
expect(out.html).toContain('<!DOCTYPE html>')
|
||||
expect(out.html).toContain('<html lang="en">')
|
||||
expect(out.html).toContain('<title>Sample Landing</title>')
|
||||
|
||||
// OG/SEO
|
||||
expect(out.html).toContain('meta property="og:title"')
|
||||
expect(out.html).toContain('meta property="og:image"')
|
||||
|
||||
// Hero 섹션 렌더링
|
||||
expect(out.html).toContain('Welcome')
|
||||
expect(out.html).toContain('Build fast')
|
||||
expect(out.html).toContain('https://cdn.example.com/hero.png')
|
||||
|
||||
// Form 렌더링 및 스팸방지 요소
|
||||
expect(out.html).toContain('name="name"')
|
||||
expect(out.html).toContain('name="email"')
|
||||
expect(out.html).toContain('name="agree"')
|
||||
expect(out.html).toContain('type="hidden"') // honeypot 또는 타임스탬프
|
||||
|
||||
// actionUrl 미지정이면 data-hint 포함(향후 Sheets 연결 힌트)
|
||||
expect(out.html).toContain('data-sheets-fallback="true"')
|
||||
})
|
||||
|
||||
it('파일 input은 생성하지 않는다', () => {
|
||||
const page = makeSamplePage()
|
||||
const out = exportPage(page)
|
||||
expect(out.html).not.toMatch(/type=\"file\"/)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user