/// Le sélecteur de compteur était **plus restrictif que la box**. /// /// Il filtrait sur l'interface `smartmeter`. Le moteur, lui, n'en regarde aucune : il fait /// `findConfiguredThing(meterThingId)` puis `hasState("currentPower")` /// (`attachMeasurements`, LM-1101). /// /// Constaté sur `.75` le 2026-08-28 : la classe `wallbox` (borne simulée) déclare /// `smartmeter`, la classe `trydan` (V2C) non — `connectable, evcharger, power` seulement. /// La V2C était donc impossible à désigner comme son propre compteur, alors que c'est le /// seul moyen de faire apparaître « mesuré » à côté de « alloué » sur sa carte, et que la /// box l'aurait accepté. library; import 'package:etm_powersync_app/models/nymea_models.dart'; import 'package:etm_powersync_app/services/nymea_service.dart'; import 'package:etm_powersync_app/widgets/thing_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; NymeaStateType _st(String id, String nom, {String type = 'Double'}) => NymeaStateType(id: id, name: nom, displayName: nom, type: type, unit: ''); /// Le parc de `.75`, réduit aux trois cas qui comptent. NymeaService _service() => NymeaService() ..adoptThingsForTest( [ const NymeaThing( id: 'v2c', name: 'V2C Trydan', thingClassId: 'cls-trydan', setupStatus: 'ok', paramValues: []), const NymeaThing( id: 'sim', name: 'Simulated wallbox', thingClassId: 'cls-wallbox', setupStatus: 'ok', paramValues: []), const NymeaThing( id: 'ecs', name: 'ECS-Meter', thingClassId: 'cls-meter', setupStatus: 'ok', paramValues: []), // Une borne SANS puissance publiée : élargir le filtre ne doit pas la faire entrer. const NymeaThing( id: 'muette', name: 'Borne muette', thingClassId: 'cls-borne-muette', setupStatus: 'ok', paramValues: []), ], [ NymeaThingClass( id: 'cls-trydan', name: 'trydan', displayName: 'Trydan', interfaces: const ['connectable', 'evcharger', 'power'], stateTypes: [_st('p', 'currentPower')], ), NymeaThingClass( id: 'cls-wallbox', name: 'wallbox', displayName: 'Simulated wallbox', interfaces: const ['evcharger', 'power', 'smartmeter', 'smartmeterconsumer'], stateTypes: [_st('p', 'currentPower')], ), NymeaThingClass( id: 'cls-meter', name: 'smartMeterConsumer', displayName: 'Compteur', interfaces: const ['smartmeter', 'smartmeterconsumer'], stateTypes: [_st('p', 'currentPower')], ), NymeaThingClass( id: 'cls-borne-muette', name: 'borneMuette', displayName: 'Borne muette', interfaces: const ['evcharger'], stateTypes: [_st('c', 'charging', type: 'Bool')], ), ], ); Widget _harness({ List aussi = const [], String? etatRequis, }) => MaterialApp( home: Scaffold( body: ThingPicker( service: _service(), interfaceRequise: 'smartmeter', interfacesAussi: aussi, etatRequis: etatRequis, valeur: null, onChoisi: (_) {}, placeholder: 'Choisir un appareil de mesure…', ), ), ); Future> _liste(WidgetTester tester) async { await tester.tap(find.text('Choisir un appareil de mesure…')); await tester.pumpAndSettle(); return tester .widgetList(find.byType(Text)) .map((t) => t.data ?? '') .toList(); } void main() { testWidgets('sans élargissement, la V2C n\'est PAS proposée', (tester) async { // L'état d'avant : le comportement qu'on corrige, figé pour qu'on sache ce qu'il était. await tester.pumpWidget(_harness()); final noms = await _liste(tester); expect(noms, contains('ECS-Meter')); expect(noms, contains('Simulated wallbox')); expect(noms.contains('V2C Trydan'), isFalse); }); testWidgets('élargi aux bornes qui publient currentPower, elle l\'est', (tester) async { await tester.pumpWidget( _harness(aussi: const ['evcharger'], etatRequis: 'currentPower')); final noms = await _liste(tester); expect(noms, contains('V2C Trydan')); // Les compteurs restent : le filtre s'élargit, il ne se remplace pas. expect(noms, contains('ECS-Meter')); expect(noms, contains('Simulated wallbox')); }); testWidgets('une borne qui ne publie AUCUNE puissance reste dehors', (tester) async { // L'élargissement suit la règle du moteur — `hasState("currentPower")` — et pas // « toute borne fera l'affaire ». Proposer un appareil qui ne mesure rien ferait // écrire une configuration muette, sans erreur. await tester.pumpWidget( _harness(aussi: const ['evcharger'], etatRequis: 'currentPower')); final noms = await _liste(tester); expect(noms.contains('Borne muette'), isFalse); }); }