import 'dart:io'; import 'package:cookit/src/app.dart'; import 'package:cookit/src/bundle/bundle_service.dart'; import 'package:cookit/src/database/database.dart'; import 'package:cookit/src/planning/plan_repository.dart'; import 'package:cookit/src/planning/plan_share_service.dart'; import 'package:cookit/src/planning/week_plan_provider.dart'; import 'package:cookit/src/recipes/course_repository.dart'; import 'package:cookit/src/recipes/photo_store.dart'; import 'package:cookit/src/recipes/recipe_list_provider.dart'; import 'package:cookit/src/recipes/recipe_repository.dart'; import 'package:cookit/src/recipes/unit_catalog.dart'; import 'package:cookit/src/recipes/unit_repository.dart'; import 'package:cookit/src/settings/settings_controller.dart'; import 'package:cookit/src/sharing/recipe_share_service.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'fixtures.dart'; import 'test_database.dart'; /// The real app wired to an in-memory database and a temporary photo folder. class TestApp { TestApp._(this.db, this.photos) : recipes = RecipeRepository(db, photos), courses = CourseRepository(db), units = UnitRepository(db), plan = PlanRepository(db), bundles = BundleService(RecipeRepository(db, photos), CourseRepository(db), UnitRepository(db), photos); final AppDatabase db; final PhotoStore photos; final RecipeRepository recipes; final CourseRepository courses; final UnitRepository units; final PlanRepository plan; final BundleService bundles; static Future create(WidgetTester tester) async { SharedPreferences.setMockInitialValues({}); // A tall phone (400 x 2000 logical px) so long forms are built without scrolling. tester.view.physicalSize = const Size(1200, 6000); tester.view.devicePixelRatio = 3; addTearDown(tester.view.reset); final photos = (await tester.runAsync(tempPhotoStore))!; return TestApp._(testDatabase(), photos); } Widget build() => MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => SettingsController(SettingsService())), Provider.value(value: photos), Provider.value(value: recipes), Provider.value(value: courses), Provider.value(value: units), Provider.value(value: plan), ChangeNotifierProvider(create: (_) => UnitCatalog(units)), Provider.value(value: bundles), Provider(create: (_) => RecipeShareService(recipes, courses, units, photos, bundles)), Provider(create: (_) => PlanShareService(recipes, courses, units, photos, plan, bundles)), ChangeNotifierProvider(create: (_) => RecipeListProvider(recipes, courses)), ChangeNotifierProvider(create: (_) => WeekPlanProvider(plan)), ], child: const CookItApp(), ); /// Lets database work and the resulting stream updates finish, then redraws. Future settle(WidgetTester tester) async { await tester.runAsync(() => Future.delayed(const Duration(milliseconds: 50))); await tester.pumpAndSettle(); } Future dispose(WidgetTester tester) async { await tester.pumpWidget(const SizedBox()); await tester.runAsync(() async { await db.close(); try { await photos.directory.delete(recursive: true); } on FileSystemException { // Windows keeps a just-decoded image file open for a moment; the temp folder can stay. } }); } }