import 'package:commons_core/commons_core.dart'; import 'package:drift/native.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tane/data/variety_repository.dart'; import 'package:tane/db/database.dart'; import 'package:tane/i18n/strings.g.dart'; import 'package:tane/state/inventory_cubit.dart'; import 'package:tane/state/variety_detail_cubit.dart'; import 'package:tane/ui/variety_detail_screen.dart'; /// A fresh in-memory database for host tests (unencrypted; encryption is /// verified separately in the SQLCipher-only security test). AppDatabase newTestDatabase() => AppDatabase(NativeDatabase.memory()); /// Unmounts the widget tree *inside* the test and drains the zero-duration /// timer Drift schedules when its stream subscription is cancelled. Without /// this, flutter_test reports "a Timer is still pending after disposal". Call /// at the end of any widget test that mounts an [InventoryCubit]. Future disposeTree(WidgetTester tester) async { await tester.pumpWidget(const SizedBox.shrink()); await tester.pump(const Duration(milliseconds: 10)); } VarietyRepository newTestRepository( AppDatabase db, { String nodeId = 'test-node', }) => VarietyRepository(db, idGen: IdGen(), nodeId: nodeId); /// Wraps [child] with the providers a screen expects (repository, inventory /// cubit) plus i18n and Material localizations, pinned to [locale]. Widget wrapScreen({ required VarietyRepository repository, required Widget child, AppLocale locale = AppLocale.en, }) { LocaleSettings.setLocaleSync(locale); return TranslationProvider( child: RepositoryProvider.value( value: repository, child: BlocProvider( create: (_) => InventoryCubit(repository), child: MaterialApp( locale: locale.flutterLocale, supportedLocales: AppLocaleUtils.supportedLocales, localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], home: child, ), ), ), ); } /// Wraps the [VarietyDetailScreen] for [varietyId] with its cubit + i18n. Widget wrapDetail({ required VarietyRepository repository, required String varietyId, AppLocale locale = AppLocale.en, }) { LocaleSettings.setLocaleSync(locale); return TranslationProvider( child: RepositoryProvider.value( value: repository, child: BlocProvider( create: (_) => VarietyDetailCubit(repository, varietyId), child: MaterialApp( locale: locale.flutterLocale, supportedLocales: AppLocaleUtils.supportedLocales, localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], home: const VarietyDetailScreen(), ), ), ), ); }