127 lines
4.7 KiB
Dart
127 lines
4.7 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:cookit/src/database/database.dart';
|
|
import 'package:cookit/src/planning/models/meal.dart';
|
|
import 'package:cookit/src/planning/plan_repository.dart';
|
|
import 'package:cookit/src/recipes/photo_store.dart';
|
|
import 'package:cookit/src/recipes/recipe_repository.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import '../support/fixtures.dart';
|
|
import '../support/test_database.dart';
|
|
|
|
void main() {
|
|
late AppDatabase db;
|
|
late PhotoStore photos;
|
|
late PlanRepository plan;
|
|
late RecipeRepository recipes;
|
|
|
|
final yesterday = DateTime.utc(2026, 10, 22);
|
|
final today = DateTime.utc(2026, 10, 23);
|
|
final tomorrow = DateTime.utc(2026, 10, 24);
|
|
|
|
setUp(() async {
|
|
db = testDatabase();
|
|
photos = await tempPhotoStore();
|
|
plan = PlanRepository(db);
|
|
recipes = RecipeRepository(db, photos);
|
|
});
|
|
|
|
tearDown(() async {
|
|
await db.close();
|
|
await photos.directory.delete(recursive: true);
|
|
});
|
|
|
|
Future<Meal> meal(String name) async => (await plan.allMeals()).firstWhere((m) => m.name == name);
|
|
|
|
test('a fresh database plans Mittag and Abend', () async {
|
|
expect((await plan.allMeals()).map((m) => m.name), defaultMeals);
|
|
});
|
|
|
|
test('entries are added in order, moved to the end of another Meal and removed', () async {
|
|
await recipes.saveRecipe(recipe());
|
|
final abend = await meal('Abend');
|
|
final mittag = await meal('Mittag');
|
|
await plan.addEntry(today, abend.id, recipeId: 'r1');
|
|
await plan.addEntry(today, abend.id, note: 'Salat');
|
|
await plan.addEntry(tomorrow, mittag.id, note: 'Reste');
|
|
|
|
var entries = await plan.allEntries();
|
|
expect(
|
|
[for (final e in entries) (e.day, e.recipeId ?? e.note, e.position)],
|
|
[(today, 'r1', 0), (today, 'Salat', 1), (tomorrow, 'Reste', 0)],
|
|
);
|
|
|
|
await plan.moveEntry(entries.first.id, tomorrow, mittag.id);
|
|
await plan.removeEntry(entries[1].id);
|
|
entries = await plan.allEntries();
|
|
expect(
|
|
[for (final e in entries) (e.day, e.mealId, e.recipeId ?? e.note, e.position)],
|
|
[(tomorrow, mittag.id, 'Reste', 0), (tomorrow, mittag.id, 'r1', 1)],
|
|
);
|
|
});
|
|
|
|
test('deleting a Meal removes its upcoming entries and keeps it retired for the past', () async {
|
|
final abend = await meal('Abend');
|
|
await plan.addEntry(yesterday, abend.id, note: 'Pizza');
|
|
await plan.addEntry(today, abend.id, note: 'Suppe');
|
|
await plan.addEntry(tomorrow, abend.id, note: 'Curry');
|
|
expect(await plan.upcomingEntryCount(abend.id, today), 2);
|
|
|
|
await plan.deleteMeal(abend.id, today);
|
|
expect((await plan.allEntries()).map((e) => e.note), ['Pizza']);
|
|
expect((await meal('Abend')).retired, isTrue);
|
|
|
|
// Added again under the same name, the old Meal comes back with its history.
|
|
await plan.addMeal('abend');
|
|
final back = await meal('abend');
|
|
expect(back.id, abend.id);
|
|
expect(back.retired, isFalse);
|
|
});
|
|
|
|
test('deleting an unused Meal removes it entirely', () async {
|
|
final mittag = await meal('Mittag');
|
|
await plan.deleteMeal(mittag.id, today);
|
|
expect((await plan.allMeals()).map((m) => m.name), ['Abend']);
|
|
});
|
|
|
|
test('a deleted Recipe stays in the plan as a note with its name', () async {
|
|
await recipes.saveRecipe(recipe());
|
|
final abend = await meal('Abend');
|
|
await plan.addEntry(yesterday, abend.id, recipeId: 'r1');
|
|
await recipes.deleteRecipe(recipe());
|
|
final entry = (await plan.allEntries()).single;
|
|
expect(entry.recipeId, isNull);
|
|
expect(entry.note, 'Focaccia');
|
|
});
|
|
|
|
test('"Tauschen" plans another Recipe in the same entry', () async {
|
|
await recipes.saveRecipe(recipe());
|
|
await recipes.saveRecipe(recipe(id: 'r2', name: 'Pizza'));
|
|
final abend = await meal('Abend');
|
|
await plan.addEntry(today, abend.id, recipeId: 'r1');
|
|
await plan.replaceRecipe((await plan.allEntries()).single.id, 'r2');
|
|
expect((await plan.allEntries()).single.recipeId, 'r2');
|
|
});
|
|
|
|
test('an existing version 2 database gets the Week Plan tables on upgrade', () async {
|
|
await db.close();
|
|
final dir = await Directory.systemTemp.createTemp('cookit_db_');
|
|
final file = File('${dir.path}/cookit.sqlite');
|
|
|
|
var fileDb = testDatabase(file: file);
|
|
await RecipeRepository(fileDb, photos).saveRecipe(recipe());
|
|
await fileDb.customStatement('DROP TABLE plan_entries');
|
|
await fileDb.customStatement('DROP TABLE meals');
|
|
await fileDb.customStatement('PRAGMA user_version = 2');
|
|
await fileDb.close();
|
|
|
|
fileDb = testDatabase(file: file);
|
|
expect((await PlanRepository(fileDb).allMeals()).map((m) => m.name), defaultMeals);
|
|
expect((await RecipeRepository(fileDb, photos).getRecipe('r1'))!.name, 'Focaccia');
|
|
await fileDb.close();
|
|
await dir.delete(recursive: true);
|
|
db = testDatabase(); // for tearDown
|
|
});
|
|
}
|