All checks were successful
Validation applicative / Tests de contrat (push) Successful in 17s
92 lines
3.6 KiB
JavaScript
92 lines
3.6 KiB
JavaScript
/*
|
||
* 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(/<script>([\s\S]*?)<\/script>/)?.[1];
|
||
assert.ok(script, 'le script dynamique du portail doit être présent');
|
||
|
||
const elements = new Map();
|
||
function element(id) {
|
||
if (!elements.has(id)) {
|
||
elements.set(id, {
|
||
innerHTML: '',
|
||
textContent: '',
|
||
classList: { toggle() {} },
|
||
setAttribute() {}
|
||
});
|
||
}
|
||
return elements.get(id);
|
||
}
|
||
|
||
const sandbox = {
|
||
AbortController,
|
||
Map,
|
||
Set,
|
||
URL,
|
||
console,
|
||
document: {
|
||
addEventListener() {},
|
||
getElementById: element,
|
||
querySelectorAll() { return []; }
|
||
},
|
||
setInterval() {},
|
||
setTimeout() { return 0; },
|
||
clearTimeout() {}
|
||
};
|
||
vm.createContext(sandbox);
|
||
vm.runInContext(script, sandbox);
|
||
|
||
sandbox.renderApps([
|
||
{
|
||
id: 'itinova-budget-si',
|
||
name: 'Gestion budget informatique',
|
||
category: 'SANTINOVA',
|
||
image: 'images/budget-si.jpg',
|
||
urls: { prod: 'https://budget-si.santinova-soft.org' },
|
||
status: 'online',
|
||
containerRunning: true
|
||
},
|
||
{
|
||
id: 'santelis-gestion',
|
||
name: 'SANTELIS Gestion',
|
||
category: 'SANTINOVA',
|
||
image: 'images/santelis-gestion.png',
|
||
urls: { prod: 'https://gestion-santelis.santinova-soft.org' },
|
||
status: 'online',
|
||
containerRunning: true
|
||
}
|
||
]);
|
||
|
||
const santinovaMarkup = element('grid-santinova').innerHTML;
|
||
assert.match(santinovaMarkup, /Gestion budget informatique/, 'Budget informatique doit être rendu dans le portail production');
|
||
assert.doesNotMatch(santinovaMarkup, /SANTELIS Gestion/, 'SANTELIS Gestion ne doit pas être rendu dans le portail production');
|
||
assert.equal(element('count-santinova').textContent, 1, 'le compteur Santinova ne doit retenir que les applications visibles');
|
||
|
||
console.log('OK portal-contract');
|