import 'package:cookit/src/recipes/views/widgets/recipe_card.dart'; import 'package:cookit/src/recipes/views/widgets/recipe_photo.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import '../support/fixtures.dart'; import '../support/test_app.dart'; Finder inSheet(Finder finder) => find.descendant(of: find.byType(BottomSheet), matching: finder); void main() { testWidgets('"Hilf mir entscheiden" narrows down by Course and time', (tester) async { final app = await TestApp.create(tester); final courses = (await tester.runAsync(app.courses.allCourses))!; final dessert = courses.firstWhere((c) => c.name == 'Dessert'); final main = courses.firstWhere((c) => c.name == 'Hauptgericht'); await tester.runAsync(() async { await app.recipes.saveRecipe( recipe( id: 'a', name: 'Kaiserschmarrn', courseId: dessert.id, ).copyWith(prepMinutes: () => 10, cookMinutes: () => 10), ); await app.recipes.saveRecipe(recipe(id: 'b', name: 'Tiramisu', courseId: dessert.id)); // 50 min await app.recipes.saveRecipe(recipe(id: 'c', name: 'Rinderrouladen', courseId: main.id)); }); await tester.pumpWidget(app.build()); await app.settle(tester); await tester.tap(find.byTooltip('Hilf mir entscheiden')); await tester.pumpAndSettle(); expect(find.text('Worauf hast du Lust?'), findsOneWidget); await tester.tap(inSheet(find.text('Dessert'))); await tester.pumpAndSettle(); await tester.tap(find.text('Weiter')); await tester.pumpAndSettle(); expect(find.text('Wie viel Zeit hast du?'), findsOneWidget); await tester.tap(find.text('bis 30 Min.')); await tester.pumpAndSettle(); await tester.tap(find.text('Vorschlag zeigen')); await tester.pumpAndSettle(); expect(find.text('1 Rezept passt'), findsOneWidget); expect(inSheet(find.text('Kaiserschmarrn')), findsOneWidget); await tester.tap(find.text('Rezept öffnen')); await app.settle(tester); expect(find.text('Kochmodus starten'), findsOneWidget); expect(find.text('Kaiserschmarrn'), findsOneWidget); await app.dispose(tester); }); testWidgets('the decision helper offers a looser choice when nothing fits', (tester) async { final app = await TestApp.create(tester); await tester.runAsync(() => app.recipes.saveRecipe(recipe())); // 50 min, no Course await tester.pumpWidget(app.build()); await app.settle(tester); await tester.tap(find.byTooltip('Hilf mir entscheiden')); await tester.pumpAndSettle(); await tester.tap(find.text('Weiter')); await tester.pumpAndSettle(); await tester.tap(find.text('bis 30 Min.')); await tester.tap(find.text('Vorschlag zeigen')); await tester.pumpAndSettle(); expect(find.text('Dazu passt leider nichts.'), findsOneWidget); await tester.tap(find.text('Ohne Zeitlimit: 1')); await tester.pumpAndSettle(); expect(find.text('1 Rezept passt'), findsOneWidget); await app.dispose(tester); }); testWidgets('Darstellung switches between light and dark', (tester) async { final app = await TestApp.create(tester); await tester.pumpWidget(app.build()); await app.settle(tester); ThemeMode mode() => tester.widget(find.byType(MaterialApp)).themeMode!; expect(mode(), ThemeMode.light); await tester.tap(find.byTooltip('Einstellungen')); await tester.pumpAndSettle(); await tester.tap(find.text('Dunkel')); await app.settle(tester); expect(mode(), ThemeMode.dark); await app.dispose(tester); }); testWidgets('an own unit added in the settings is offered in the unit picker', (tester) async { final app = await TestApp.create(tester); await tester.pumpWidget(app.build()); await app.settle(tester); await tester.tap(find.byTooltip('Einstellungen')); await tester.pumpAndSettle(); await tester.tap(find.text('Maßeinheiten bearbeiten')); await app.settle(tester); await tester.tap(find.text('Einheit hinzufügen')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextFormField), 'Würfel'); await tester.tap(find.text('Speichern')); await app.settle(tester); expect(find.text('Würfel'), findsOneWidget); expect(find.text('Eigene Einheit'), findsOneWidget); await tester.tap(find.byTooltip('Zurück')); await tester.pumpAndSettle(); await tester.tap(find.byTooltip('Zurück')); await app.settle(tester); await tester.tap(find.byTooltip('Neues Rezept')); await app.settle(tester); await tester.tap(find.text('–')); await tester.pumpAndSettle(); expect(find.widgetWithText(ChoiceChip, 'Würfel'), findsOneWidget); await app.dispose(tester); }); testWidgets('tapping a photo can make it the main Photo', (tester) async { final app = await TestApp.create(tester); final (first, second) = (await tester.runAsync(() async { final a = await app.photos.saveBytes(Uint8List.fromList([1])); final b = await app.photos.saveBytes(Uint8List.fromList([2])); await app.recipes.saveRecipe(recipe(photos: [a, b])); return (a, b); }))!; await tester.pumpWidget(app.build()); await app.settle(tester); await tester.tap(find.descendant(of: find.byType(RecipeCard), matching: find.text('Focaccia'))); await app.settle(tester); await tester.tap(find.byTooltip('Bearbeiten')); await app.settle(tester); expect(find.textContaining('das erste Foto ist das Hauptfoto'), findsOneWidget); // The photo is covered by its own tap layer, which is what receives the tap. await tester.tap(find.byType(RecipePhoto).at(1), warnIfMissed: false); await tester.pumpAndSettle(); await tester.tap(find.text('Als Hauptfoto festlegen')); await tester.pumpAndSettle(); await tester.tap(find.text('Speichern')); await app.settle(tester); expect((await tester.runAsync(() => app.recipes.getRecipe('r1')))!.photos, [second, first]); await app.dispose(tester); }); testWidgets('"Zutaten teilen" shares the ingredients for the chosen servings', (tester) async { final shared = >[]; tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( const MethodChannel('dev.fluttercommunity.plus/share'), (call) async { shared.add(call.arguments as Map); return 'dev.fluttercommunity.plus/share/unavailable'; }, ); 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.text('Focaccia'))); await app.settle(tester); await tester.scrollUntilVisible(find.text('Zutaten teilen'), 200, scrollable: find.byType(Scrollable).first); await tester.tap(find.text('Zutaten teilen')); await tester.pumpAndSettle(); await tester.tap(inSheet(find.byTooltip('Mehr Portionen'))); await tester.pumpAndSettle(); await tester.tap(find.text('Teilen')); await tester.pumpAndSettle(); expect(shared, hasLength(1)); expect(shared.single['text'], '375 g Mehl\n2½–3¾ EL Olivenöl (gutes)\n\nRosmarin'); expect(shared.single['subject'], 'Focaccia – Zutaten für 5 Portionen'); await app.dispose(tester); }); }