check:poster-section covers min-card-px and show-header, with poisons for a dropped attribute and an unwired view

This commit is contained in:
Doxa Maps 2026-10-02 10:38:59 +00:00
parent aed7849bd2
commit dc9014bb83

View file

@ -16,7 +16,7 @@ import { fileURLToPath } from 'node:url'
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..')
const DXL = ['africa', 'asia', 'europe', 'latin-america-and-caribbean', 'middle-east', 'north-america-and-non-spanish-caribbean', 'oceania', 'other']
async function arms({ types, country, element, sectionSrc }) {
async function arms({ types, country, element, sectionSrc, viewSrc }) {
const fails = []
// A
if (!types.posterTypeNames().includes('country')) fails.push("A: the registry has no 'country' type")
@ -55,6 +55,19 @@ async function arms({ types, country, element, sectionSrc }) {
if (!(d0.type === 'country' && d0.scope === 'africa' && d0.collapsible === true && d0.collapsed === false)) fails.push(`D: defaults wrong ${JSON.stringify(d0)}`)
if (element.posterSectionConfig(fake({ collapsible: 'false' })).collapsible !== false) fails.push('D: collapsible="false" does not turn collapsing off')
if (element.posterSectionConfig(fake({ collapsed: '' })).collapsed !== true) fails.push('D: collapsed does not start the section shut')
// min-card-px: absent = no key (the wall's own default); an integer 80..600 is kept; anything else is dropped.
if ('minCardPx' in d0) fails.push('D: no min-card-px still sets minCardPx')
if (element.posterSectionConfig(fake({ 'min-card-px': '150' })).minCardPx !== 150) fails.push('D: min-card-px="150" is not kept')
if ('minCardPx' in element.posterSectionConfig(fake({ 'min-card-px': '50' }))) fails.push('D: min-card-px="50" (below 80) is kept')
// show-header: absent = no key (shown, every current host unchanged); "false" = showHeader false; any other value = shown.
if ('showHeader' in d0) fails.push('D: no show-header still sets showHeader')
if (element.posterSectionConfig(fake({ 'show-header': 'false' })).showHeader !== false) fails.push('D: show-header="false" does not hide the head')
if ('showHeader' in element.posterSectionConfig(fake({ 'show-header': '' }))) fails.push('D: show-header="" hides the head')
// F: the view passes show-header to the wall, and a headless section can neither collapse nor start shut.
const view = String(viewSrc || '').replace(/<!--[\s\S]*?-->/g, '').replace(/\/\/[^\n]*/g, '')
if (!/:section-heads="showHeader"/.test(view)) fails.push('F: PosterSectionView does not pass showHeader to the wall (section-heads)')
if (!/const collapsible\s*=\s*computed\([^\n]*showHeader/.test(view)) fails.push('F: a headless section can still collapse')
if (!/const startCollapsed\s*=\s*computed\([^\n]*showHeader/.test(view)) fails.push('F: a headless section can still start shut')
// E
const tpl = (sectionSrc.match(/<template>([\s\S]*)<\/template>\s*$/) || ['', ''])[1].replace(/<!--[\s\S]*?-->/g, '')
const injected = new Set(((sectionSrc.match(/const \{([\s\S]*?)\} = inject\(POSTER_WALL_CTX\)/) || ['', ''])[1]).split(/[\s,]+/).filter(Boolean))
@ -78,12 +91,16 @@ try {
const country = (await load('library/components/poster/types/countryPosterType.js')).default
const element = await load('library/elements/posterSectionConfig.js')
const sectionSrc = readFileSync(join(ROOT, 'library/components/poster/PosterSection.vue'), 'utf8')
const real = { types, country, element, sectionSrc }
const viewSrc = readFileSync(join(ROOT, 'library/components/poster/PosterSectionView.vue'), 'utf8')
const real = { types, country, element, sectionSrc, viewSrc }
if (process.argv.includes('--self-test')) {
const poisons = [
["a registry without 'country'", { ...real, types: { ...types, posterTypeNames: () => [] } }, /^A:/],
['a region key without "&" → "and"', { ...real, country: { ...country, items: (s, l) => (/-and-/.test(String(s)) ? [] : country.items(s, l)) } }, /^B:/],
['a section that uses a name it does not inject', { ...real, sectionSrc: sectionSrc.replace('</template>', '{{ notProvided }}</template>') }, /^E:/],
['an element config that drops show-header', { ...real, element: { posterSectionConfig: (el) => { const c = element.posterSectionConfig(el); delete c.showHeader; return c } } }, /^D: show-header="false"/],
['a view that does not pass show-header to the wall', { ...real, viewSrc: viewSrc.replace(':section-heads="showHeader"', '') }, /^F:/],
['a headless section that can still start shut', { ...real, viewSrc: viewSrc.replace(/(const startCollapsed = computed\(\(\) => cfg\.value\.collapsed === true)[^\n]*/, '$1)') }, /^F: a headless section can still start shut/],
]
for (const [name, inp, rx] of poisons) {
const f = await arms(inp); const ok = f.some((x) => rx.test(x))