- 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>
786 lines
31 KiB
Python
786 lines
31 KiB
Python
"""Tests unitaires pour le module app.fiches.utils.dynamic.indice.ihh.
|
|
|
|
Ces tests verifient les fonctions de traitement des indices IHH :
|
|
- _extraire_donnees_operations : extraction et organisation des donnees
|
|
- _generer_tableau_produits : generation de tableau markdown produits
|
|
- _generer_tableau_composants : generation de tableau markdown composants
|
|
- _generer_tableau_minerais : generation de tableau markdown minerais
|
|
- _synth_ihh : synthese des tableaux IHH
|
|
- build_ihh_sections : construction des sections dynamiques markdown
|
|
"""
|
|
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from app.fiches.utils.dynamic.indice.ihh import (
|
|
IHH_RE,
|
|
_extraire_donnees_operations,
|
|
_generer_tableau_composants,
|
|
_generer_tableau_minerais,
|
|
_generer_tableau_produits,
|
|
_synth_ihh,
|
|
build_ihh_sections,
|
|
)
|
|
|
|
# ──────────────────────────────────────────────
|
|
# Fixtures
|
|
# ──────────────────────────────────────────────
|
|
|
|
@pytest.fixture
|
|
def operation_minerai():
|
|
"""Operation type minerai avec extraction, reserves et traitement."""
|
|
return {
|
|
"minerai": "Lithium",
|
|
"extraction": {"ihh_pays": 1500, "ihh_acteurs": 2000},
|
|
"reserves": {"ihh_pays": 1800},
|
|
"traitement": {"ihh_pays": 900, "ihh_acteurs": 1100},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def operation_produit():
|
|
"""Operation type produit avec assemblage."""
|
|
return {
|
|
"produit": "Batterie",
|
|
"assemblage": {"ihh_pays": 3000, "ihh_acteurs": 2500},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def operation_composant():
|
|
"""Operation type composant avec fabrication."""
|
|
return {
|
|
"composant": "Cathode",
|
|
"fabrication": {"ihh_pays": 1200, "ihh_acteurs": 800},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_pastille():
|
|
"""Mock la fonction pastille pour retourner une valeur previsible."""
|
|
with patch("app.fiches.utils.dynamic.indice.ihh.pastille", side_effect=lambda indice, valeur: f"[{indice}:{valeur}]") as m:
|
|
yield m
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# IHH_RE (regex)
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestIhhRegex:
|
|
"""Tests pour la regex IHH_RE."""
|
|
|
|
def test_match_bloc_yaml_simple(self):
|
|
"""Test la detection d'un bloc YAML operation basique."""
|
|
# Le pattern cherche "opération:" (avec accent)
|
|
texte = "```yaml\n op\u00e9ration:\n minerai: Lithium\n```"
|
|
matches = list(IHH_RE.finditer(texte))
|
|
assert len(matches) == 1
|
|
|
|
def test_match_insensible_casse(self):
|
|
"""Test que la regex est insensible a la casse du mot YAML."""
|
|
texte = "```YAML\n op\u00e9ration:\n minerai: Cobalt\n```"
|
|
matches = list(IHH_RE.finditer(texte))
|
|
assert len(matches) == 1
|
|
|
|
def test_pas_de_match_sans_operation(self):
|
|
"""Test qu'un bloc YAML sans 'operation' n'est pas capture."""
|
|
texte = "```yaml\n autre_cle: valeur\n```"
|
|
matches = list(IHH_RE.finditer(texte))
|
|
assert len(matches) == 0
|
|
|
|
def test_match_multiple_blocs(self):
|
|
"""Test la detection de plusieurs blocs YAML operation."""
|
|
texte = (
|
|
"Intro\n"
|
|
"```yaml\n op\u00e9ration:\n minerai: Lithium\n```\n"
|
|
"texte entre\n"
|
|
"```yaml\n op\u00e9ration:\n produit: Batterie\n```\n"
|
|
)
|
|
matches = list(IHH_RE.finditer(texte))
|
|
assert len(matches) == 2
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# _extraire_donnees_operations
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestExtraireDonneesOperations:
|
|
"""Tests pour la fonction _extraire_donnees_operations."""
|
|
|
|
def test_operation_minerai(self, operation_minerai):
|
|
"""Test l'extraction des donnees pour une operation minerai."""
|
|
resultat = _extraire_donnees_operations([operation_minerai])
|
|
|
|
assert "Lithium" in resultat
|
|
data = resultat["Lithium"]
|
|
assert data["type"] == "minerai"
|
|
assert data["extraction_ihh_pays"] == 1500
|
|
assert data["extraction_ihh_acteurs"] == 2000
|
|
assert data["reserves_ihh_pays"] == 1800
|
|
assert data["traitement_ihh_pays"] == 900
|
|
assert data["traitement_ihh_acteurs"] == 1100
|
|
|
|
def test_operation_produit(self, operation_produit):
|
|
"""Test l'extraction des donnees pour une operation produit."""
|
|
resultat = _extraire_donnees_operations([operation_produit])
|
|
|
|
assert "Batterie" in resultat
|
|
data = resultat["Batterie"]
|
|
assert data["type"] == "produit"
|
|
assert data["assemblage_ihh_pays"] == 3000
|
|
assert data["assemblage_ihh_acteurs"] == 2500
|
|
|
|
def test_operation_composant(self, operation_composant):
|
|
"""Test l'extraction des donnees pour une operation composant."""
|
|
resultat = _extraire_donnees_operations([operation_composant])
|
|
|
|
assert "Cathode" in resultat
|
|
data = resultat["Cathode"]
|
|
assert data["type"] == "composant"
|
|
assert data["fabrication_ihh_pays"] == 1200
|
|
assert data["fabrication_ihh_acteurs"] == 800
|
|
|
|
def test_operations_multiples_types(self, operation_minerai, operation_produit, operation_composant):
|
|
"""Test l'extraction avec des operations de types differents."""
|
|
resultat = _extraire_donnees_operations([operation_minerai, operation_produit, operation_composant])
|
|
|
|
assert len(resultat) == 3
|
|
assert resultat["Lithium"]["type"] == "minerai"
|
|
assert resultat["Batterie"]["type"] == "produit"
|
|
assert resultat["Cathode"]["type"] == "composant"
|
|
|
|
def test_liste_vide(self):
|
|
"""Test avec une liste d'operations vide."""
|
|
resultat = _extraire_donnees_operations([])
|
|
|
|
assert resultat == {}
|
|
|
|
def test_operation_sans_identifiant(self):
|
|
"""Test qu'une operation sans minerai, produit ou composant est ignoree."""
|
|
operation = {"autre_cle": "valeur"}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat == {}
|
|
|
|
def test_operation_identifiant_vide(self):
|
|
"""Test qu'une operation avec identifiant vide est ignoree."""
|
|
operation = {"minerai": "", "extraction": {"ihh_pays": 100}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat == {}
|
|
|
|
def test_valeurs_par_defaut_minerai(self):
|
|
"""Test que les valeurs par defaut sont '-' pour un nouveau minerai."""
|
|
operation = {"minerai": "Cobalt", "extraction": {"ihh_pays": 500, "ihh_acteurs": 600}, "reserves": {"ihh_pays": 700}, "traitement": {"ihh_pays": 400, "ihh_acteurs": 300}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
data = resultat["Cobalt"]
|
|
# Les champs non lies a l'extraction doivent rester a '-'
|
|
assert data["assemblage_ihh_pays"] == "-"
|
|
assert data["assemblage_ihh_acteurs"] == "-"
|
|
assert data["fabrication_ihh_pays"] == "-"
|
|
assert data["fabrication_ihh_acteurs"] == "-"
|
|
|
|
def test_valeurs_par_defaut_produit(self, operation_produit):
|
|
"""Test que les valeurs par defaut sont '-' pour un nouveau produit."""
|
|
resultat = _extraire_donnees_operations([operation_produit])
|
|
|
|
data = resultat["Batterie"]
|
|
assert data["extraction_ihh_pays"] == "-"
|
|
assert data["extraction_ihh_acteurs"] == "-"
|
|
assert data["reserves_ihh_pays"] == "-"
|
|
assert data["traitement_ihh_pays"] == "-"
|
|
assert data["traitement_ihh_acteurs"] == "-"
|
|
|
|
def test_valeurs_par_defaut_composant(self, operation_composant):
|
|
"""Test que les valeurs par defaut sont '-' pour un nouveau composant."""
|
|
resultat = _extraire_donnees_operations([operation_composant])
|
|
|
|
data = resultat["Cathode"]
|
|
assert data["extraction_ihh_pays"] == "-"
|
|
assert data["assemblage_ihh_pays"] == "-"
|
|
|
|
def test_detection_type_minerai_par_extraction(self):
|
|
"""Test que le type 'minerai' est detecte par la cle 'extraction'."""
|
|
operation = {"minerai": "Fer", "extraction": {"ihh_pays": 100}, "reserves": {}, "traitement": {}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat["Fer"]["type"] == "minerai"
|
|
|
|
def test_detection_type_minerai_par_reserves(self):
|
|
"""Test que le type 'minerai' est detecte par la cle 'reserves'."""
|
|
operation = {"minerai": "Cuivre", "reserves": {"ihh_pays": 200}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat["Cuivre"]["type"] == "minerai"
|
|
|
|
def test_detection_type_minerai_par_traitement(self):
|
|
"""Test que le type 'minerai' est detecte par la cle 'traitement'."""
|
|
operation = {"minerai": "Zinc", "traitement": {"ihh_pays": 300}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat["Zinc"]["type"] == "minerai"
|
|
|
|
def test_detection_type_produit_par_assemblage(self):
|
|
"""Test que le type 'produit' est detecte par la cle 'assemblage'."""
|
|
operation = {"produit": "Ecran", "assemblage": {"ihh_pays": 100}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat["Ecran"]["type"] == "produit"
|
|
|
|
def test_detection_type_composant_par_defaut(self):
|
|
"""Test que le type 'composant' est attribue par defaut sans cles specifiques."""
|
|
operation = {"composant": "Puce", "fabrication": {"ihh_pays": 500}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert resultat["Puce"]["type"] == "composant"
|
|
|
|
def test_extraction_valeurs_manquantes_dans_sous_dict(self):
|
|
"""Test avec des cles manquantes dans les sous-dictionnaires d'extraction."""
|
|
operation = {
|
|
"minerai": "Titane",
|
|
"extraction": {}, # Pas de ihh_pays ni ihh_acteurs
|
|
"reserves": {},
|
|
"traitement": {},
|
|
}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
data = resultat["Titane"]
|
|
assert data["extraction_ihh_pays"] == "-"
|
|
assert data["extraction_ihh_acteurs"] == "-"
|
|
assert data["reserves_ihh_pays"] == "-"
|
|
assert data["traitement_ihh_pays"] == "-"
|
|
assert data["traitement_ihh_acteurs"] == "-"
|
|
|
|
def test_assemblage_valeurs_manquantes(self):
|
|
"""Test avec des cles manquantes dans le sous-dictionnaire assemblage."""
|
|
operation = {"produit": "Smartphone", "assemblage": {}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
data = resultat["Smartphone"]
|
|
assert data["assemblage_ihh_pays"] == "-"
|
|
assert data["assemblage_ihh_acteurs"] == "-"
|
|
|
|
def test_fabrication_valeurs_manquantes(self):
|
|
"""Test avec des cles manquantes dans le sous-dictionnaire fabrication."""
|
|
operation = {"composant": "Resistance", "fabrication": {}}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
data = resultat["Resistance"]
|
|
assert data["fabrication_ihh_pays"] == "-"
|
|
assert data["fabrication_ihh_acteurs"] == "-"
|
|
|
|
def test_meme_minerai_deux_operations(self):
|
|
"""Test que deux operations sur le meme minerai fusionnent les donnees."""
|
|
op1 = {"minerai": "Lithium", "extraction": {"ihh_pays": 100, "ihh_acteurs": 200}, "reserves": {"ihh_pays": 300}, "traitement": {"ihh_pays": 400, "ihh_acteurs": 500}}
|
|
# Deuxieme operation avec fabrication sur le meme identifiant
|
|
# (cas improbable mais le code le gere)
|
|
op2 = {"minerai": "Lithium", "fabrication": {"ihh_pays": 600, "ihh_acteurs": 700}}
|
|
|
|
resultat = _extraire_donnees_operations([op1, op2])
|
|
|
|
assert len(resultat) == 1
|
|
data = resultat["Lithium"]
|
|
# Les donnees extraction de la premiere operation sont conservees
|
|
assert data["extraction_ihh_pays"] == 100
|
|
# Les donnees fabrication de la seconde operation sont ajoutees
|
|
assert data["fabrication_ihh_pays"] == 600
|
|
assert data["fabrication_ihh_acteurs"] == 700
|
|
|
|
def test_priorite_identifiant_minerai_sur_produit(self):
|
|
"""Test que l'identifiant minerai est prioritaire sur produit et composant."""
|
|
operation = {"minerai": "Fer", "produit": "Acier", "composant": "Plaque"}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
# minerai est evalue en premier dans le get chain
|
|
assert "Fer" in resultat
|
|
assert "Acier" not in resultat
|
|
assert "Plaque" not in resultat
|
|
|
|
def test_priorite_identifiant_produit_sur_composant(self):
|
|
"""Test que l'identifiant produit est prioritaire sur composant."""
|
|
operation = {"produit": "Acier", "composant": "Plaque"}
|
|
resultat = _extraire_donnees_operations([operation])
|
|
|
|
assert "Acier" in resultat
|
|
assert "Plaque" not in resultat
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# _generer_tableau_produits
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestGenererTableauProduits:
|
|
"""Tests pour la fonction _generer_tableau_produits."""
|
|
|
|
def test_dict_vide(self):
|
|
"""Test qu'un dictionnaire vide retourne une chaine vide."""
|
|
assert _generer_tableau_produits({}) == ""
|
|
|
|
def test_un_produit(self, mock_pastille):
|
|
"""Test la generation d'un tableau avec un seul produit."""
|
|
produits = {
|
|
"Batterie": {
|
|
"type": "produit",
|
|
"assemblage_ihh_pays": 3000,
|
|
"assemblage_ihh_acteurs": 2500,
|
|
}
|
|
}
|
|
|
|
resultat = _generer_tableau_produits(produits)
|
|
|
|
assert "## Assemblage des produits" in resultat
|
|
assert "| Batterie |" in resultat
|
|
assert "| Produit | Assemblage IHH Pays | Assemblage IHH Acteurs |" in resultat
|
|
assert "| :-- | :--: | :--: |" in resultat
|
|
assert "[IHH:3000]" in resultat
|
|
assert "[IHH:2500]" in resultat
|
|
|
|
def test_plusieurs_produits_tries(self, mock_pastille):
|
|
"""Test que les produits sont tries par ordre alphabetique."""
|
|
produits = {
|
|
"Smartphone": {"type": "produit", "assemblage_ihh_pays": 100, "assemblage_ihh_acteurs": 200},
|
|
"Batterie": {"type": "produit", "assemblage_ihh_pays": 300, "assemblage_ihh_acteurs": 400},
|
|
"Ecran": {"type": "produit", "assemblage_ihh_pays": 500, "assemblage_ihh_acteurs": 600},
|
|
}
|
|
|
|
resultat = _generer_tableau_produits(produits)
|
|
|
|
# Verifier l'ordre : Batterie < Ecran < Smartphone
|
|
idx_batterie = resultat.index("Batterie")
|
|
idx_ecran = resultat.index("Ecran")
|
|
idx_smartphone = resultat.index("Smartphone")
|
|
assert idx_batterie < idx_ecran < idx_smartphone
|
|
|
|
def test_valeur_tiret(self, mock_pastille):
|
|
"""Test avec des valeurs '-' (donnees manquantes)."""
|
|
produits = {
|
|
"Produit": {"type": "produit", "assemblage_ihh_pays": "-", "assemblage_ihh_acteurs": "-"},
|
|
}
|
|
|
|
resultat = _generer_tableau_produits(produits)
|
|
|
|
assert "[IHH:-]" in resultat
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# _generer_tableau_composants
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestGenererTableauComposants:
|
|
"""Tests pour la fonction _generer_tableau_composants."""
|
|
|
|
def test_dict_vide(self):
|
|
"""Test qu'un dictionnaire vide retourne une chaine vide."""
|
|
assert _generer_tableau_composants({}) == ""
|
|
|
|
def test_un_composant(self, mock_pastille):
|
|
"""Test la generation d'un tableau avec un seul composant."""
|
|
composants = {
|
|
"Cathode": {
|
|
"type": "composant",
|
|
"fabrication_ihh_pays": 1200,
|
|
"fabrication_ihh_acteurs": 800,
|
|
}
|
|
}
|
|
|
|
resultat = _generer_tableau_composants(composants)
|
|
|
|
assert "## Fabrication des composants" in resultat
|
|
assert "| Cathode |" in resultat
|
|
assert "| Composant | Fabrication IHH Pays | Fabrication IHH Acteurs |" in resultat
|
|
assert "| :-- | :--: | :--: |" in resultat
|
|
assert "[IHH:1200]" in resultat
|
|
assert "[IHH:800]" in resultat
|
|
|
|
def test_plusieurs_composants_tries(self, mock_pastille):
|
|
"""Test que les composants sont tries par ordre alphabetique."""
|
|
composants = {
|
|
"Puce": {"type": "composant", "fabrication_ihh_pays": 100, "fabrication_ihh_acteurs": 200},
|
|
"Anode": {"type": "composant", "fabrication_ihh_pays": 300, "fabrication_ihh_acteurs": 400},
|
|
"Cathode": {"type": "composant", "fabrication_ihh_pays": 500, "fabrication_ihh_acteurs": 600},
|
|
}
|
|
|
|
resultat = _generer_tableau_composants(composants)
|
|
|
|
idx_anode = resultat.index("Anode")
|
|
idx_cathode = resultat.index("Cathode")
|
|
idx_puce = resultat.index("Puce")
|
|
assert idx_anode < idx_cathode < idx_puce
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# _generer_tableau_minerais
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestGenererTableauMinerais:
|
|
"""Tests pour la fonction _generer_tableau_minerais."""
|
|
|
|
def test_dict_vide(self):
|
|
"""Test qu'un dictionnaire vide retourne une chaine vide."""
|
|
assert _generer_tableau_minerais({}) == ""
|
|
|
|
def test_un_minerai(self, mock_pastille):
|
|
"""Test la generation d'un tableau avec un seul minerai."""
|
|
minerais = {
|
|
"Lithium": {
|
|
"type": "minerai",
|
|
"extraction_ihh_pays": 1500,
|
|
"extraction_ihh_acteurs": 2000,
|
|
"reserves_ihh_pays": 1800,
|
|
"traitement_ihh_pays": 900,
|
|
"traitement_ihh_acteurs": 1100,
|
|
}
|
|
}
|
|
|
|
resultat = _generer_tableau_minerais(minerais)
|
|
|
|
assert "## Op\u00e9rations sur les minerais" in resultat
|
|
assert "| Lithium |" in resultat
|
|
assert "| Minerai | Extraction IHH Pays | Extraction IHH Acteurs | R\u00e9serves IHH Pays | Traitement IHH Pays | Traitement IHH Acteurs |" in resultat
|
|
assert "| :-- | :--: | :--: | :--: | :--: | :--: |" in resultat
|
|
assert "[IHH:1500]" in resultat
|
|
assert "[IHH:2000]" in resultat
|
|
assert "[IHH:1800]" in resultat
|
|
assert "[IHH:900]" in resultat
|
|
assert "[IHH:1100]" in resultat
|
|
|
|
def test_plusieurs_minerais_tries(self, mock_pastille):
|
|
"""Test que les minerais sont tries par ordre alphabetique."""
|
|
minerais = {
|
|
"Zinc": {"type": "minerai", "extraction_ihh_pays": 1, "extraction_ihh_acteurs": 2, "reserves_ihh_pays": 3, "traitement_ihh_pays": 4, "traitement_ihh_acteurs": 5},
|
|
"Cobalt": {"type": "minerai", "extraction_ihh_pays": 6, "extraction_ihh_acteurs": 7, "reserves_ihh_pays": 8, "traitement_ihh_pays": 9, "traitement_ihh_acteurs": 10},
|
|
"Lithium": {"type": "minerai", "extraction_ihh_pays": 11, "extraction_ihh_acteurs": 12, "reserves_ihh_pays": 13, "traitement_ihh_pays": 14, "traitement_ihh_acteurs": 15},
|
|
}
|
|
|
|
resultat = _generer_tableau_minerais(minerais)
|
|
|
|
idx_cobalt = resultat.index("Cobalt")
|
|
idx_lithium = resultat.index("Lithium")
|
|
idx_zinc = resultat.index("Zinc")
|
|
assert idx_cobalt < idx_lithium < idx_zinc
|
|
|
|
def test_minerai_avec_tirets(self, mock_pastille):
|
|
"""Test avec des valeurs '-' (donnees manquantes)."""
|
|
minerais = {
|
|
"Fer": {
|
|
"type": "minerai",
|
|
"extraction_ihh_pays": "-",
|
|
"extraction_ihh_acteurs": "-",
|
|
"reserves_ihh_pays": "-",
|
|
"traitement_ihh_pays": "-",
|
|
"traitement_ihh_acteurs": "-",
|
|
}
|
|
}
|
|
|
|
resultat = _generer_tableau_minerais(minerais)
|
|
|
|
assert "| Fer |" in resultat
|
|
# 5 pastilles avec valeur "-"
|
|
assert resultat.count("[IHH:-]") == 5
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# _synth_ihh
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestSynthIhh:
|
|
"""Tests pour la fonction _synth_ihh."""
|
|
|
|
def test_liste_vide(self, mock_pastille):
|
|
"""Test avec une liste d'operations vide."""
|
|
resultat = _synth_ihh([])
|
|
|
|
assert resultat == ""
|
|
|
|
def test_une_operation_minerai(self, operation_minerai, mock_pastille):
|
|
"""Test avec une seule operation minerai."""
|
|
resultat = _synth_ihh([operation_minerai])
|
|
|
|
assert "## Op\u00e9rations sur les minerais" in resultat
|
|
assert "Lithium" in resultat
|
|
# Pas de tableau produits ni composants
|
|
assert "## Assemblage des produits" not in resultat
|
|
assert "## Fabrication des composants" not in resultat
|
|
|
|
def test_une_operation_produit(self, operation_produit, mock_pastille):
|
|
"""Test avec une seule operation produit."""
|
|
resultat = _synth_ihh([operation_produit])
|
|
|
|
assert "## Assemblage des produits" in resultat
|
|
assert "Batterie" in resultat
|
|
assert "## Op\u00e9rations sur les minerais" not in resultat
|
|
|
|
def test_une_operation_composant(self, operation_composant, mock_pastille):
|
|
"""Test avec une seule operation composant."""
|
|
resultat = _synth_ihh([operation_composant])
|
|
|
|
assert "## Fabrication des composants" in resultat
|
|
assert "Cathode" in resultat
|
|
|
|
def test_toutes_categories(self, operation_minerai, operation_produit, operation_composant, mock_pastille):
|
|
"""Test avec les trois categories d'operations."""
|
|
resultat = _synth_ihh([operation_minerai, operation_produit, operation_composant])
|
|
|
|
assert "## Assemblage des produits" in resultat
|
|
assert "## Fabrication des composants" in resultat
|
|
assert "## Op\u00e9rations sur les minerais" in resultat
|
|
|
|
def test_operations_sans_identifiant(self, mock_pastille):
|
|
"""Test que les operations sans identifiant sont ignorees."""
|
|
operations = [{"autre_cle": "valeur"}]
|
|
resultat = _synth_ihh(operations)
|
|
|
|
assert resultat == ""
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
# build_ihh_sections
|
|
# ──────────────────────────────────────────────
|
|
|
|
class TestBuildIhhSections:
|
|
"""Tests pour la fonction build_ihh_sections."""
|
|
|
|
def test_markdown_sans_bloc_yaml(self):
|
|
"""Test qu'un markdown sans bloc YAML est retourne tel quel."""
|
|
md = "# Titre\n\nContenu normal sans bloc YAML."
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert resultat == md
|
|
|
|
def test_markdown_vide(self):
|
|
"""Test avec un markdown vide."""
|
|
resultat = build_ihh_sections("")
|
|
|
|
assert resultat == ""
|
|
|
|
def test_un_bloc_yaml_simple(self, mock_pastille):
|
|
"""Test avec un seul bloc YAML operation."""
|
|
md = (
|
|
"Introduction\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" minerai: Lithium\n"
|
|
" extraction:\n"
|
|
" ihh_pays: 1500\n"
|
|
" ihh_acteurs: 2000\n"
|
|
" reserves:\n"
|
|
" ihh_pays: 1800\n"
|
|
" traitement:\n"
|
|
" ihh_pays: 900\n"
|
|
" ihh_acteurs: 1100\n"
|
|
"```\n"
|
|
"Section apres le bloc."
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert "Introduction" in resultat
|
|
assert "Section apres le bloc." in resultat
|
|
# Le bloc YAML brut ne doit plus etre present
|
|
assert "```yaml" not in resultat
|
|
|
|
def test_jinja_template_dans_section(self, mock_pastille):
|
|
"""Test que les templates Jinja2 sont rendus avec les donnees de l'operation."""
|
|
md = (
|
|
"Intro\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" minerai: Lithium\n"
|
|
" extraction:\n"
|
|
" ihh_pays: 1500\n"
|
|
" reserves:\n"
|
|
" ihh_pays: 1800\n"
|
|
" traitement:\n"
|
|
" ihh_pays: 900\n"
|
|
"```\n"
|
|
"Le minerai est {{ minerai }}."
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert "Le minerai est Lithium." in resultat
|
|
|
|
def test_plusieurs_blocs_yaml(self, mock_pastille):
|
|
"""Test avec plusieurs blocs YAML operations."""
|
|
md = (
|
|
"Introduction generale\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" minerai: Lithium\n"
|
|
" extraction:\n"
|
|
" ihh_pays: 1500\n"
|
|
" reserves:\n"
|
|
" ihh_pays: 1800\n"
|
|
" traitement:\n"
|
|
" ihh_pays: 900\n"
|
|
"```\n"
|
|
"Section Lithium : {{ minerai }}\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" produit: Batterie\n"
|
|
" assemblage:\n"
|
|
" ihh_pays: 3000\n"
|
|
"```\n"
|
|
"Section Batterie : {{ produit }}"
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert "Introduction generale" in resultat
|
|
assert "Section Lithium : Lithium" in resultat
|
|
assert "Section Batterie : Batterie" in resultat
|
|
|
|
def test_avec_tableau_synthese(self, mock_pastille):
|
|
"""Test la generation du tableau de synthese quand le marqueur est present."""
|
|
md = (
|
|
"Introduction\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" minerai: Lithium\n"
|
|
" extraction:\n"
|
|
" ihh_pays: 1500\n"
|
|
" reserves:\n"
|
|
" ihh_pays: 1800\n"
|
|
" traitement:\n"
|
|
" ihh_pays: 900\n"
|
|
"```\n"
|
|
"Texte apres\n\n"
|
|
"# Tableaux de synth\u00e8se\n"
|
|
"<!---- AUTO-BEGIN:TABLEAU-FINAL -->\n"
|
|
"ancien contenu\n"
|
|
"<!---- AUTO-END:TABLEAU-FINAL -->"
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert "# Tableaux de synth\u00e8se" in resultat
|
|
assert "<!---- AUTO-BEGIN:TABLEAU-FINAL -->" in resultat
|
|
assert "<!---- AUTO-END:TABLEAU-FINAL -->" in resultat
|
|
# L'ancien contenu doit etre remplace
|
|
assert "ancien contenu" not in resultat
|
|
# Le tableau minerais doit etre genere
|
|
assert "Lithium" in resultat
|
|
|
|
def test_sans_tableau_synthese(self, mock_pastille):
|
|
"""Test sans marqueur de tableau de synthese."""
|
|
md = (
|
|
"Introduction\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" produit: Batterie\n"
|
|
" assemblage:\n"
|
|
" ihh_pays: 3000\n"
|
|
"```\n"
|
|
"Fin du document."
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert "# Tableaux de synth\u00e8se" not in resultat
|
|
assert "Introduction" in resultat
|
|
assert "Fin du document." in resultat
|
|
|
|
def test_intro_vide_avant_bloc(self, mock_pastille):
|
|
"""Test quand le bloc YAML est au tout debut du markdown."""
|
|
md = (
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" produit: Batterie\n"
|
|
" assemblage:\n"
|
|
" ihh_pays: 3000\n"
|
|
"```\n"
|
|
"Section apres."
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
assert "Section apres." in resultat
|
|
|
|
def test_synthese_remplace_marqueurs_differents_niveaux_titre(self, mock_pastille):
|
|
"""Test que la regex de remplacement gere differents niveaux de titre (#, ##, ###)."""
|
|
md = (
|
|
"Introduction\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" minerai: Cobalt\n"
|
|
" extraction:\n"
|
|
" ihh_pays: 800\n"
|
|
" reserves:\n"
|
|
" ihh_pays: 600\n"
|
|
" traitement:\n"
|
|
" ihh_pays: 500\n"
|
|
"```\n"
|
|
"Texte\n\n"
|
|
"## Tableaux de synth\u00e8se\n"
|
|
"<!---- AUTO-BEGIN:TABLEAU-FINAL -->\n"
|
|
"contenu a remplacer\n"
|
|
"<!---- AUTO-END:TABLEAU-FINAL -->"
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
# Le titre doit etre normalise en h1
|
|
assert "# Tableaux de synth\u00e8se" in resultat
|
|
assert "contenu a remplacer" not in resultat
|
|
|
|
def test_retour_type_str(self):
|
|
"""Test que la fonction retourne toujours une chaine."""
|
|
assert isinstance(build_ihh_sections(""), str)
|
|
assert isinstance(build_ihh_sections("Texte simple"), str)
|
|
|
|
def test_integration_complete(self, mock_pastille):
|
|
"""Test d'integration avec minerai, produit, composant et synthese."""
|
|
md = (
|
|
"# Analyse IHH\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" minerai: Lithium\n"
|
|
" extraction:\n"
|
|
" ihh_pays: 1500\n"
|
|
" ihh_acteurs: 2000\n"
|
|
" reserves:\n"
|
|
" ihh_pays: 1800\n"
|
|
" traitement:\n"
|
|
" ihh_pays: 900\n"
|
|
" ihh_acteurs: 1100\n"
|
|
"```\n"
|
|
"Extraction de {{ minerai }}\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" produit: Batterie\n"
|
|
" assemblage:\n"
|
|
" ihh_pays: 3000\n"
|
|
" ihh_acteurs: 2500\n"
|
|
"```\n"
|
|
"Assemblage de {{ produit }}\n\n"
|
|
"```yaml\n"
|
|
"op\u00e9ration:\n"
|
|
" composant: Cathode\n"
|
|
" fabrication:\n"
|
|
" ihh_pays: 1200\n"
|
|
" ihh_acteurs: 800\n"
|
|
"```\n"
|
|
"Fabrication de {{ composant }}\n\n"
|
|
"# Tableaux de synth\u00e8se\n"
|
|
"<!---- AUTO-BEGIN:TABLEAU-FINAL -->\n"
|
|
"placeholder\n"
|
|
"<!---- AUTO-END:TABLEAU-FINAL -->"
|
|
)
|
|
|
|
resultat = build_ihh_sections(md)
|
|
|
|
# Introduction preservee
|
|
assert "# Analyse IHH" in resultat
|
|
# Templates Jinja rendus
|
|
assert "Extraction de Lithium" in resultat
|
|
assert "Assemblage de Batterie" in resultat
|
|
assert "Fabrication de Cathode" in resultat
|
|
# Tableau de synthese genere
|
|
assert "## Assemblage des produits" in resultat
|
|
assert "## Fabrication des composants" in resultat
|
|
assert "## Op\u00e9rations sur les minerais" in resultat
|
|
# Placeholder remplace
|
|
assert "placeholder" not in resultat
|