Les tuiles disent la JOURNÉE, par différence de compteurs sur la fenêtre publiée. La nouvelle ligne dit ce que la BOX publie, qui part de la baseline — et elle ne s'affiche QUE lorsque cette origine diffère du début de journée. Le cas est arrivé de lui-même : `nymead` redémarré à 09:23, sonde à 09:26, et la box publiait 100 % d'autoconsommation. Vrai sur trois minutes ; absurde intitulé « aujourd'hui ». La ligne le rend lisible — « Instantané depuis 09:23 » — au lieu de le laisser passer pour la journée. Vérifié avec le MODÈLE de l'app et non à l'œil sur le JSON : `ratios_check.dart` importe `EnergyRatiosSnapshot` (idiome de `measurement_check.dart`) et rend `baselineRepriseEnJournee: true`, ratios couvrant 3 minutes. Le banc est passé en Europe/Paris entre-temps, et `periodStartedAt` suit sans que le code bouge — c'est l'intérêt d'une frontière publiée. Quand les deux coïncident, rien n'est ajouté : une phrase permanente cesse d'être lue, comme un avertissement permanent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
92 lines
3.9 KiB
Dart
92 lines
3.9 KiB
Dart
/// **Deux grandeurs, deux phrases, aucune ne ment.**
|
|
///
|
|
/// Les tuiles disent la JOURNÉE — différence de compteurs sur `periodStartedAt → maintenant`.
|
|
/// La ligne des ratios dit ce que la BOX publie, qui part de la **baseline** et non du début
|
|
/// de journée.
|
|
///
|
|
/// Le cas est arrivé de lui-même le 2026-09-05 : `nymead` redémarré à 09:23, sonde à 09:26,
|
|
/// et la box publiait **100 % d'autoconsommation**. Vrai sur trois minutes ; absurde intitulé
|
|
/// « aujourd'hui ». C'est ce que le drapeau rend lisible — et c'est pour ça que la ligne ne
|
|
/// s'affiche QUE lorsque l'origine diffère : quand les deux coïncident, une phrase de plus
|
|
/// serait du bruit, et un texte permanent cesse d'être lu.
|
|
library;
|
|
|
|
import 'package:etm_powersync_app/features/dashboard/widgets/kpi_row.dart';
|
|
import 'package:etm_powersync_app/models/daily_balance.dart';
|
|
import 'package:etm_powersync_app/models/energy_data.dart';
|
|
import 'package:etm_powersync_app/models/energy_ratios_snapshot.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
/// Relevé `.75` du 2026-09-05 09:26, après le redémarrage de 09:23.
|
|
EnergyRatiosSnapshot _releve({int measuredSince = 1788592995}) =>
|
|
EnergyRatiosSnapshot.fromJson({
|
|
'autonomyRate': 28.570199887530475,
|
|
'selfConsumptionRate': 100,
|
|
'periodStartedAt': 1788559200,
|
|
'measuredSince': measuredSince,
|
|
'timeZone': 'Europe/Paris',
|
|
});
|
|
|
|
DailyBalance _bilan() => DailyBalance(
|
|
from: DateTime(2026, 9, 5, 0, 15),
|
|
to: DateTime(2026, 9, 5, 9, 26),
|
|
periodStart: DateTime(2026, 9, 5),
|
|
sampleCount: 37,
|
|
productionKwh: 8.0,
|
|
consumptionKwh: 12.0,
|
|
importKwh: 5.0,
|
|
exportKwh: 1.0,
|
|
);
|
|
|
|
Widget _harness({EnergyRatiosSnapshot? ratios}) => MaterialApp(
|
|
home: Scaffold(
|
|
body: SingleChildScrollView(
|
|
child: KpiRow(
|
|
data: const EnergyData(), balance: _bilan(), ratios: ratios),
|
|
),
|
|
),
|
|
);
|
|
|
|
void main() {
|
|
testWidgets('baseline reposée en journée : l\'origine est DITE', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(1000, 2000));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
await tester.pumpWidget(_harness(ratios: _releve()));
|
|
|
|
expect(find.textContaining('Instantané depuis 09:23'), findsOneWidget);
|
|
// Le 100 % est affiché — il est vrai — mais jamais sous le mot « aujourd'hui ».
|
|
expect(find.textContaining('autoconsommation 100 %'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('les tuiles restent la JOURNÉE, calculée sur la fenêtre de la box',
|
|
(tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(1000, 2000));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
await tester.pumpWidget(_harness(ratios: _releve()));
|
|
// Les anneaux animent leur valeur : sans laisser l'animation finir, ils affichent 0 —
|
|
// une absence qui se lirait comme un succès si on cherchait justement une absence.
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Aujourd\'hui'), findsOneWidget);
|
|
// 8 kWh produits, 1 exporté -> 87,5 % ; et surtout PAS le 100 % de la box.
|
|
expect(find.textContaining('88'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('origine confondue avec le début de journée : rien de plus',
|
|
(tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(1000, 2000));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
// Le cas normal : la baseline date du début de journée.
|
|
await tester.pumpWidget(_harness(ratios: _releve(measuredSince: 1788559200)));
|
|
expect(find.textContaining('Instantané depuis'), findsNothing);
|
|
});
|
|
|
|
testWidgets('box antérieure : aucune ligne, aucune supposition', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(1000, 2000));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
await tester.pumpWidget(_harness());
|
|
expect(find.textContaining('Instantané'), findsNothing);
|
|
});
|
|
}
|