fix(dashboard): DETTE-024 — download fleet, fallback legacy rendu visible
_resolve_lea_zip_template() reste résolu à la volée (full buildé après démarrage OK) ; ajout d'un WARNING explicite quand le full est absent et qu'on retombe sur le ZIP léger non autoportant (plus de fallback silencieux). Fonction injectable pour tests. 4 tests + 32 non-régression verts. refs DETTE-024 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
75
tests/unit/test_resolve_lea_zip_template.py
Normal file
75
tests/unit/test_resolve_lea_zip_template.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Tests unitaires pour _resolve_lea_zip_template (DETTE-024).
|
||||
|
||||
La fonction est injectable (full_path, legacy_path en paramètres)
|
||||
→ testable sans instancier Flask ni lire le vrai deploy/.
|
||||
|
||||
Pattern anti-DETTE-013 : os.environ.setdefault avant l'import du module.
|
||||
"""
|
||||
import os
|
||||
|
||||
os.environ.setdefault("DASHBOARD_AUTH_DISABLED", "true")
|
||||
|
||||
import pytest # noqa: E402
|
||||
from web_dashboard.app import _resolve_lea_zip_template # noqa: E402
|
||||
|
||||
|
||||
class TestResolveLéaZipTemplate:
|
||||
"""DETTE-024 — sélection du ZIP template pour le download fleet."""
|
||||
|
||||
def test_full_present_retourne_full(self, tmp_path):
|
||||
"""Si le ZIP complet autoportant est présent, il est retourné."""
|
||||
full = tmp_path / "Lea_full_v1.0.1.zip"
|
||||
legacy = tmp_path / "Lea_v1.0.0.zip"
|
||||
full.write_bytes(b"full-stub")
|
||||
legacy.write_bytes(b"legacy-stub")
|
||||
|
||||
result = _resolve_lea_zip_template(full_path=full, legacy_path=legacy)
|
||||
|
||||
assert result == full, f"Attendu full ({full}), obtenu {result}"
|
||||
|
||||
def test_full_absent_retourne_legacy_avec_warning(self, tmp_path, caplog):
|
||||
"""Si le ZIP complet est absent, le legacy est retourné + WARNING loggué.
|
||||
|
||||
Le WARNING est le signal observable en production (DETTE-024) :
|
||||
sans lui, le fallback silencieux rendait le problème invisible.
|
||||
"""
|
||||
import logging
|
||||
|
||||
full = tmp_path / "Lea_full_v1.0.1.zip"
|
||||
legacy = tmp_path / "Lea_v1.0.0.zip"
|
||||
# full intentionnellement absent
|
||||
legacy.write_bytes(b"legacy-stub")
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
result = _resolve_lea_zip_template(full_path=full, legacy_path=legacy)
|
||||
|
||||
assert result == legacy, f"Attendu legacy ({legacy}), obtenu {result}"
|
||||
# Le WARNING DETTE-024 doit apparaître dans les logs
|
||||
assert any(
|
||||
"DETTE-024" in record.message for record in caplog.records
|
||||
), (
|
||||
"Un WARNING DETTE-024 doit être émis quand le ZIP complet est absent "
|
||||
f"(logs: {[r.message for r in caplog.records]})"
|
||||
)
|
||||
|
||||
def test_full_et_legacy_absents_retourne_none(self, tmp_path):
|
||||
"""Si aucun ZIP n'existe, retourne None (la route renvoie 500)."""
|
||||
full = tmp_path / "Lea_full_v1.0.1.zip"
|
||||
legacy = tmp_path / "Lea_v1.0.0.zip"
|
||||
# aucun des deux créés
|
||||
|
||||
result = _resolve_lea_zip_template(full_path=full, legacy_path=legacy)
|
||||
|
||||
assert result is None, f"Attendu None, obtenu {result}"
|
||||
|
||||
def test_full_prime_sur_legacy(self, tmp_path):
|
||||
"""Le full est retourné même si le legacy existe aussi (priorité correcte)."""
|
||||
full = tmp_path / "Lea_full_v1.0.1.zip"
|
||||
legacy = tmp_path / "Lea_v1.0.0.zip"
|
||||
full.write_bytes(b"full-stub")
|
||||
legacy.write_bytes(b"legacy-stub")
|
||||
|
||||
result = _resolve_lea_zip_template(full_path=full, legacy_path=legacy)
|
||||
|
||||
assert result == full
|
||||
assert result != legacy
|
||||
Reference in New Issue
Block a user