test(ci): add exporter heading levels and a11y typography smoke; update MAIN_PLAN
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
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('<select')
|
||||
expect(out.html).toContain('<option value="A">A</option>')
|
||||
expect(out.html).toContain('<input type="radio"')
|
||||
|
||||
// checkbox/textarea
|
||||
expect(out.html).toContain('type="checkbox"')
|
||||
expect(out.html).toContain('<textarea')
|
||||
|
||||
// 스팸 방지: honeypot + timestamp
|
||||
expect(out.html).toContain('type="hidden"')
|
||||
expect(out.html).toContain('name="_hp"')
|
||||
expect(out.html).toContain('name="_ts"')
|
||||
|
||||
// action 미지정 → Sheets fallback 힌트
|
||||
expect(out.html).toContain('data-sheets-fallback="true"')
|
||||
})
|
||||
|
||||
it('action URL이 있으면 form에 action 속성이 포함된다', () => {
|
||||
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"')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user