From 81c5b4e72f4636ffd45758b5bdc62371e4416f77 Mon Sep 17 00:00:00 2001 From: Strycher Date: Mon, 22 Jun 2026 03:10:15 -0400 Subject: [PATCH] test(#74): lock observer provider wiring -- shared connector + gate reactivity (P1) main.dart wiring verified correct (no change): the singleton MeshCoreConnector (main.dart:38 -> field -> provided by value) is the SAME instance passed to ObserverConfigService, so the service watches the live transport. Plain ChangeNotifierProvider (not a proxy) is right -- the connector instance is stable; only its state changes, which the service reads live. Lazy-safe: the constructor has no side effects. This test pins that contract: the service is reachable through Provider and a mutation to the shared connector's caps flips the Observer gate (supported). Co-Authored-By: Claude Opus 4.8 --- test/services/observer_provider_test.dart | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test/services/observer_provider_test.dart diff --git a/test/services/observer_provider_test.dart b/test/services/observer_provider_test.dart new file mode 100644 index 0000000..24cfc81 --- /dev/null +++ b/test/services/observer_provider_test.dart @@ -0,0 +1,60 @@ +// Provider wiring lock for the Observer config feature (#64 P1). +// +// main.dart provides the singleton MeshCoreConnector by value and creates +// ObserverConfigService with THAT SAME connector (main.dart:38 -> field -> the +// two providers). This pins the contract the feature depends on: the service is +// reachable through Provider AND shares the live connector, so the Observer +// settings gate (`supported`) reacts to device-info caps. A fresh-connector +// rewire (create: (_) => ObserverConfigService(MeshCoreConnector())) breaks it. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:provider/provider.dart'; +import 'package:meshcore_open/connector/meshcore_connector.dart'; +import 'package:meshcore_open/connector/observer_config_client.dart'; +import 'package:meshcore_open/services/observer_config_service.dart'; + +class _CapsConnector extends MeshCoreConnector { + int? ver; + int? caps; + @override + int? get firmwareVerCode => ver; + @override + int? get offbandCaps => caps; +} + +void main() { + testWidgets( + 'ObserverConfigService is provided and shares the live connector', + (tester) async { + final connector = _CapsConnector(); + late ObserverConfigService svc; + + await tester.pumpWidget( + MultiProvider( + providers: [ + ChangeNotifierProvider.value(value: connector), + ChangeNotifierProvider( + create: (_) => ObserverConfigService(connector), + ), + ], + child: Builder( + builder: (context) { + svc = context.read(); + return const SizedBox.shrink(); + }, + ), + ), + ); + + // Unsupported until the shared connector reports a v14+ observer build. + expect(svc.supported, isFalse); + + connector.ver = ObserverConfigClient.minVerCode; + connector.caps = ObserverConfigClient.capWifiObserver; + + // The gate flips because the service reads through the SAME connector. + expect(svc.supported, isTrue); + }, + ); +}