import 'package:cookit/src/bundle/bundle_service.dart'; import 'package:cookit/src/database/database.dart'; import 'package:cookit/src/planning/day.dart'; import 'package:cookit/src/planning/plan_repository.dart'; import 'package:cookit/src/planning/plan_share_service.dart'; import 'package:cookit/src/recipes/course_repository.dart'; import 'package:cookit/src/recipes/photo_store.dart'; import 'package:cookit/src/recipes/recipe_repository.dart'; import 'package:cookit/src/recipes/unit_repository.dart'; import 'package:flutter_test/flutter_test.dart'; import '../support/fixtures.dart'; import '../support/test_database.dart'; /// One cook's collection and Week Plan. class Phone { Phone._(this.db, this.photos) : recipes = RecipeRepository(db, photos), courses = CourseRepository(db), units = UnitRepository(db), plan = PlanRepository(db) { bundles = BundleService(recipes, courses, units, photos); shares = PlanShareService(recipes, courses, units, photos, plan, bundles); } static Future create() async { final phone = Phone._(testDatabase(), await tempPhotoStore()); addTearDown(() async { await phone.db.close(); await phone.photos.directory.delete(recursive: true); }); return phone; } final AppDatabase db; final PhotoStore photos; final RecipeRepository recipes; final CourseRepository courses; final UnitRepository units; final PlanRepository plan; late final BundleService bundles; late final PlanShareService shares; Future meal(String name) async => (await plan.allMeals()).firstWhere((m) => m.name == name).id; } void main() { final monday = DateTime.utc(2026, 10, 19); test('a shared week reuses known Recipes, adds new ones and its Meals, and keeps what is planned', () async { final mine = await Phone.create(); final theirs = await Phone.create(); // Mine: three Recipes planned across the week, plus a note and a Meal they don't have. await mine.recipes.saveRecipe(recipe(id: 'shared', name: 'Focaccia')); await mine.recipes.saveRecipe(recipe(id: 'mine-pizza', name: 'Pizza')); await mine.recipes.saveRecipe(recipe(id: 'new', name: 'Gulasch')); await mine.plan.addMeal('Frühstück'); await mine.plan.addEntry(monday, await mine.meal('Abend'), recipeId: 'shared'); await mine.plan.addEntry(addDays(monday, 1), await mine.meal('Abend'), recipeId: 'mine-pizza'); await mine.plan.addEntry(addDays(monday, 2), await mine.meal('Mittag'), recipeId: 'new'); await mine.plan.addEntry(addDays(monday, 3), await mine.meal('Frühstück'), note: 'Bäcker'); await mine.plan.addEntry(addDays(monday, 8), await mine.meal('Abend'), recipeId: 'new'); // next week: not sent // Theirs: the same Focaccia (same id), their own Pizza (same name), and a plan of their own. await theirs.recipes.saveRecipe(recipe(id: 'shared', name: 'Focaccia')); await theirs.recipes.saveRecipe(recipe(id: 'their-pizza', name: 'pizza ')); await theirs.plan.addEntry(monday, await theirs.meal('Mittag'), note: 'Reste'); final week = SharedWeek(await theirs.bundles.read(await mine.shares.weekFile(monday))); final preview = await theirs.shares.preview(week); expect((preview.entries, preview.newRecipes, preview.existingEntries), (4, 1, 1)); await theirs.shares.adopt(week); final recipes = await theirs.recipes.allRecipes(); expect(recipes.map((r) => r.id), unorderedEquals(['shared', 'their-pizza', 'new'])); final meals = {for (final m in await theirs.plan.allMeals()) m.id: m.name}; final entries = await theirs.plan.allEntries(); expect( [for (final e in entries) (e.day, meals[e.mealId], e.recipeId ?? e.note)], unorderedEquals([ (monday, 'Mittag', 'Reste'), (monday, 'Abend', 'shared'), (addDays(monday, 1), 'Abend', 'their-pizza'), (addDays(monday, 2), 'Mittag', 'new'), (addDays(monday, 3), 'Frühstück', 'Bäcker'), ]), ); }); test('only a bundle shared from the Week Plan carries a week', () async { final mine = await Phone.create(); await mine.recipes.saveRecipe(recipe()); final contents = await mine.bundles.read(await mine.bundles.exportBundle()); expect(contents.plan, isNull); final week = await mine.bundles.read(await mine.shares.weekFile(monday)); expect(week.plan, isNotNull); }); }