67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { pageSchema, type Page } from '@/lib/schema/page'
|
|
import { exportPage } from '@/lib/exporter/html'
|
|
|
|
function makePage(fields: Page['form']['fields']): Page {
|
|
return pageSchema.parse({
|
|
title: 'Matrix',
|
|
locale: 'en',
|
|
theme: { primaryColor: '#0ea5e9', fontFamily: 'Inter' },
|
|
sections: [],
|
|
form: {
|
|
actionUrl: '',
|
|
fields,
|
|
spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 },
|
|
},
|
|
seo: { title: 'SEO', description: 'Desc' },
|
|
})
|
|
}
|
|
|
|
describe('Exporter - form helptext matrix (required/maxLength/pattern/help)', () => {
|
|
it('text: required + maxLength + help → has required, maxlength, help id and aria-describedby', () => {
|
|
const page = makePage([
|
|
{ type: 'text', name: 'nick', label: 'Nickname', required: true, maxLength: 10, help: 'Public name' },
|
|
])
|
|
const html = exportPage(page).html
|
|
expect(html).toContain('id="field-nick"')
|
|
expect(html).toMatch(/name="nick"[^"]*[^>]*required/)
|
|
expect(html).toMatch(/name="nick"[^"]*[^>]*maxlength="10"/)
|
|
expect(html).toContain('id="field-nick-help"')
|
|
expect(html).toContain('aria-describedby="field-nick-help"')
|
|
})
|
|
|
|
it('tel: pattern only, no help → has pattern, no aria-describedby', () => {
|
|
const page = makePage([
|
|
{ type: 'tel', name: 'phone', label: 'Phone', required: false, pattern: '^\\+?[0-9\\- ]{7,}$' },
|
|
])
|
|
const html = exportPage(page).html
|
|
expect(html).toMatch(/name="phone"[^"]*[^>]*pattern="\^\\\+\?\[0-9\\\- \]\{7,\}\$"/)
|
|
expect(html).not.toContain('field-phone-help')
|
|
// ensure no false aria-describedby
|
|
expect(html).not.toMatch(/name="phone"[^"]*[^>]*aria-describedby=/)
|
|
})
|
|
|
|
it('select: help present → select has aria-describedby and help element exists', () => {
|
|
const page = makePage([
|
|
{ type: 'select', name: 'plan', label: 'Plan', required: false, options: ['Free','Pro'], help: 'Choose one' },
|
|
])
|
|
const html = exportPage(page).html
|
|
expect(html).toContain('id="field-plan"')
|
|
expect(html).toContain('aria-describedby="field-plan-help"')
|
|
expect(html).toContain('id="field-plan-help"')
|
|
})
|
|
|
|
it('radio: help present → fieldset has aria-describedby; radios do not individually', () => {
|
|
const page = makePage([
|
|
{ type: 'radio', name: 'size', label: 'Size', required: false, options: ['S','M'], help: 'Pick one' },
|
|
])
|
|
const html = exportPage(page).html
|
|
// fieldset wiring
|
|
expect(html).toContain('<fieldset')
|
|
expect(html).toContain('aria-describedby="field-size-help"')
|
|
expect(html).toContain('id="field-size-help"')
|
|
// radios present
|
|
expect(html).toContain('type="radio"')
|
|
})
|
|
})
|