import 'dart:io'; import 'package:cookit/src/database/database.dart'; import 'package:cookit/src/recipes/models/recipe.dart'; import 'package:cookit/src/recipes/models/unit.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'; void main() { late AppDatabase db; late PhotoStore photos; late UnitRepository units; late RecipeRepository recipes; setUp(() async { db = testDatabase(); photos = await tempPhotoStore(); units = UnitRepository(db); recipes = RecipeRepository(db, photos); }); tearDown(() async { await db.close(); await photos.directory.delete(recursive: true); }); test('a fresh database lists every built-in unit, the common ones offered directly', () async { final all = await units.allUnits(); expect(all.map((u) => u.key), Unit.values.map((u) => u.key)); expect(all.where((u) => u.direct).map((u) => u.key), [ for (final u in Unit.values) if (u.common) u.key, ]); expect(all.every((u) => u.builtIn), isTrue); }); test('own units can be added, renamed, offered directly or not, and sorted', () async { final cube = await units.addOwn('Würfel'); expect(cube.key, startsWith('own-')); await units.rename(cube.key, 'Brühwürfel'); await units.setDirect(cube.key, false); await units.setDirect('gram', false); final all = await units.allUnits(); final reordered = [all.last, ...all.take(all.length - 1)]; await units.reorder(reordered); final after = await units.allUnits(); expect(after.first.key, cube.key); expect((after.first.label, after.first.direct, after.first.builtIn), ('Brühwürfel', false, false)); expect(after.firstWhere((u) => u.key == 'gram').direct, isFalse); }); test('built-in units keep their name', () async { await units.rename('gram', 'Gramm!'); expect((await units.allUnits()).firstWhere((u) => u.key == 'gram').label, isNull); }); test('deleting an own unit moves its name into the Ingredient Lines that used it', () async { final cube = await units.addOwn('Würfel'); await recipes.saveRecipe( recipe( ingredientGroups: [ IngredientGroup( lines: [ IngredientLine(amount: 2, unitKey: cube.key, name: 'Brühe'), const IngredientLine(amount: 100, unitKey: 'gram', name: 'Mehl'), ], ), ], ), ); await recipes.saveRecipe(recipe(id: 'r2', name: 'Ohne Würfel')); expect(await units.recipeCount(cube.key), 1); await units.deleteOwn(cube); final lines = (await recipes.getRecipe('r1'))!.ingredientGroups.single.lines; expect((lines[0].amount, lines[0].unitKey, lines[0].name), (2, null, 'Würfel Brühe')); expect((lines[1].unitKey, lines[1].name), ('gram', 'Mehl')); expect((await units.allUnits()).any((u) => u.key == cube.key), isFalse); }); test('an existing version 1 database gets the units table 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()); // Make it look like the database before units existed. await fileDb.customStatement('DROP TABLE units'); await fileDb.customStatement('PRAGMA user_version = 1'); await fileDb.close(); fileDb = testDatabase(file: file); expect(await UnitRepository(fileDb).allUnits(), hasLength(Unit.values.length)); expect((await RecipeRepository(fileDb, photos).getRecipe('r1'))!.name, 'Focaccia'); await fileDb.close(); await dir.delete(recursive: true); db = testDatabase(); // for tearDown }); }