[DTP-Worker 20260803_030641] Auto exec · session 20260803_030641
CI / Contraintes NON-NÉGOCIABLES (CLAUDE.md) (push) Has been cancelled
CI / Validation JSON (schémas Faisabilité) (push) Has been cancelled
CI / Qualité documentaire (liens + 4Big) (push) Has been cancelled
CI / Reproductibilité des artefacts out/ (build == commité) (push) Has been cancelled
CI / Fraîcheur matrice de régression (run == commité) (push) Has been cancelled
CI / Intégrité du câblage CI (gate agrège tout · gates statiques verrouillés) (push) Has been cancelled
CI / Intégrité des chiffres du README (valeur == artefact cité · (push) Has been cancelled
CI / Publiciste · parser + schéma + generator (unittest) (push) Has been cancelled
CI / RBAC · 50 rôles + schéma (unittest) (push) Has been cancelled
CI / Faisabilité · générateur 4 volets + round-trip (unittest) (push) Has been cancelled
CI / RBAC · fixtures ERPNext (Role + Custom DocPerm) (push) Has been cancelled
CI / RBAC · plan User Permission (row-level) (push) Has been cancelled
CI / RBAC · Role Profile (bundles par portail) (push) Has been cancelled
CI / RBAC · run-book d'application unifié (agrégat 3 volets) (push) Has been cancelled
CI / Faisabilité · dossier bancable trilingue FR/EN/ES (push) Has been cancelled
CI / CRM · workflow vente ERPNext (lead → CONFOTUR) (push) Has been cancelled
CI / CRM · DocType porteur OTO Dossier Vente (push) Has been cancelled
CI / CRM · barème commissions vendeurs (push) Has been cancelled
CI / Fiscal · e-CF DGII (Compupar) (push) Has been cancelled
CI / Frontend · Workspaces 5 portails rôle (push) Has been cancelled
CI / Legal · DocType CONFOTUR Application (push) Has been cancelled
CI / QA · Audit 5D conformité (push) Has been cancelled
CI / SEO · mots-clés trilingues + schema.org + hreflang (push) Has been cancelled
CI / Chat OTOIA · montage par portail (Custom Block) (push) Has been cancelled
CI / QA · Audit 4Big (95+/100 sur 100% deliverables) (push) Has been cancelled
CI / Démo · Scénarios (run-sheet P07 banquier / P05 client) (push) Has been cancelled
CI / QA · Matrice de régression exhaustive (Sprint 8) (push) Has been cancelled
CI / DevOps · Run-book de déploiement VPS unifié (Sprint 8) (push) Has been cancelled
CI / QA · Matrice d'acceptation / traçabilité MVP (Sprint 8) (push) Has been cancelled
CI / Mobile · config app Expo/EAS (navigation par rôle) (push) Has been cancelled
CI / E2E baseline Playwright (manuel) (push) Has been cancelled
CI / Gate qualité (agrégat) (push) Has been cancelled

This commit is contained in:
Claude Code DTP Worker
2026-08-03 03:21:42 +00:00
parent 3eec69a87f
commit d0b354f81e
14 changed files with 302 additions and 21 deletions
@@ -1,10 +1,13 @@
"""Tests du générateur de config app mobile (Sprint 5 · Mobile).
Stdlib pur (unittest) — aucune dépendance pip. Couvre :
- conformité au schéma + les 12 invariants du CLI (chemin nominal) ;
- conformité au schéma + les 15 invariants du CLI (chemin nominal) ;
- la cross-cohérence RBAC ↔ portails ↔ seo (onglets, rôles, labels/icônes, langues) ;
- la fiche store dérivée (langues seo, limites de caractères, portails/langues
injectés depuis la surface réelle) ;
- l'anti-invention (#6) par injections négatives (identifiant de store fabriqué,
rôles désynchronisés de la surface RBAC, langue inventée, token de marque altéré).
rôles désynchronisés de la surface RBAC, langue inventée, token de marque altéré,
description store dépassant la limite ou désalignée des portails réels).
"""
from __future__ import annotations
@@ -113,6 +116,38 @@ class TestNominal(unittest.TestCase):
self.assertEqual(a, b)
class TestStoreListing(unittest.TestCase):
"""Fiche store : couverture langues, limites de caractères, injection sourcée."""
def setUp(self):
self.bundle = build()
self.sl = self.bundle["store_listing"]
def test_langues_egal_seo(self):
langs, _ = deps.load_langs()
self.assertEqual(sorted(self.sl["content"].keys()), sorted(langs))
self.assertEqual(self.sl["langues"], list(langs))
def test_limites_caracteres_store(self):
spec = deps.load_spec()
limits = spec["store_listing"]["limits"]
for lang, fields in self.sl["content"].items():
for champ, limit in limits.items():
self.assertTrue(fields.get(champ), f"{lang}.{champ} vide")
self.assertLessEqual(len(fields[champ]), limit, f"{lang}.{champ} > {limit}")
def test_portails_et_langues_injectes(self):
"""Anti-dérive : la copie cite les portails/langues RÉELS, pas une liste figée."""
langs, _ = deps.load_langs()
nav = self.bundle["role_navigation"]
portails_str = " · ".join(n["label"] for n in nav)
langues_str = "/".join(l.upper() for l in langs)
for lang, fields in self.sl["content"].items():
self.assertIn(portails_str, fields["full_description"])
self.assertIn(langues_str, fields["full_description"])
self.assertNotIn("{", fields["full_description"])
class TestAntiInvention(unittest.TestCase):
"""Injections négatives : chaque garde-fou doit MORDRE (invariant → erreur)."""
@@ -149,6 +184,18 @@ class TestAntiInvention(unittest.TestCase):
errs = gen._validate_bundle(bad)
self.assertTrue(any("ordre des onglets" in e for e in errs), errs)
def test_fiche_store_trop_longue_detecte(self):
bad = copy.deepcopy(self.bundle)
bad["store_listing"]["content"]["fr"]["subtitle"] = "x" * 200
errs = gen._validate_bundle(bad)
self.assertTrue(any("limite store" in e for e in errs), errs)
def test_fiche_store_portails_desalignes_detecte(self):
bad = copy.deepcopy(self.bundle)
bad["store_listing"]["content"]["en"]["full_description"] = "No portals listed here."
errs = gen._validate_bundle(bad)
self.assertTrue(any("full_description" in e for e in errs), errs)
if __name__ == "__main__":
unittest.main()