# Tests du moteur (v2.3)

Finalisation publique : `node open-data/moteur/tests/navigation.mjs` couvre
désormais 13 tests, dont l'absence de calcul pour les chiffrages indisponibles,
le refus des tests dans l'interface publique et l'atelier limité à localhost.
`test_refonte.py` ajoute 38 × 12 = 456 comparaisons annuelles pour le pessimiste
à programme intégral (10 tests, 2 736 comparaisons annuelles au total).

- Depuis la racine : `node open-data/moteur/tests/navigation.mjs` — 9 tests des vrais gestionnaires de navigation : candidats uniques, variantes propres à chaque candidat, déclaratif séparé, tests techniques sans verdict, scénario conservé, concurrence et échecs de chargement, imports. Compléter par une vérification navigateur.

- Depuis la racine : `python3 open-data/moteur/tests/test_dynamique.py` — extension expérimentale, 38 profils × 3 variantes × 12 années, propriétés économiques/comptables et aller-retour d'export. Ne régénère pas les golden historiques. Voir [contrat et limites](../DYNAMIQUE_EXPERIMENTALE.md).

- `node run_tests.mjs` — golden (tous les profils publics), rejets explicites des entrées hors domaine, stress crise/guerre, propriétés (impulsion réversible, inflation ≠ potentiel, potentiel signé, emploi symétrique, Garant immuable), cohérence du corpus. Écrit `resultats_tests.json`. La première exécution crée `golden.json` ; toute modification du moteur ou des profils doit régénérer les golden **et** être consignée dans le journal du moteur.
- `python3 parite.py` — rejoue les mêmes profils avec `moteur_v2.py` et exige `|écart| < 0,0005` point sur dette, solde et dépenses 2037 ; vérifie que Python rejette les mêmes entrées.
- `../profils_publics.json` — export au schéma `fr2027-profil/3` de tous les profils affichés sur le site (auteur × scénarios × écoles, candidats, crash-tests), régénéré à chaque build.
- `node xss_regression.mjs` — régression XSS (import de profils) : charges `<img onerror>`, `<svg onload>`, `"><script>`, `<a href="javascript:">` acceptées comme **texte** dans `nom`/`doc`, champs mal typés refusés (`nom`, `doc`, `conf`), gabarit de `construireLeviers` sans aucune chaîne du profil.
- `xss_regression.html` — même régression dans un vrai navigateur (servir le site en local, ouvrir `/open-data/moteur/tests/xss_regression.html`) : import par le bouton, export/réimport, sauvegarde locale, pont inter-pages ; titre de l'onglet `XSS-OK n/n tirs=0` attendu. `?cible=<autre page>` pour rejouer contre une autre version.
- `node profils_candidats.mjs` — vérifie que `profils_publics.json` et `profils_index.json` concordent avec l'objet `PROGRAMMES` de la page `/candidats/`, qui est la source ; `--ecrire <clé…>` réexporte les profils nommés depuis la page (nom, leviers, libellé d'index seulement).
- `node rn_trajectoire.mjs` puis `python3 rn_parite_annuelle.py` — contrôles de la mise à jour RN du 06/10/2026 : passage documentaire 125 → 140 Mds (+15, +12 %), convention de signe, rampe et effet 2032 du levier `ecoRN`, interdiction de remplacer le coût `ret60CL` (9) par les 15-20 Mds d'économies annoncés, absence de double compte avec le contre-budget 2027, valeurs 2032 et 2037 de la production, cohérence page ↔ profils ↔ index ↔ corpus ↔ `build.json`, profil posé pour le simulateur ; parité JavaScript/Python sur chaque année 2026-2037. Écrit `resultats_rn.json`.
- Depuis la racine : `python3 open-data/moteur/tests/test_refonte.py` — V2 : 38 profils × 3 variantes et 38 profils × 2 scénarios de supplément annuel, soit 2 280 points annuels comparés JS/Python. Vérifie aussi le bilan de dette, l'absence de cumul des deux modes de croissance, le rejeu des exports et les entrées invalides. Contrat : [refonte V2](../REFONTE_V2.md).
