test(ux): add FLUX Studio UX release gate

This commit is contained in:
Masterluke77
2026-07-12 02:01:10 +02:00
parent 764e4dc615
commit 3c8cc9cf26
+102
View File
@@ -0,0 +1,102 @@
import fs from 'node:fs';
import path from 'node:path';
const root = process.cwd();
const read = relative => fs.readFileSync(path.join(root, relative), 'utf8');
const js = read('public/flux-studio-ux.js');
const css = read('public/flux-studio-ux.css');
const loader = read('public/ux-foundation.js');
const html = read('public/index.html');
const pkg = JSON.parse(read('package.json'));
const failures = [];
const expect = (condition, message) => {
if (!condition) failures.push(message);
};
const includesAll = (source, values, label) => {
for (const value of values) expect(source.includes(value), `${label}: ${value}`);
};
includesAll(html, [
'id="flux-studio"',
'id="flux-studio-prompt"',
'id="flux-studio-generate"',
'id="flux-studio-preview-image"',
'id="flux-studio-engine-chip"',
'id="flux-runtime-summary"',
'id="flux-job-center-body"',
'id="flux-job-filter"',
'id="flux-job-list"',
'id="flux-studio-history"',
'id="flux-studio-use-in-generator"',
], 'Bestehender FLUX-Studio-Vertrag fehlt');
includesAll(loader, [
'flux-studio-ux.css?v=1.44.0',
'flux-studio-ux.js?v=1.44.0',
'data-ux-flux-studio',
'loadFluxStudioAssets()',
], 'UX-Loader bindet FLUX Studio nicht vollständig ein');
expect(pkg.scripts?.['verify:flux-studio-ux'] === 'node tools/verify-flux-studio-ux-1.44.0.mjs', 'verify:flux-studio-ux Script fehlt');
expect(pkg.scripts?.['verify:all']?.includes('npm run verify:flux-studio-ux'), 'verify:all enthält das FLUX-Studio-Gate nicht');
includesAll(js, [
'ux-flux-view-navigation',
'data-ux-flux-view',
'ux-flux-workflow',
'data-ux-flux-step',
'ux-flux-system-panel',
'ux-flux-advanced',
'ux-flux-preview-primary',
'ux-flux-job-quick-filters',
'data-ux-flux-job-filter',
'flux-studio-prompt',
'flux-studio-generate',
'flux-studio-preview-image',
'flux-job-center-body',
'flux-studio-history',
'MutationObserver',
'requestAnimationFrame',
'scrollIntoView',
'aria-selected',
'ArrowLeft',
'ArrowRight',
], 'FLUX-Studio-UX-Vertrag fehlt');
includesAll(css, [
'#flux-studio.ux-flux-studio-ready',
'.ux-flux-view-navigation',
'.ux-flux-workflow',
'.ux-flux-steps',
'.ux-flux-system-panel',
'.ux-flux-advanced',
'.ux-flux-preview-primary',
'.ux-flux-job-quick-filters',
'.ux-flux-panel-hidden',
'@media (max-width: 760px)',
'@media (max-width: 470px)',
'@media (prefers-reduced-motion: reduce)',
':focus-visible',
'var(--',
], 'FLUX-Studio-CSS-Vertrag fehlt');
expect(!/\bfetch\s*\(/.test(js), 'Additive FLUX-Studio-UX darf keine eigenen Netzwerkaufrufe ausführen');
expect(!/\bapi\s*\(/.test(js), 'Additive FLUX-Studio-UX darf die Vendoo-API nicht direkt aufrufen');
expect(!/\.innerHTML\s*=/.test(js), 'FLUX-Studio-UX darf keine innerHTML-Zuweisungen verwenden');
expect(!/\.outerHTML\s*=/.test(js), 'FLUX-Studio-UX darf keine outerHTML-Zuweisungen verwenden');
expect(!/\.onclick\s*=/.test(js), 'FLUX-Studio-UX darf keine onclick-Zuweisungen verwenden');
expect(!/confirm\s*\(/.test(js), 'Gefährliche FLUX-Aktionen müssen in der bestehenden geprüften Logik bleiben');
expect(!/\b(?:DELETE|PATCH|POST|PUT)\b/.test(js), 'FLUX-Studio-UX darf keine Schreiboperationen implementieren');
expect(!/runFluxStudioGeneration\s*\(/.test(js), 'UX-Schicht darf keine FLUX-Produktion direkt auslösen');
expect(!/deleteFluxStudioImage\s*\(/.test(js), 'UX-Schicht darf keine FLUX-Bilder direkt löschen');
expect(!/toggleFluxFavorite\s*\(/.test(js), 'UX-Schicht darf Favoritenstatus nicht direkt verändern');
expect(!/state\.flux/.test(js), 'Additive UX darf den produktiven FLUX-State nicht direkt verändern');
if (failures.length) {
console.error('FLUX Studio UX Gate fehlgeschlagen:');
for (const failure of failures) console.error(`- ${failure}`);
process.exit(1);
}
console.log('FLUX Studio UX Gate bestanden.');