From 5472b195045fb28ff3af4d032dab7470353a369b Mon Sep 17 00:00:00 2001 From: Johan LEROY Date: Tue, 22 Sep 2026 15:08:40 +0200 Subject: [PATCH] fix(backend): repare ce que la CI a trouve sur les tests de derive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deux causes distinctes, toutes deux invisibles sans base. `creer_lecture` ne posait pas `consumption_kwh` : l'override etait ignore en silence, la colonne restait nulle, et la jointure de derive, qui ecarte les lectures sans mesure, ne trouvait donc aucune paire. Le helper accepte desormais ce champ, nul par defaut, ce qui ne change rien pour les dix fichiers qui l'utilisent deja. `test_the_operator_rank_opens_nothing_more_than_the_reader_rank` figeait l'egalite des deux rangs en annoncant, dans son propre commentaire, qu'il devait sonner « le jour ou une route d'operateur arrive ». Ce jour est arrive avec `GET /monitoring/drift`. Le test compare maintenant chaque route a ce que `ROLE_MINIMUM` lui reserve : il continue d'attraper une route d'operateur ajoutee sans etre classee, et attrape en plus une garde d'operateur posee par erreur sur une route de lecture. --- apps/backend/tests/api/test_matrice_acces.py | 20 ++++++++++--------- .../tests/repositories/test_reading.py | 3 +++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/backend/tests/api/test_matrice_acces.py b/apps/backend/tests/api/test_matrice_acces.py index 5def3a7..8833596 100644 --- a/apps/backend/tests/api/test_matrice_acces.py +++ b/apps/backend/tests/api/test_matrice_acces.py @@ -227,24 +227,26 @@ async def test_a_real_token_reaches_exactly_the_routes_of_its_rank( assert ecarts == [] -# Contrainte : `operateur` n'ouvre aujourd'hui aucune route de plus que `lecteur`, faute d'écriture -# métier dans l'API. Figer l'égalité rend la régression visible le jour où une route d'opérateur -# arrive sans que `ROLE_MINIMUM` soit mis à jour. +# Contrainte : les deux rangs ne se séparent que sur les routes que `ROLE_MINIMUM` réserve à +# `operateur`. Une route d'opérateur ajoutée sans être classée fait diverger les statuts sans +# qu'aucune entrée ne l'annonce, et une garde d'opérateur posée par erreur sur une route de +# lecture fait diverger ce qui devait rester identique. @pytest.mark.integration -async def test_the_operator_rank_opens_nothing_more_than_the_reader_rank( +async def test_the_operator_rank_diverges_from_the_reader_rank_only_where_declared( comptes_par_role: dict[Role, str], client: AsyncClient ) -> None: lecteur = await authentifie(client, comptes_par_role[Role.LECTEUR]) operateur = await authentifie(client, comptes_par_role[Role.OPERATEUR]) - divergences: list[tuple[str, str]] = [] + ecarts: list[tuple[str, str]] = [] - for methode, chemin in ROLE_MINIMUM: + for (methode, chemin), minimum in ROLE_MINIMUM.items(): cote_lecteur = await appelle(client, methode, chemin, headers=lecteur) cote_operateur = await appelle(client, methode, chemin, headers=operateur) - if cote_lecteur.status_code != cote_operateur.status_code: - divergences.append((methode, chemin)) + diverge = cote_lecteur.status_code != cote_operateur.status_code + if diverge is not (minimum is Role.OPERATEUR): + ecarts.append((methode, chemin)) - assert divergences == [] + assert ecarts == [] # Piège : `/auth/logout-all` prend un `CurrentPrincipalDep` nu, donc elle échappe au gate diff --git a/apps/backend/tests/repositories/test_reading.py b/apps/backend/tests/repositories/test_reading.py index ac3f854..c62a3d2 100644 --- a/apps/backend/tests/repositories/test_reading.py +++ b/apps/backend/tests/repositories/test_reading.py @@ -33,6 +33,9 @@ async def creer_lecture(session: AsyncSession, *, site_id: str, **overrides: obj timestamp=overrides.get("timestamp", datetime(2026, 9, 16, tzinfo=UTC)), source=overrides.get("source", "api_current"), consumption_kw=overrides.get("consumption_kw", 10.0), + # Nul par defaut : seules les mesures en kWh alimentent la comparaison prevu/realise, et + # un override silencieusement ignore laissait la colonne vide sans que rien ne le dise. + consumption_kwh=overrides.get("consumption_kwh"), data_quality=overrides.get("data_quality", "good"), raw_data=overrides.get("raw_data", {}), )