test(appareil): vérifier le chip de domaine et l'écran de mécanisme depuis le harnais

MIUI refuse l'injection d'événements adb : impossible de faire défiler ou de taper depuis
l'hôte pour contrôler visuellement. Les assertions descendent donc dans integration_test,
qui a la main sur l'IU : le chip porte bien un libellé, le sélecteur de mécanisme propose
les trois valeurs, et les sections exigées par la maquette (Relais commandés,
Temporisations, Compteur dédié, Arbitrage) sont présentes.

Une clé est posée sur le chip pour le viser sans compter des icônes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HajXLUczEyZd22JeewRfff
This commit is contained in:
Patrick Schurig 2026-08-26 08:59:00 +02:00
parent aada8e2ba5
commit 708914861e
2 changed files with 41 additions and 1 deletions

View File

@ -244,6 +244,43 @@ void main() {
debugPrint('[appareil] brouillon abandonné — rien n\'est écrit sur la box');
}
// ── 5-ter. Le chip de domaine PORTE son libellé ─────────────────────────
//
// Il ne rendait qu'une étiquette dessinée : le domaine d'une charge était illisible
// sur sa carte, alors que c'est lui qui décide de son groupe et de son rang.
final chip = find.byKey(const ValueKey('chip-domaine-chauffe-eau'));
await _attendre(tester, () => chip.evaluate().isNotEmpty,
quoi: 'le chip de domaine de chauffe-eau');
final texteChip = find
.descendant(of: chip, matching: find.byType(Text))
.evaluate()
.map((e) => (e.widget as Text).data)
.whereType<String>()
.toList();
debugPrint('[appareil] chip de domaine : $texteChip');
expect(texteChip.any((t) => t.trim().isNotEmpty), isTrue,
reason: 'le chip doit porter un libellé, pas seulement une icône');
// ── 5-quater. L'écran de mécanisme, et son sélecteur ACTIF ──────────────
final boutons = find.text('Configurer');
await tester.tap(boutons.first);
await tester.pump(const Duration(seconds: 2));
for (final m in ['Routeur de relais', 'Modulable', 'SG-Ready']) {
expect(find.text(m), findsWidgets,
reason: 'le sélecteur de mécanisme doit proposer « $m »');
}
// Les sections que la maquette exige et qui manquaient.
for (final titre in ['Relais commandés', 'Temporisations', 'Compteur dédié',
'Arbitrage']) {
expect(find.text(titre), findsWidgets, reason: 'section « $titre » absente');
}
debugPrint('[appareil] écran de mécanisme : sélecteur et sections présents');
// On repart sans rien changer.
Navigator.of(tester.element(find.text('Arbitrage'))).pop();
await tester.pump(const Duration(seconds: 1));
// ── 6. On laisse l'écran affiché ────────────────────────────────────────
//
// `flutter test integration_test` referme l'app dès la dernière assertion. Sans

View File

@ -339,7 +339,10 @@ class LoadConfigCard extends StatelessWidget {
),
const SizedBox(height: 10),
Row(children: [
DomainMenu(entry: entry, provider: provider),
DomainMenu(
key: ValueKey('chip-domaine-${entry.id}'),
entry: entry,
provider: provider),
const Spacer(),
TextButton.icon(
onPressed: () => onConfigure(context, entry),