Initial commit: CookIT recipe collection and week planner
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
7d7a0bc60b
173 files changed
+22803
No files matched your search
@@ -0,0 +1,100 @@
|
||||
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<Phone> 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<String> 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);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user