diff --git a/tools/verify-article-overview-ux-1.44.0.mjs b/tools/verify-article-overview-ux-1.44.0.mjs new file mode 100644 index 0000000..39db09a --- /dev/null +++ b/tools/verify-article-overview-ux-1.44.0.mjs @@ -0,0 +1,56 @@ +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const root = resolve(process.cwd()); +const read = path => readFileSync(resolve(root, path), 'utf8'); +const loader = read('public/ux-foundation.js'); +const css = read('public/article-overview-ux.css'); +const js = read('public/article-overview-ux.js'); +const pkg = JSON.parse(read('package.json')); + +const failures = []; +const assert = (condition, message) => { if (!condition) failures.push(message); }; + +assert(loader.includes('/article-overview-ux.css?v=1.44.0'), 'Article-Overview-Stylesheet wird nicht über die UX-Foundation geladen.'); +assert(loader.includes('/article-overview-ux.js?v=1.44.0'), 'Article-Overview-Script wird nicht über die UX-Foundation geladen.'); +assert(pkg.scripts?.['verify:article-overview'] === 'node tools/verify-article-overview-ux-1.44.0.mjs', 'npm-Script verify:article-overview fehlt oder ist falsch.'); +assert(String(pkg.scripts?.['verify:all'] || '').includes('verify:article-overview'), 'verify:all enthält das Article-Overview-Gate nicht.'); + +for (const value of ['', 'active', 'reserved', 'sold']) { + assert(js.includes(`value: '${value}'`), `Status-Schnellfilter fehlt: ${value || 'Alle'}`); +} +for (const id of ['history-list', 'filter-status', 'search-input', 'history-batch-actions', 'history-total-info']) { + assert(js.includes(id), `Bestehender Artikelvertrag wird nicht referenziert: ${id}`); +} +for (const token of ['data-article-view-choice', 'data-article-status', 'data-ux-label', 'MutationObserver', 'localStorage', 'requestAnimationFrame']) { + assert(js.includes(token), `Article-Overview-Vertrag fehlt: ${token}`); +} +assert(js.includes("row.tabIndex = 0"), 'Artikelkarten sind nicht tastaturfokussierbar.'); +assert(js.includes("event.key === 'Enter'"), 'Artikelkarten unterstützen Enter nicht.'); +assert(!js.includes('onclick='), 'Inline-Eventhandler sind im Article-Overview-Script unzulässig.'); +assert(!js.includes('innerHTML +=') && !js.includes('outerHTML'), 'Unsichere DOM-Erweiterung im Article-Overview-Script erkannt.'); + +for (const selector of [ + '.ux-article-toolbar', + '.ux-status-filters', + '.ux-active-filters', + '.ux-batch-more', + '#history[data-article-view="cards"] .history-list', + '#history[data-article-view="list"] .history-table-head', + '@media (max-width: 760px)', + '@media (prefers-reduced-motion: reduce)', +]) { + assert(css.includes(selector), `Article-Overview-CSS-Vertrag fehlt: ${selector}`); +} +assert(css.includes('focus-visible'), 'Sichtbare Tastaturfokusse fehlen im Article-Overview-CSS.'); +assert(css.includes('var(--vd-'), 'Article-Overview-CSS verwendet das zentrale Design-Token-System nicht.'); +assert(css.includes('repeat(auto-fill, minmax('), 'Adaptive Kartenraster fehlen.'); +assert(css.includes('.history-batch-bar:not(.has-selection)'), 'Inaktive Mehrfachaktionen werden nicht reduziert.'); + +if (failures.length) { + console.error('[ARTICLE-OVERVIEW-UX] Prüfung fehlgeschlagen:'); + failures.forEach(failure => console.error(`- ${failure}`)); + process.exit(1); +} + +console.log('[ARTICLE-OVERVIEW-UX] Karten-/Listenansicht, Status-Schnellfilter, aktive Filter, reduzierte Mehrfachaktionen, Responsive-Vertrag und Tastaturführung sind vollständig.'); \ No newline at end of file