/// 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}) => 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, ), ), ), ), ), ); /// `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('la vue consommation ANNONCE que trois branches sont estimées', (tester) async { await tester.pumpWidget(_harness(evChargerPowerW: 0)); await _ouvrirConso(tester); final note = find.textContaining('Répartition estimée'); expect(note, findsOneWidget); final texte = tester.widget(note).data!; // Les trois branches sont NOMMÉES : « certaines valeurs sont estimées » laisserait // chercher lesquelles, et quatre chiffres en kW se ressemblent tous. expect(texte, contains('PAC')); expect(texte, contains('eau chaude')); expect(texte, contains('autres usages')); expect(texte, contains('Seule la voiture est mesurée')); }); 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); }); }