mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-11-11 12:47:39 +01:00
fix: initialise the catering queue at startup
`KuchniaQueueService` had no `init()` call in `main()`, so on a real device the whole feature would have done nothing: every entry point checks `isInitialized` first and returns quietly, which reads as "no delivery today" rather than as an error. All 694 tests passed throughout, because widget tests initialise the service directly. Caught by grepping main.dart before the phone deploy, not by the suite. So it is now a repo invariant: `repo_invariants_test.dart` asserts main() names both catering `init()` calls, and the assertion was checked against a main.dart with the line deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QQpCiPaSbyRpwsLkH3dgsX
This commit is contained in:
parent
af35eb20c8
commit
8836453f8c
@ -10,6 +10,7 @@ import 'package:diet_guard_app/services/budget_history_service.dart';
|
||||
import 'package:diet_guard_app/services/foodbank_service.dart';
|
||||
import 'package:diet_guard_app/services/frame_stats.dart';
|
||||
import 'package:diet_guard_app/services/kuchnia_credential_service.dart';
|
||||
import 'package:diet_guard_app/services/kuchnia_queue.dart';
|
||||
import 'package:diet_guard_app/services/log_storage_service.dart';
|
||||
import 'package:diet_guard_app/services/meal_schedule_service.dart';
|
||||
import 'package:diet_guard_app/services/notification_service.dart';
|
||||
@ -28,6 +29,7 @@ Future<void> main() async {
|
||||
await MealScheduleService.init();
|
||||
await FoodBankService.init();
|
||||
await KuchniaCredentialService.init();
|
||||
await KuchniaQueueService.init();
|
||||
final notifications = await NotificationService.init();
|
||||
// Deliberately *not* awaited before the first frame: the browser's
|
||||
// `Notification.requestPermission()` does not complete until the user
|
||||
|
||||
@ -23,6 +23,7 @@ library;
|
||||
|
||||
import 'package:diet_guard_app/models/kuchnia_dish.dart';
|
||||
import 'package:diet_guard_app/services/document_store.dart';
|
||||
import 'package:diet_guard_app/services/document_store_factory.dart';
|
||||
import 'package:diet_guard_app/services/kuchnia_import.dart';
|
||||
import 'package:diet_guard_app/services/kuchnia_orders.dart' show isoDay;
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -60,7 +61,24 @@ class KuchniaQueueService {
|
||||
/// How many dishes are still waiting to be logged.
|
||||
static int get remaining => _instance?._pending.length ?? 0;
|
||||
|
||||
/// Initialises from [store], for tests and for [init].
|
||||
/// Initialises the singleton against the platform document store.
|
||||
///
|
||||
/// Without this the queue silently no-ops on a real device: every entry
|
||||
/// point checks [isInitialized] first, so a missing call reads as "no
|
||||
/// delivery" rather than as an error.
|
||||
static Future<KuchniaQueueService> init() async {
|
||||
if (_instance != null) return _instance!;
|
||||
// Resolving the platform store is a plugin call, not reachable from
|
||||
// `flutter test`.
|
||||
// coverage:ignore-start
|
||||
final service = KuchniaQueueService._(await openDocumentStore());
|
||||
// coverage:ignore-end
|
||||
await service._load();
|
||||
_instance = service;
|
||||
return service;
|
||||
}
|
||||
|
||||
/// Initialises from [store], for tests.
|
||||
@visibleForTesting
|
||||
static Future<KuchniaQueueService> initForTesting(DocumentStore store) async {
|
||||
final service = KuchniaQueueService._(store);
|
||||
|
||||
@ -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.64+1
|
||||
version: 1.0.65+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.12.2
|
||||
|
||||
@ -125,6 +125,28 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('singletons that silently no-op are initialised at startup', () {
|
||||
// Every catering entry point checks `isInitialized` first and returns
|
||||
// quietly when it is false, so a missing `init()` does not throw -- it
|
||||
// reads as "no delivery" and "no credential" forever. That is invisible in
|
||||
// widget tests, which initialise these directly, and was caught only by
|
||||
// grepping main.dart before a phone deploy.
|
||||
test('main.dart initialises the catering services', () {
|
||||
final source = File('${_appDir.path}/lib/main.dart').readAsStringSync();
|
||||
for (final call in [
|
||||
'KuchniaCredentialService.init()',
|
||||
'KuchniaQueueService.init()',
|
||||
]) {
|
||||
expect(
|
||||
source.contains(call),
|
||||
isTrue,
|
||||
reason: '$call is missing from main(). The feature will silently do '
|
||||
'nothing on a real device while every test still passes.',
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
group('the desktop wrapper origin is fixed', () {
|
||||
// IndexedDB is keyed by origin and lives in the Chrome profile. Changing
|
||||
// either the port or the --user-data-dir hides the entire local food log
|
||||
|
||||
Loading…
Reference in New Issue
Block a user