import 'dart:math'; import 'package:cookit/src/database/database.dart'; import 'package:cookit/src/localization/app_localizations_de.dart'; import 'package:cookit/src/recipes/course_repository.dart'; import 'package:cookit/src/recipes/photo_store.dart'; import 'package:cookit/src/recipes/recipe_list_provider.dart'; import 'package:cookit/src/recipes/recipe_repository.dart'; import 'package:cookit/src/recipes/time_format.dart'; import 'package:flutter_test/flutter_test.dart'; import '../support/fixtures.dart'; import '../support/test_database.dart'; void main() { group('Idee für heute', () { late AppDatabase db; late PhotoStore photos; late RecipeRepository recipes; var now = DateTime(2026, 10, 20, 18); setUp(() async { db = testDatabase(); photos = await tempPhotoStore(); recipes = RecipeRepository(db, photos); for (final (i, name) in ['Avocado Pasta', 'Brot', 'Curry', 'Dürüm'].indexed) { await recipes.saveRecipe(recipe(id: 'r$i', name: name)); } }); tearDown(() async { await db.close(); await photos.directory.delete(recursive: true); }); Future provider() async { final p = RecipeListProvider(recipes, CourseRepository(db), clock: () => now, random: Random(1)); await Future.delayed(const Duration(milliseconds: 20)); return p; } test('is stable within a day and drawn at random from day to day', () async { final p = await provider(); final today = p.suggestion; now = DateTime(2026, 10, 20, 23, 59); expect(p.suggestion!.id, today!.id); // Not the alphabetical walk it used to be: over two weeks the picks jump around. final picks = []; for (var d = 0; d < 14; d++) { now = DateTime(2026, 11, 1 + d, 12); picks.add(p.suggestion!.id); } expect(picks.toSet().length, greaterThan(2)); final steps = [ for (var i = 1; i < picks.length; i++) (int.parse(picks[i].substring(1)) - int.parse(picks[i - 1].substring(1))) % 4, ]; expect(steps.every((s) => s == 1), isFalse); p.dispose(); }); test('"Andere Idee" holds until midnight only', () async { now = DateTime(2026, 10, 20, 18); final p = await provider(); p.shuffleSuggestion(); final shuffled = p.suggestion!.id; now = DateTime(2026, 10, 20, 23, 0); expect(p.suggestion!.id, shuffled); now = DateTime(2026, 10, 21, 8); final p2 = await provider(); expect(p.suggestion!.id, p2.suggestion!.id); p.dispose(); p2.dispose(); }); test('"Andere Idee" always picks a different Recipe', () async { final p = await provider(); for (var i = 0; i < 10; i++) { final before = p.suggestion!.id; p.shuffleSuggestion(); expect(p.suggestion!.id, isNot(before)); } p.dispose(); }); }); group('time format', () { final l10n = AppLocalizationsDe(); test('formatMinutes', () { expect(formatMinutes(l10n, 45), '45 Min.'); expect(formatMinutes(l10n, 60), '1 Std.'); expect(formatMinutes(l10n, 70), '1 Std. 10 Min.'); }); test('greeting follows the time of day', () { final cases = { (2, 0): 'Schönen Abend', (5, 0): 'Guten Morgen', (11, 29): 'Guten Morgen', (11, 30): 'Mahlzeit!', (13, 59): 'Mahlzeit!', (14, 0): 'Guten Tag', (17, 0): 'Guten Abend', (21, 59): 'Guten Abend', (22, 0): 'Schönen Abend', }; cases.forEach((time, expected) { final (hour, minute) = time; expect(greeting(l10n, DateTime(2026, 1, 1, hour, minute)), expected, reason: '$hour:$minute'); }); }); }); }