Files
tableau-de-bord/tests/test_config_loader.py
Antoine Van Elstraete 85e6e502e5 feat(config): ajouter la configuration Home Assistant (étape 1)
Ajoute la section [home_assistant] au TOML et sa validation au chargement
via get_home_assistant_config(). La section est facultative pour préserver
la compatibilité avec les configurations existantes, mais si elle est
présente elle doit être complète et référencer un type de journée, un
trajet et un véhicule à moteur existants, sous peine de refuser le
démarrage de l'application. La configuration validée est exposée dans
app.config['HOME_ASSISTANT'].

Co-authored-by: OpenAI/GPT-5.6-Luna-Pro <vibecoder@antoineve.me>
2026-08-13 16:13:18 +02:00

168 lines
4.6 KiB
Python

import pytest
from app import create_app
_MINIMAL_CONFIG = """
[vehicles.citadine]
name = "Citadine"
type = "moteur"
[vehicles.velo]
name = "Vélo"
type = "velo"
[journeys.moteur_seul]
name = "Moteur seul"
distances = {{ moteur = 1 }}
[home_assistant]
timezone = "{timezone}"
default_day_type = "{day_type}"
default_journey_profile_id = "{journey_id}"
default_motor_vehicle_id = "{vehicle_id}"
"""
def _create_app_with_home_assistant_config(tmp_path, **values):
config_path = tmp_path / "config.toml"
config_path.write_text(_MINIMAL_CONFIG.format(**values), encoding="utf-8")
return create_app(config_path=str(config_path))
def test_get_vehicles_returns_configured_vehicles(app):
with app.app_context():
from app.config_loader import get_vehicles
vehicles = get_vehicles()
assert "familiale" in vehicles
assert vehicles["familiale"]["co2_per_km"] == 142
def test_get_motor_vehicles_excludes_velo(app):
with app.app_context():
from app.config_loader import get_motor_vehicles
motor = get_motor_vehicles()
assert "familiale" in motor
assert "citadine" in motor
assert "moto" in motor
assert "velo" not in motor
def test_get_journeys_returns_profiles(app):
with app.app_context():
from app.config_loader import get_journeys
journeys = get_journeys()
assert "moteur_seul" in journeys
assert journeys["moteur_seul"]["distances"]["moteur"] == 25
def test_journey_has_motor_true(app):
with app.app_context():
from app.config_loader import journey_has_motor
assert journey_has_motor("moteur_seul") is True
assert journey_has_motor("moteur_velo") is True
def test_journey_has_motor_false(app):
with app.app_context():
from app.config_loader import journey_has_motor
assert journey_has_motor("velo_seul") is False
assert journey_has_motor(None) is False
def test_get_bareme_returns_tranches(app):
with app.app_context():
from app.config_loader import get_bareme
tranches = get_bareme(2025, 5)
assert len(tranches) == 3
assert tranches[0]["taux"] == 0.548
def test_day_types_without_journey(app):
with app.app_context():
from app.config_loader import day_types_without_journey
types = day_types_without_journey()
assert "TT" in types
assert "WORK" not in types
def test_get_home_assistant_config_returns_validated_defaults(app):
with app.app_context():
from app.config_loader import get_home_assistant_config
assert get_home_assistant_config() == {
"timezone": "Europe/Paris",
"default_day_type": "WORK",
"default_journey_profile_id": "moteur_seul",
"default_motor_vehicle_id": "citadine",
}
assert app.config["HOME_ASSISTANT"]["default_motor_vehicle_id"] == "citadine"
def test_home_assistant_section_absent_is_allowed(app):
with app.app_context():
from app.config_loader import get_home_assistant_config
app.config["TOML"].pop("home_assistant")
assert get_home_assistant_config() is None
@pytest.mark.parametrize(
("field", "value", "message"),
[
("timezone", "Mars/NoSuchPlace", "fuseau horaire"),
("day_type", "UNKNOWN", "type de journée"),
("journey_id", "unknown_journey", "trajet inconnu"),
("vehicle_id", "unknown_vehicle", "véhicule inconnu"),
],
)
def test_invalid_home_assistant_config_prevents_startup(tmp_path, field, value, message):
values = {
"timezone": "Europe/Paris",
"day_type": "WORK",
"journey_id": "moteur_seul",
"vehicle_id": "citadine",
}
values[field] = value
with pytest.raises(ValueError, match=message):
_create_app_with_home_assistant_config(tmp_path, **values)
def test_home_assistant_default_vehicle_must_be_motor_vehicle(tmp_path):
values = {
"timezone": "Europe/Paris",
"day_type": "WORK",
"journey_id": "moteur_seul",
"vehicle_id": "velo",
}
with pytest.raises(ValueError, match="véhicule moteur"):
_create_app_with_home_assistant_config(tmp_path, **values)
def test_incomplete_home_assistant_config_prevents_startup(tmp_path):
config_path = tmp_path / "config.toml"
config_path.write_text(
"""
[vehicles.citadine]
type = "moteur"
[journeys.moteur_seul]
distances = { moteur = 1 }
[home_assistant]
timezone = "Europe/Paris"
""",
encoding="utf-8",
)
with pytest.raises(ValueError, match="clé.*manquante"):
create_app(config_path=str(config_path))