Files
CookIT/test/views/app_flow_test.dart
2026-10-28 22:55:09 +01:00

233 lines
9.3 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:cookit/src/recipes/models/recipe.dart';
import 'package:cookit/src/recipes/views/widgets/recipe_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../support/fixtures.dart';
import '../support/test_app.dart';
/// A Recipe name as shown on a grid card (the suggestion card may show it too).
Finder inGrid(String text) => find.descendant(of: find.byType(RecipeCard), matching: find.text(text));
void main() {
testWidgets('home grid shows Recipes and filters them by search, Course and review', (tester) async {
final app = await TestApp.create(tester);
final dessert = (await tester.runAsync(() => app.courses.findOrCreate('Dessert')))!;
await tester.runAsync(() async {
await app.recipes.saveRecipe(recipe(id: 'a', name: 'Käsespätzle', tags: ['schwäbisch']));
await app.recipes.saveRecipe(
recipe(id: 'b', name: 'Tiramisu', courseId: dessert.id, reviewReasons: ['Portionen fehlen.']),
);
});
await tester.pumpWidget(app.build());
await app.settle(tester);
expect(inGrid('Käsespätzle'), findsOneWidget);
expect(inGrid('Tiramisu'), findsOneWidget);
expect(find.text('IDEE FÜR HEUTE'), findsOneWidget);
await tester.enterText(find.byType(TextField), 'kase');
await tester.pumpAndSettle();
expect(inGrid('Käsespätzle'), findsOneWidget);
expect(inGrid('Tiramisu'), findsNothing);
await tester.enterText(find.byType(TextField), '');
await tester.tap(find.text('1 Rezept wartet auf deinen Blick'));
await tester.pumpAndSettle();
expect(inGrid('Käsespätzle'), findsNothing);
expect(inGrid('Tiramisu'), findsOneWidget);
await tester.tap(find.text('Nur Rezepte zum Prüfen – alle zeigen'));
await tester.pumpAndSettle();
final chips = find.byWidgetPredicate((w) => w is ListView && w.scrollDirection == Axis.horizontal);
final dessertChip = find.descendant(of: chips, matching: find.text('Dessert'));
await tester.scrollUntilVisible(
dessertChip,
200,
scrollable: find.descendant(of: chips, matching: find.byType(Scrollable)),
);
await tester.tap(dessertChip);
await tester.pumpAndSettle();
expect(inGrid('Tiramisu'), findsOneWidget);
expect(inGrid('Käsespätzle'), findsNothing);
await app.dispose(tester);
});
testWidgets('Cooking Mode walks through the ingredients and every step', (tester) async {
final app = await TestApp.create(tester);
await tester.runAsync(() => app.recipes.saveRecipe(recipe()));
await tester.pumpWidget(app.build());
await app.settle(tester);
await tester.tap(inGrid('Focaccia'));
await app.settle(tester);
await tester.tap(find.text('Kochmodus starten'));
await app.settle(tester);
expect(find.text('Bereit zum Kochen?'), findsOneWidget);
expect(find.text('300 g'), findsOneWidget);
await tester.tap(find.byTooltip('Mehr Portionen'));
await tester.pumpAndSettle();
expect(find.text('5'), findsOneWidget);
expect(find.text('375 g'), findsOneWidget);
await tester.tap(find.text('Los geht’s'));
await tester.pumpAndSettle();
expect(find.text('Schritt 1 von 2'), findsOneWidget);
expect(find.text('Kneten.'), findsOneWidget);
expect(find.text('Teig'), findsOneWidget);
await tester.tap(find.text('Weiter'));
await tester.pumpAndSettle();
expect(find.text('Gehen lassen.'), findsOneWidget);
await tester.tap(find.text('Fertig'));
await tester.pumpAndSettle();
expect(find.text('Guten Appetit!'), findsOneWidget);
await tester.tap(find.text('Zurück zum Rezept'));
await app.settle(tester);
expect(find.text('Kochmodus starten'), findsOneWidget);
await app.dispose(tester);
});
testWidgets('the heart on a card toggles the favourite', (tester) async {
final app = await TestApp.create(tester);
await tester.runAsync(() => app.recipes.saveRecipe(recipe()));
await tester.pumpWidget(app.build());
await app.settle(tester);
await tester.tap(find.descendant(of: find.byType(RecipeCard), matching: find.byTooltip('Favorit')));
await app.settle(tester);
expect((await tester.runAsync(app.recipes.allRecipes))!.single.favourite, isTrue);
await app.dispose(tester);
});
testWidgets('empty collection explains how to start', (tester) async {
final app = await TestApp.create(tester);
await tester.pumpWidget(app.build());
await app.settle(tester);
expect(find.text('Noch keine Rezepte'), findsOneWidget);
await app.dispose(tester);
});
testWidgets('detail shows the Recipe, and "Erledigt" clears its Review Flag', (tester) async {
final app = await TestApp.create(tester);
await tester.runAsync(() => app.recipes.saveRecipe(recipe(reviewReasons: ['Portionen fehlen.'])));
await tester.pumpWidget(app.build());
await app.settle(tester);
await tester.tap(inGrid('Focaccia'));
await app.settle(tester);
expect(find.text('Bitte prüfen'), findsOneWidget);
expect(find.text('• Portionen fehlen.'), findsOneWidget);
expect(find.text('300 g'), findsOneWidget);
expect(find.text('2–3 EL'), findsOneWidget);
expect(find.text('Topping'), findsOneWidget);
expect(find.text('775 kcal'), findsOneWidget);
expect(find.text('pro Portion'), findsOneWidget);
expect(find.text('50 Min.'), findsOneWidget);
expect(find.text('22x22 cm Form'), findsOneWidget, reason: 'Notes show under the Zutaten tab too');
await tester.tap(find.text('Zubereitung · 2'));
await tester.pumpAndSettle();
expect(find.text('Teig'), findsOneWidget);
expect(find.text('Kneten.'), findsOneWidget);
expect(find.text('22x22 cm Form'), findsOneWidget);
await tester.tap(find.text('Erledigt'));
await app.settle(tester);
expect(find.text('Bitte prüfen'), findsNothing);
await app.dispose(tester);
});
testWidgets('a new Recipe can be created with ingredients and steps', (tester) async {
final app = await TestApp.create(tester);
await tester.pumpWidget(app.build());
await app.settle(tester);
await tester.tap(find.byTooltip('Neues Rezept'));
await app.settle(tester);
await tester.tap(find.text('Speichern'));
await tester.pumpAndSettle();
expect(find.text('Bitte gib dem Rezept einen Namen.'), findsOneWidget);
await tester.enterText(find.widgetWithText(TextFormField, 'Name'), 'Pfannkuchen');
await tester.enterText(find.widgetWithText(TextFormField, 'Portionen'), '2');
final ingredientName = find.widgetWithText(TextFormField, 'Zutat');
await tester.enterText(find.widgetWithText(TextFormField, 'Menge'), '1,5');
await tester.enterText(ingredientName, 'Mehl');
await tester.tap(find.text('–'));
await tester.pumpAndSettle();
expect(find.text('Bund'), findsNothing);
await tester.tap(find.text('Weitere Einheiten …'));
await tester.pumpAndSettle();
await tester.tap(find.widgetWithText(ChoiceChip, 'Bund'));
await tester.pumpAndSettle();
expect(find.text('Bund'), findsOneWidget);
await tester.enterText(find.widgetWithText(TextFormField, 'Schritt 1'), 'Alles verrühren.');
await tester.tap(find.text('Speichern'));
await app.settle(tester);
expect(inGrid('Pfannkuchen'), findsOneWidget);
final saved = (await tester.runAsync(app.recipes.allRecipes))!.single;
expect(saved.servings, 2);
expect(saved.ingredientGroups.single.lines.single.amount, 1.5);
expect(saved.ingredientGroups.single.lines.single.name, 'Mehl');
expect(saved.ingredientGroups.single.lines.single.unitKey, 'bunch');
expect(saved.stepSections.single.steps, ['Alles verrühren.']);
expect(saved.calories, isNull);
expect(saved.needsReview, isFalse);
await app.dispose(tester);
});
testWidgets('an invalid amount blocks saving', (tester) async {
final app = await TestApp.create(tester);
await tester.pumpWidget(app.build());
await app.settle(tester);
await tester.tap(find.byTooltip('Neues Rezept'));
await app.settle(tester);
await tester.enterText(find.widgetWithText(TextFormField, 'Name'), 'Test');
await tester.enterText(find.widgetWithText(TextFormField, 'Menge'), 'viel');
await tester.tap(find.text('Speichern'));
await app.settle(tester);
expect(find.text('z. B. 2, 1,5, ½ oder 2-3'), findsOneWidget);
expect(await tester.runAsync(app.recipes.allRecipes), isEmpty);
await app.dispose(tester);
});
testWidgets('editing keeps favourite and Review Flag', (tester) async {
final app = await TestApp.create(tester);
await tester.runAsync(() => app.recipes.saveRecipe(recipe(favourite: true, reviewReasons: ['x'])));
await tester.pumpWidget(app.build());
await app.settle(tester);
await tester.tap(inGrid('Focaccia'));
await app.settle(tester);
await tester.tap(find.byTooltip('Bearbeiten'));
await app.settle(tester);
await tester.enterText(find.widgetWithText(TextFormField, 'Name'), 'Focaccia mit Rosmarin');
await tester.tap(find.text('Speichern'));
await app.settle(tester);
final saved = (await tester.runAsync(app.recipes.allRecipes))!.single;
expect(saved.name, 'Focaccia mit Rosmarin');
expect(saved.favourite, isTrue);
expect(saved.reviewReasons, ['x']);
expect(saved.calories!.basis, CaloriesBasis.perServing);
expect(saved.ingredientGroups.map((g) => g.name), [null, 'Topping']);
expect(saved.stepSections.single.title, 'Teig');
await app.dispose(tester);
});
}