- 9 nouveaux fichiers de tests (persistance, translations, fiches, indices, IHH) - Enrichissement des tests existants (graph_utils, gitea, widgets, tickets) - 67→448 tests, tous passent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
286 lines
10 KiB
Python
286 lines
10 KiB
Python
"""Tests unitaires pour le module app.fiches.utils.dynamic.indice.isg.
|
|
|
|
Ces tests verifient les fonctions de traitement Markdown pour l'indice ISG :
|
|
- _synth_isg
|
|
- build_isg_sections
|
|
"""
|
|
|
|
import textwrap
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from app.fiches.utils.dynamic.indice.isg import (
|
|
_synth_isg,
|
|
build_isg_sections,
|
|
)
|
|
|
|
# ──────────────────────────────────────────────
|
|
# Helpers
|
|
# ──────────────────────────────────────────────
|
|
|
|
def _yaml_pays_bloc(pays: list[dict]) -> str:
|
|
"""Construit un bloc YAML markdown avec des donnees de pays ISG."""
|
|
lignes = ["```yaml"]
|
|
for p in pays:
|
|
lignes.append(f"{p['id']}:")
|
|
lignes.append(f" pays: {p['pays']}")
|
|
lignes.append(f" wgi_ps: {p['wgi_ps']}")
|
|
lignes.append(f" fsi: {p['fsi']}")
|
|
lignes.append(f" ndgain: {p['ndgain']}")
|
|
lignes.append(f" isg: {p['isg']}")
|
|
lignes.append("```")
|
|
return "\n".join(lignes)
|
|
|
|
|
|
def _sample_pays(**overrides) -> dict:
|
|
"""Retourne un dictionnaire pays avec des valeurs par defaut."""
|
|
base = {
|
|
"id": "chine",
|
|
"pays": "Chine",
|
|
"wgi_ps": 35,
|
|
"fsi": 72,
|
|
"ndgain": 48,
|
|
"isg": 54,
|
|
}
|
|
base.update(overrides)
|
|
return base
|
|
|
|
|
|
def _make_isg_md(pays: list[dict], with_front_matter: bool = True,
|
|
indice_court: str = "ISG") -> str:
|
|
"""Construit un markdown complet pour ISG."""
|
|
parts = []
|
|
if with_front_matter:
|
|
parts.append(
|
|
f"---\nindice: Indice de Stabilit\u00e9 G\u00e9opolitique\n"
|
|
f"indice_court: {indice_court}\n---\n"
|
|
)
|
|
parts.append("# Indice de Stabilit\u00e9 G\u00e9opolitique (ISG)\n")
|
|
parts.append("Introduction de la fiche.\n")
|
|
parts.append("# Criticit\u00e9 par pays\n")
|
|
parts.append(_yaml_pays_bloc(pays))
|
|
parts.append("\n## Tableau de synth\u00e8se\n")
|
|
parts.append("<!---- AUTO-BEGIN:TABLEAU-FINAL -->\nancien tableau\n<!---- AUTO-END:TABLEAU-FINAL -->")
|
|
return "\n".join(parts)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _mock_pastille():
|
|
"""Mock la fonction pastille pour retourner une valeur previsible."""
|
|
with patch(
|
|
"app.fiches.utils.dynamic.indice.isg.pastille",
|
|
side_effect=lambda indice, valeur: f"[{indice}:{valeur}]",
|
|
):
|
|
yield
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# _synth_isg
|
|
# ──────────────────────────────────────────────
|
|
class TestSynthIsg:
|
|
"""Tests pour la generation du tableau de synthese ISG."""
|
|
|
|
def test_un_pays(self):
|
|
"""Test la synthese avec un seul pays."""
|
|
pays = [_sample_pays()]
|
|
md = _yaml_pays_bloc(pays)
|
|
result = _synth_isg(md)
|
|
|
|
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
|
|
assert "| :-- | :-- | :-- | :-- | :-- |" in result
|
|
assert "Chine" in result
|
|
assert "54" in result
|
|
|
|
def test_plusieurs_pays_tries_alpha(self):
|
|
"""Test que les pays sont tries alphabetiquement par nom."""
|
|
pays = [
|
|
_sample_pays(id="chine", pays="Chine", isg=54),
|
|
_sample_pays(id="australie", pays="Australie", isg=25),
|
|
_sample_pays(id="rdc", pays="RDC", isg=82),
|
|
]
|
|
md = _yaml_pays_bloc(pays)
|
|
result = _synth_isg(md)
|
|
|
|
idx_australie = result.find("Australie")
|
|
idx_chine = result.find("Chine")
|
|
idx_rdc = result.find("RDC")
|
|
assert idx_australie < idx_chine < idx_rdc
|
|
|
|
def test_toutes_colonnes_presentes(self):
|
|
"""Test que toutes les colonnes de donnees sont presentes."""
|
|
pays = [_sample_pays(wgi_ps=35, fsi=72, ndgain=48, isg=54)]
|
|
md = _yaml_pays_bloc(pays)
|
|
result = _synth_isg(md)
|
|
|
|
assert "35" in result
|
|
assert "72" in result
|
|
assert "48" in result
|
|
assert "54" in result
|
|
|
|
def test_pas_de_bloc_yaml(self):
|
|
"""Test avec un texte sans bloc yaml retourne un message par defaut."""
|
|
result = _synth_isg("Texte sans donnees YAML.")
|
|
assert "aucune donnee de pays trouvee" in result.lower() or "aucune donn" in result
|
|
|
|
def test_texte_vide(self):
|
|
"""Test avec un texte vide."""
|
|
result = _synth_isg("")
|
|
assert "aucune donn" in result
|
|
|
|
def test_nombre_lignes(self):
|
|
"""Test que le nombre de lignes correspond aux donnees."""
|
|
pays = [
|
|
_sample_pays(id="a", pays="Alpha", isg=10),
|
|
_sample_pays(id="b", pays="Beta", isg=20),
|
|
_sample_pays(id="c", pays="Gamma", isg=30),
|
|
]
|
|
md = _yaml_pays_bloc(pays)
|
|
result = _synth_isg(md)
|
|
lignes = result.strip().split("\n")
|
|
# 2 en-tetes + 3 donnees = 5
|
|
assert len(lignes) == 5
|
|
|
|
def test_pastille_incluse(self):
|
|
"""Test que la pastille est incluse dans la colonne ISG."""
|
|
pays = [_sample_pays(isg=25)]
|
|
md = _yaml_pays_bloc(pays)
|
|
result = _synth_isg(md)
|
|
|
|
# La pastille mockee retourne [ISG:valeur] avant la valeur
|
|
assert "[ISG:25]" in result
|
|
assert "25" in result
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# build_isg_sections
|
|
# ──────────────────────────────────────────────
|
|
class TestBuildIsgSections:
|
|
"""Tests pour la fonction principale de construction des sections dynamiques ISG."""
|
|
|
|
def test_remplacement_tableau_final(self):
|
|
"""Test que le tableau final est remplace entre les marqueurs."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays)
|
|
result = build_isg_sections(md)
|
|
|
|
assert "<!---- AUTO-BEGIN:TABLEAU-FINAL -->" in result
|
|
assert "<!---- AUTO-END:TABLEAU-FINAL -->" in result
|
|
assert "ancien tableau" not in result
|
|
|
|
def test_tableau_synthese_genere(self):
|
|
"""Test que le tableau de synthese est genere correctement."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays)
|
|
result = build_isg_sections(md)
|
|
|
|
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
|
|
assert "Chine" in result
|
|
|
|
def test_bloc_yaml_pays_supprime(self):
|
|
"""Test que le bloc YAML des pays est supprime de la section Criticite."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays)
|
|
result = build_isg_sections(md)
|
|
|
|
assert "# Criticit\u00e9 par pays" in result
|
|
# Le bloc YAML doit etre supprime
|
|
assert "```yaml" not in result
|
|
|
|
def test_front_matter_isg_valide(self):
|
|
"""Test que la fiche est traitee quand indice_court est ISG."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays, indice_court="ISG")
|
|
result = build_isg_sections(md)
|
|
|
|
# La fiche doit etre traitee
|
|
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
|
|
|
|
def test_front_matter_non_isg_retourne_original(self):
|
|
"""Test que la fiche n'est pas traitee si indice_court != ISG."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays, indice_court="ICS")
|
|
result = build_isg_sections(md)
|
|
|
|
# Le markdown original doit etre retourne sans modification
|
|
assert "ancien tableau" in result
|
|
|
|
def test_sans_front_matter(self):
|
|
"""Test le traitement sans front-matter YAML."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays, with_front_matter=False)
|
|
result = build_isg_sections(md)
|
|
|
|
# Sans front-matter, la fiche est quand meme traitee (pas de filtre)
|
|
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
|
|
|
|
def test_plusieurs_pays(self):
|
|
"""Test avec plusieurs pays dans le bloc YAML."""
|
|
pays = [
|
|
_sample_pays(id="australie", pays="Australie", wgi_ps=85, fsi=28, ndgain=72, isg=25),
|
|
_sample_pays(id="chine", pays="Chine", wgi_ps=35, fsi=72, ndgain=48, isg=54),
|
|
_sample_pays(id="rdc", pays="RDC", wgi_ps=15, fsi=102, ndgain=33, isg=82),
|
|
]
|
|
md = _make_isg_md(pays)
|
|
result = build_isg_sections(md)
|
|
|
|
assert "Australie" in result
|
|
assert "Chine" in result
|
|
assert "RDC" in result
|
|
|
|
def test_texte_sans_marqueurs(self):
|
|
"""Test avec un markdown sans marqueurs AUTO-BEGIN/END."""
|
|
md = textwrap.dedent("""\
|
|
---
|
|
indice_court: ISG
|
|
---
|
|
|
|
# ISG
|
|
|
|
# Criticit\u00e9 par pays
|
|
```yaml
|
|
fr:
|
|
pays: France
|
|
wgi_ps: 80
|
|
fsi: 30
|
|
ndgain: 65
|
|
isg: 28
|
|
```
|
|
|
|
## Tableau de synth\u00e8se
|
|
|
|
Pas de marqueurs ici.
|
|
""")
|
|
result = build_isg_sections(md)
|
|
# Sans marqueurs, le sub ne match pas, le tableau n'est pas remplace
|
|
assert isinstance(result, str)
|
|
|
|
def test_md_vide_avec_front_matter_isg(self):
|
|
"""Test avec un markdown minimal contenant seulement le front-matter ISG."""
|
|
md = "---\nindice_court: ISG\n---\n\nContenu minimal."
|
|
result = build_isg_sections(md)
|
|
# Pas de bloc YAML de pays, pas de marqueurs, retourne le texte en l'etat
|
|
assert "Contenu minimal." in result
|
|
|
|
def test_preservation_contenu_hors_sections(self):
|
|
"""Test que le contenu hors des sections dynamiques est preserve."""
|
|
pays = [_sample_pays()]
|
|
md = _make_isg_md(pays)
|
|
result = build_isg_sections(md)
|
|
|
|
assert "# Indice de Stabilit\u00e9 G\u00e9opolitique (ISG)" in result
|
|
assert "Introduction de la fiche." in result
|
|
|
|
def test_tri_alphabetique_dans_resultat(self):
|
|
"""Test que les pays sont tries alphabetiquement dans le resultat final."""
|
|
pays = [
|
|
_sample_pays(id="z", pays="Zambie", isg=60),
|
|
_sample_pays(id="a", pays="Albanie", isg=30),
|
|
]
|
|
md = _make_isg_md(pays)
|
|
result = build_isg_sections(md)
|
|
|
|
idx_albanie = result.find("Albanie")
|
|
idx_zambie = result.find("Zambie")
|
|
assert idx_albanie < idx_zambie
|