/// La vue « consommation » du Sankey — ce qui est mesuré, et ce qui ne l'est pas. /// /// Trois de ses quatre branches sont des **ratios en dur** posés à la maquette : PAC = 38 % /// de la consommation maison, eau chaude = 18 %, autres = 22 %. Un seul nœud (« Autres ») /// portait le cercle pointillé ; les deux autres se lisaient comme des mesures. Et la /// voiture affichait 3,6 kW en permanence, véhicule débranché — la valeur par défaut de /// `EnergyData.chargingPower`, supprimée le 2026-08-28. /// /// Ces tests figent le marquage. Ils ne valident pas les ratios : les remplacer par /// `measuredW` de `GetLoadTelemetry` est un lot à part. library; import 'package:etm_powersync_app/features/dashboard/widgets/energy_flow_card.dart'; import 'package:etm_powersync_app/models/energy_data.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; /// Largeur contrainte : le schéma est un carré, et en pleine largeur de la fenêtre de test /// (800 px) il déborde des 600 px de haut — le nœud « Maison » se retrouve hors écran et /// aucune touche ne l'atteint. Widget _harness({double? evChargerPowerW, Map? mesures}) => MediaQuery( data: const MediaQueryData(disableAnimations: true), child: MaterialApp( home: Scaffold( body: Center( child: SizedBox( width: 340, child: EnergyFlowCard( data: const EnergyData(homePower: 4000, pvPower: 5000), evChargerPowerW: evChargerPowerW, mesuresParDomaine: mesures ?? const {}, ), ), ), ), ), ); /// `pumpAndSettle` est inutilisable ici : les particules du schéma tournent en boucle /// (`repeat()`), et `disableAnimations` ne change que la valeur lue, pas le contrôleur. On /// avance donc d'un nombre fini de trames. Future _poser(WidgetTester tester) async { for (var i = 0; i < 6; i++) { await tester.pump(const Duration(milliseconds: 120)); } } /// Ouvre le détail de consommation — il n'est atteignable qu'en touchant « Maison ». /// /// Le `_poser` AVANT la touche n'est pas décoratif : les nœuds entrent en `ScaleTransition` /// et, sur la première trame, leur échelle vaut zéro — la touche traverse sans rien /// atteindre, silencieusement. Future _ouvrirConso(WidgetTester tester) async { await _poser(tester); await tester.tap(find.text('Maison')); await _poser(tester); } void main() { testWidgets('la vue d\'ensemble ne parle pas d\'estimation — tout y est mesuré', (tester) async { await tester.pumpWidget(_harness()); await _poser(tester); expect(find.textContaining('Répartition estimée'), findsNothing); }); testWidgets('un compteur a 0 W affiche 0 W, pas 18 % de la maison', (tester) async { // Le cas exact du 2026-09-06 : ECS et PAC publiaient {powerW: 0, source: meter} // pendant que l'ecran montrait des parts de la consommation du foyer. await tester.pumpWidget(_harness(mesures: {'ecs': 0.0, 'heating': 0.0})); await _ouvrirConso(tester); expect(find.text('0.0 kW'), findsNWidgets(2)); // 18 % et 38 % de 4 000 W : les deux nombres qui ne doivent plus exister. expect(find.textContaining('0.7'), findsNothing); expect(find.textContaining('1.5'), findsNothing); }); testWidgets('un domaine sans mesure publiee dit non publie', (tester) async { await tester.pumpWidget(_harness(mesures: {'ecs': 1200.0})); await _ouvrirConso(tester); expect(find.text('1.2 kW'), findsOneWidget); expect(find.text('non publié'), findsOneWidget); }); testWidgets('la note ne parle plus d estimation, il n y a plus rien d estime', (tester) async { // La mention « estimé » etait le probleme autant que le remede : sous un nombre // invente, elle le rend acceptable. L'enlever oblige a ne montrer que du vrai. await tester.pumpWidget(_harness(mesures: {'ecs': 1200.0})); await _ouvrirConso(tester); expect(find.textContaining('Répartition estimée'), findsNothing); expect(find.textContaining('parts types'), findsNothing); expect(find.textContaining('non publié'), findsWidgets); }); testWidgets('Autres a disparu : un reste calcule sur des parts inventees', (tester) async { await tester.pumpWidget(_harness(mesures: {'ecs': 1200.0, 'heating': 800.0})); await _ouvrirConso(tester); expect(find.text('Autres'), findsNothing); }); testWidgets('sans borne, la voiture affiche « non lu » — jamais 0,0 kW', (tester) async { // 3,6 kW en dur vivait ici, voiture débranchée, sur le premier écran de l'app. // Le remplacer par un zéro aurait échangé une fiction contre une autre : « rien ne // charge » n'est pas « je ne mesure rien ». await tester.pumpWidget(_harness()); await _ouvrirConso(tester); expect(find.text('non lu'), findsOneWidget); expect(find.textContaining('3.6'), findsNothing); }); testWidgets('avec une borne, elle affiche la puissance mesurée', (tester) async { await tester.pumpWidget(_harness(evChargerPowerW: 3907)); await _ouvrirConso(tester); expect(find.text('3.9 kW'), findsOneWidget); expect(find.text('non lu'), findsNothing); }); }