import 'package:eatvio_app/core/app_config.dart'; import 'package:eatvio_app/core/app_initializer.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:eatvio_app/features/feed/models/recipes_model.dart' as recipes; import 'package:eatvio_app/features/recipe/presentation/widgets/ingredients_widget.dart'; import 'package:eatvio_app/features/recipe/presentation/widgets/steps_widget.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:network_image_mock/network_image_mock.dart'; void main() { group('Recipes Widgets Tests', () { setUp(() async { await sl.reset(); dotenv.loadFromString(envString: 'DEV_BASE_URL=http://localhost\nBASE_URL=http://localhost'); sl.registerLazySingleton(() => AppConfig(buildType: AppBuildType.tests)..setBaseUrl('http://localhost')); }); Widget createTestWidget(Widget child) { return MaterialApp( theme: ThemeHelper().themeData(), localizationsDelegates: const [ S.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: const [Locale('ru')], home: Portal( child: Scaffold(body: SingleChildScrollView(child: child)), ), ); } group('IngredientsWidget', () { testWidgets('should display IngredientsWidget with ingredients', (WidgetTester tester) async { // Arrange const recipe = recipes.Recipe( id: 1, image: 'test-image.jpg', state: 'active', cookingTime: 30, activeCookingTime: 15, ingredients: [ recipes.Ingredient(name: 'Flour', unit: 'g', portion: '200', productId: 1), recipes.Ingredient(name: 'Sugar', unit: 'g', portion: '100', productId: 2), ], description: 'Test recipe', steps: [], videoUrl: null, createdAt: null, updatedAt: null, title: 'Test Recipe', type: 'main', slug: 'test-recipe', commentsCount: 0, wasLikedByMe: false, isFavorite: false, calories: 300.0, servings: 4, likesCount: 0, viewsCount: 0, tags: [], author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), ); const widget = IngredientsWidget(recipe: recipe); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 300)); // Assert expect(find.byType(IngredientsWidget), findsOneWidget); expect(find.byType(ExpansionTile), findsOneWidget); // The ingredients text may be formatted with units, so just check the widget structure }); testWidgets('should display IngredientsWidget with empty ingredients', (WidgetTester tester) async { // Arrange const recipe = recipes.Recipe( id: 1, image: 'test-image.jpg', state: 'active', cookingTime: 30, activeCookingTime: 15, ingredients: [], description: 'Test recipe', steps: [], videoUrl: null, createdAt: null, updatedAt: null, title: 'Test Recipe', type: 'main', slug: 'test-recipe', commentsCount: 0, wasLikedByMe: false, isFavorite: false, calories: 300.0, servings: 4, likesCount: 0, viewsCount: 0, tags: [], author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), ); const widget = IngredientsWidget(recipe: recipe); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(IngredientsWidget), findsOneWidget); }); }); group('StepsWidget', () { testWidgets('should display StepsWidget with steps', (WidgetTester tester) async { await mockNetworkImagesFor(() async { // Arrange const recipe = recipes.Recipe( id: 1, image: 'test-image.jpg', state: 'active', cookingTime: 30, activeCookingTime: 15, ingredients: [], description: 'Test recipe', steps: [ recipes.Step(image: 'step1.jpg', description: 'Step 1 description'), recipes.Step(image: 'step2.jpg', description: 'Step 2 description'), ], videoUrl: null, createdAt: null, updatedAt: null, title: 'Test Recipe', type: 'main', slug: 'test-recipe', commentsCount: 0, wasLikedByMe: false, isFavorite: false, calories: 300.0, servings: 4, likesCount: 0, viewsCount: 0, tags: [], author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), ); const widget = StepsWidget(recipe: recipe); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(StepsWidget), findsOneWidget); expect(find.text('Step 1 description'), findsOneWidget); expect(find.text('Step 2 description'), findsOneWidget); }); await tester.pump(const Duration(milliseconds: 600)); }); testWidgets('should display StepsWidget with steps without images', (WidgetTester tester) async { // Arrange const recipe = recipes.Recipe( id: 1, image: 'test-image.jpg', state: 'active', cookingTime: 30, activeCookingTime: 15, ingredients: [], description: 'Test recipe', steps: [ recipes.Step(image: '', description: 'Step 1 description'), recipes.Step(image: '', description: 'Step 2 description'), ], videoUrl: null, createdAt: null, updatedAt: null, title: 'Test Recipe', type: 'main', slug: 'test-recipe', commentsCount: 0, wasLikedByMe: false, isFavorite: false, calories: 300.0, servings: 4, likesCount: 0, viewsCount: 0, tags: [], author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), ); const widget = StepsWidget(recipe: recipe); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(StepsWidget), findsOneWidget); expect(find.text('Step 1 description'), findsOneWidget); expect(find.text('Step 2 description'), findsOneWidget); }); testWidgets('should display StepsWidget with empty steps', (WidgetTester tester) async { // Arrange const recipe = recipes.Recipe( id: 1, image: 'test-image.jpg', state: 'active', cookingTime: 30, activeCookingTime: 15, ingredients: [], description: 'Test recipe', steps: [], videoUrl: null, createdAt: null, updatedAt: null, title: 'Test Recipe', type: 'main', slug: 'test-recipe', commentsCount: 0, wasLikedByMe: false, isFavorite: false, calories: 300.0, servings: 4, likesCount: 0, viewsCount: 0, tags: [], author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), ); const widget = StepsWidget(recipe: recipe); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(StepsWidget), findsOneWidget); }); }); }); }