import 'dart:typed_data'; import 'package:cookit/src/database/database.dart'; import 'package:cookit/src/recipes/course_repository.dart'; import 'package:cookit/src/recipes/models/course.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 RecipeRepository recipes; late CourseRepository courses; setUp(() async { db = testDatabase(); photos = await tempPhotoStore(); recipes = RecipeRepository(db, photos); courses = CourseRepository(db); }); tearDown(() async { await db.close(); await photos.directory.delete(recursive: true); }); test('a fresh database starts with the default Courses in order', () async { final all = await courses.allCourses(); expect(all.map((c) => c.name), defaultCourses.map((c) => c.$1)); expect(all.first.label, '🍝 Hauptgericht'); }); test('saves and reads back a whole Recipe', () async { final course = (await courses.allCourses()).first; final original = recipe(courseId: course.id, tags: ['Brot'], reviewReasons: ['Portionen fehlen.']); await recipes.saveRecipe(original); final read = (await recipes.watchRecipe('r1').first)!; expect(read.name, 'Focaccia'); expect(read.courseId, course.id); expect(read.tags, ['Brot']); expect(read.calories!.kcal, 775); expect( [for (final g in read.ingredientGroups) g.toJson()], [for (final g in original.ingredientGroups) g.toJson()], ); expect(read.stepSections.single.title, 'Teig'); expect(read.sources, ['https://example.org/focaccia']); expect(read.needsReview, isTrue); }); test('watchRecipes is sorted by name ignoring case', () async { await recipes.saveRecipe(recipe(id: 'b', name: 'zwiebelkuchen')); await recipes.saveRecipe(recipe(id: 'a', name: 'Apfelstrudel')); await recipes.saveRecipe(recipe(id: 'c', name: 'Brot')); final names = (await recipes.watchRecipes().first).map((r) => r.name); expect(names, ['Apfelstrudel', 'Brot', 'zwiebelkuchen']); }); test('favourite and clearing the Review Flag', () async { await recipes.saveRecipe(recipe(reviewReasons: ['x'])); await recipes.setFavourite('r1', true); await recipes.clearReview('r1'); final read = (await recipes.watchRecipe('r1').first)!; expect(read.favourite, isTrue); expect(read.needsReview, isFalse); }); test('deleting a Recipe removes its Photo files', () async { final photo = await photos.saveBytes(Uint8List.fromList([1, 2, 3])); await recipes.saveRecipe(recipe(photos: [photo])); await recipes.deleteRecipe((await recipes.watchRecipe('r1').first)!); expect(await recipes.watchRecipe('r1').first, isNull); expect(photos.file(photo).existsSync(), isFalse); }); test('deleting a Course keeps its Recipes without one', () async { final course = await courses.addCourse('Suppe', emoji: '🍲'); await recipes.saveRecipe(recipe(courseId: course.id)); expect(await courses.recipeCount(course.id), 1); await courses.deleteCourse(course.id); expect((await recipes.watchRecipe('r1').first)!.courseId, isNull); }); test('findOrCreate matches names ignoring case', () async { final existing = await courses.findOrCreate('dessert'); expect(existing.name, 'Dessert'); final created = await courses.findOrCreate('Suppe'); expect(created.position, defaultCourses.length); }); test('reorder and update Courses', () async { final all = await courses.allCourses(); await courses.reorder(all.reversed.toList()); await courses.updateCourse(all.first.id, name: 'Hauptspeise', emoji: null); final reordered = await courses.allCourses(); expect(reordered.last.name, 'Hauptspeise'); expect(reordered.last.emoji, isNull); }); }