diff --git a/stronglift_replacement/workout_app/lib/screens/history_screen.dart b/stronglift_replacement/workout_app/lib/screens/history_screen.dart index d1f15ef..2e82e39 100644 --- a/stronglift_replacement/workout_app/lib/screens/history_screen.dart +++ b/stronglift_replacement/workout_app/lib/screens/history_screen.dart @@ -8,6 +8,7 @@ library; import 'dart:async'; import 'dart:convert'; import 'dart:math'; +import 'package:crdt_sync/crdt_sync.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:workout_app/models/exercise.dart'; @@ -29,11 +30,20 @@ class HistoryScreen extends StatefulWidget { /// /// [httpClient] is injected only by tests, so the synced-workout fetch can /// be driven without real network — same pattern as `SettingsScreen`. - const HistoryScreen({super.key, this.httpClient}); + /// + /// [firebaseFactory] is likewise tests-only, and is NOT redundant with + /// [httpClient]: the sync guard short-circuits on "no backend configured", + /// and it asks Firebase that question directly. On a desktop that has a + /// cached refresh token the real factory answers yes, so the guard opens and + /// the fetch goes to the network even with the sync token faked away. + const HistoryScreen({super.key, this.httpClient, this.firebaseFactory}); /// Overrides the HTTP client used to read synced workouts (tests only). final http.Client? httpClient; + /// Overrides how a Firebase account is discovered (tests only). + final Future Function()? firebaseFactory; + @override State createState() => _HistoryScreenState(); } @@ -106,6 +116,7 @@ class _HistoryScreenState extends State { Future>> _readSyncedPayloads() => WorkoutSyncService( httpClient: widget.httpClient, + firebaseFactory: widget.firebaseFactory, ).readMergedWorkoutPayloads(); Future _pickExercise(String name) async { diff --git a/stronglift_replacement/workout_app/test/screens/_history_test_fixtures.dart b/stronglift_replacement/workout_app/test/screens/_history_test_fixtures.dart index 5478934..809ecce 100644 --- a/stronglift_replacement/workout_app/test/screens/_history_test_fixtures.dart +++ b/stronglift_replacement/workout_app/test/screens/_history_test_fixtures.dart @@ -23,9 +23,23 @@ Future pumpHistory(WidgetTester tester, Widget w) async { await tester.pump(); } -Widget wrapHistory({http.Client? httpClient}) => MaterialApp( +/// Wraps the history screen with sync pinned to a known state. +/// +/// [firebaseFactory] defaults to "no account", which is what makes these +/// tests independent of the machine they run on. Faking the sync token is not +/// enough on its own: the guard also asks Firebase whether an account exists, +/// and on a desktop holding a cached refresh token the real factory says yes, +/// so the fetch escapes to the network and the test fails with a +/// RemoteSyncError that has nothing to do with the screen. +Widget wrapHistory({ + http.Client? httpClient, + Future Function()? firebaseFactory, +}) => MaterialApp( theme: buildAppTheme(), - home: HistoryScreen(httpClient: httpClient), + home: HistoryScreen( + httpClient: httpClient, + firebaseFactory: firebaseFactory ?? () async => null, + ), ); /// A GitHub mock serving one PC device log holding a run and a manual. diff --git a/stronglift_replacement/workout_app/test/services/workout_sync_read_test.dart b/stronglift_replacement/workout_app/test/services/workout_sync_read_test.dart index b450685..694a707 100644 --- a/stronglift_replacement/workout_app/test/services/workout_sync_read_test.dart +++ b/stronglift_replacement/workout_app/test/services/workout_sync_read_test.dart @@ -75,6 +75,7 @@ void main() { ); final payloads = await WorkoutSyncService( httpClient: httpClient, + firebaseFactory: () async => null, ).readMergedManualPayloads(); expect(payloads, hasLength(1)); expect(payloads.single['cost'], 'NEW'); @@ -148,6 +149,7 @@ void main() { ); final manuals = await WorkoutSyncService( httpClient: httpClient, + firebaseFactory: () async => null, ).readMergedManualPayloads(); expect(manuals, hasLength(1)); expect(manuals.single['kind'], 'manual_workout'); @@ -207,6 +209,7 @@ void main() { final payloads = await WorkoutSyncService( httpClient: httpClient, + firebaseFactory: () async => null, ).readMergedManualPayloads(); expect(payloads, hasLength(1));