/* * Contrat de non-régression du portail de production. * Il vérifie la séparation stricte des environnements, la publication * dynamique des applications et les exceptions explicitement demandées. */ const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const vm = require('node:vm'); const root = path.join(__dirname, '..'); const html = fs.readFileSync(path.join(root, 'index.html'), 'utf8'); const attributions = fs.readFileSync(path.join(root, 'images', 'ATTRIBUTIONS.md'), 'utf8'); assert.equal(/^(<<<<<<<|=======|>>>>>>>)/m.test(html), false, 'aucun marqueur de conflit Git ne doit être livré'); assert.equal((html.match(/var DASHBOARD_APPS_URL/g) || []).length, 1, 'une seule URL API applications doit être déclarée'); assert.equal((html.match(/var DASHBOARD_STATUS_URL/g) || []).length, 1, 'une seule URL API statuts doit être déclarée'); assert.match(html, /var ENV = 'prod';/, 'la version production doit déclarer explicitement son environnement'); assert.match(html, /app\.urls\[ENV\]/, 'les liens doivent être sélectionnés depuis l’environnement déclaré'); assert.match(html, /app\.category === 'INFRA'/, 'les tuiles INFRA doivent rester dans leur onglet dédié'); assert.match(html, /var STATUS_REFRESH_MS = 30000;/, 'le délai de grisage doit être explicite'); assert.match(html, /setInterval\(fetchAndApplyStatuses, STATUS_REFRESH_MS\)/, 'le grisage doit être réactualisé périodiquement'); for (const imageName of ['budget-si.jpg', 'studio-portee.png']) { const imagePath = path.join(root, 'images', imageName); assert.equal(fs.existsSync(imagePath), true, `l’asset ${imageName} doit être publié`); assert.ok(fs.statSync(imagePath).size > 2048, `l’asset ${imageName} ne doit pas être vide`); assert.match(attributions, new RegExp(imageName.replace('.', '\\.')), `l’attribution de ${imageName} doit être documentée`); } const script = html.match(/