From a9aa379a13a08bf4cec8bcee89d6cfa3478c712a Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sat, 10 Oct 2026 20:00:45 +0200 Subject: [PATCH] app tests: off-hour schedule round trips + real settings wiring Pins that fm/lm survive both the sync wire and a disk reload, and that a quarter-hour pick in SettingsScreen goes through the real _applySchedule. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_015npsYVB2PdtWkG7MPAi4tn --- app/pubspec.yaml | 2 +- app/test/screens/settings_screen_test.dart | 17 +++++++++++++++++ .../services/meal_schedule_service_test.dart | 17 +++++++++++++++++ app/test/services/sync_merge_schedule_test.dart | 14 ++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 463443c..8684a1d 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -2,7 +2,7 @@ name: diet_guard_app description: "Companion phone app for diet_guard: log meals on the go." publish_to: 'none' -version: 1.0.107+1 +version: 1.0.108+1 environment: sdk: ^3.12.2 diff --git a/app/test/screens/settings_screen_test.dart b/app/test/screens/settings_screen_test.dart index 7ba0c40..515c4b2 100644 --- a/app/test/screens/settings_screen_test.dart +++ b/app/test/screens/settings_screen_test.dart @@ -85,6 +85,23 @@ void main() { expect(find.text('Meals per day'), findsOneWidget); }); }); + testWidgets('picking a quarter-hour first meal saves the schedule', ( + tester, + ) async { + await tester.runAsync(() async { + await tester.pumpWidget(const MaterialApp(home: SettingsScreen())); + await settle(tester); + + await tester.tap(find.widgetWithText(InputDecorator, 'First meal')); + await settle(tester); + await tester.tap(find.text('07:45').last); + await settle(tester); + + // Through the real _applySchedule: normalised, recorded, persisted. + expect(MealScheduleService.current.firstMinute, 465); + expect(find.text('07:45 · 11:45 · 16:00 · 20:00'), findsOneWidget); + }); + }); testWidgets('reflects a five-meal schedule as the user\'s example', ( tester, ) async { diff --git a/app/test/services/meal_schedule_service_test.dart b/app/test/services/meal_schedule_service_test.dart index 29a1f8b..9d11fec 100644 --- a/app/test/services/meal_schedule_service_test.dart +++ b/app/test/services/meal_schedule_service_test.dart @@ -143,5 +143,22 @@ void main() { expect(decoded['v'], 1); expect((decoded['e']! as Map).keys, contains('2026-08-16')); }); + + test('an off-the-hour schedule survives a reload', () async { + const offHour = MealSchedule(firstMinute: 443, lastMinute: 1155, count: 5); + await MealScheduleService.initForTesting(store); + await MealScheduleService.instance.recordChange(offHour); + + MealScheduleService.resetForTesting(); + await MealScheduleService.initForTesting(store); + + expect(MealScheduleService.current, offHour); + final decoded = + jsonDecode(store.documents[MealScheduleService.documentName]!) + as Map; + final today = (decoded['e']! as Map).values.last as Map; + expect(today['fm'], 443); + expect(today['lm'], 1155); + }); }); } diff --git a/app/test/services/sync_merge_schedule_test.dart b/app/test/services/sync_merge_schedule_test.dart index 65f2ad0..b67a6c0 100644 --- a/app/test/services/sync_merge_schedule_test.dart +++ b/app/test/services/sync_merge_schedule_test.dart @@ -93,6 +93,20 @@ void main() { ); }); + test('an off-the-hour schedule round trips through the wire', () { + // Dropping fm/lm on either side would silently snap 07:15 to 07:00. + const offHour = MealSchedule(firstMinute: 435, lastMinute: 1140, count: 5); + final entry = _entry('2026-08-16', offHour, '2026-08-16T10:00:00+02:00'); + expect(scheduleFields([entry]).values.single.$1, { + 'f': 7, + 'l': 19, + 'n': 5, + 'fm': 435, + }); + final back = logToScheduleHistory(budgetToLog(_record, const [], [entry])); + expect(back.single.schedule, offHour); + }); + test("normalizes a peer's out-of-range schedule", () { final log = budgetToLog(_record); final record = log[budgetRecordId]!;