test: expand exporter/css/a11y/i18n regressions and add e2e skip-link focus check
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
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"')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user