import 'package:eatvio_app/app_keys.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart'; import 'package:eatvio_app/features/create_recipe/presentation/widgets/info_about_recipe_widget.dart'; import 'package:eatvio_app/features/create_recipe/presentation/widgets/ingredients_widget.dart'; import 'package:eatvio_app/features/create_recipe/presentation/widgets/steps_widget.dart'; import 'package:eatvio_app/features/create_recipe/reporitories/recipe_repository.dart'; import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'simple_widget_test.mocks.dart'; @GenerateMocks([RecipeRepository, GlossaryRepository]) void main() { group('Recipe Creation Widget Tests', () { late MockRecipeRepository mockRecipeRepository; late MockGlossaryRepository mockGlossaryRepository; late CreateRecipeCubit createRecipeCubit; setUp(() { mockRecipeRepository = MockRecipeRepository(); mockGlossaryRepository = MockGlossaryRepository(); createRecipeCubit = CreateRecipeCubit(recipeRepository: mockRecipeRepository, glossaryRepository: mockGlossaryRepository); }); tearDown(() { createRecipeCubit.close(); }); Widget createTestWidget(Widget child) { return MaterialApp( theme: ThemeHelper().themeData(), home: BlocProvider( create: (context) => createRecipeCubit, child: Scaffold(body: child), ), ); } testWidgets('should display InfoAboutRecipeWidget with all form fields', (WidgetTester tester) async { // Arrange & Act await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.recipeCreateScreenTitleField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenTypeDropdown), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenPortionsField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenCaloriesField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenTotalHoursField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenTotalMinutesField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenActiveHoursField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenActiveMinutesField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenDescriptionField), findsOneWidget); }); testWidgets('should display IngredientsWidget with add button', (WidgetTester tester) async { // Arrange & Act await tester.pumpWidget(createTestWidget(const IngredientsWidget())); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.recipeCreateScreenAddIngredientButton), findsOneWidget); }); testWidgets('should display StepsWidget with add button', (WidgetTester tester) async { // Arrange & Act await tester.pumpWidget(createTestWidget(StepsWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.recipeCreateScreenAddStepButton), findsOneWidget); }); testWidgets('should update title when user types in title field', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testTitle = 'Тестовый рецепт'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenTitleField), testTitle); await tester.pump(); // Assert expect(find.text(testTitle), findsOneWidget); }); testWidgets('should update portions when user types in portions field', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testPortions = '4'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenPortionsField), testPortions); await tester.pump(); // Assert expect(find.text(testPortions), findsOneWidget); }); testWidgets('should update calories when user types in calories field', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testCalories = '250'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenCaloriesField), testCalories); await tester.pump(); // Assert expect(find.text(testCalories), findsOneWidget); }); testWidgets('should update description when user types in description field', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testDescription = 'Это тестовое описание рецепта'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenDescriptionField), testDescription); await tester.pump(); // Assert expect(find.text(testDescription), findsOneWidget); }); testWidgets('should update cooking time fields', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testHours = '1'; const testMinutes = '30'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenTotalHoursField), testHours); await tester.enterText(find.byKey(AppKeys.recipeCreateScreenTotalMinutesField), testMinutes); await tester.pump(); // Assert expect(find.text(testHours), findsOneWidget); expect(find.text(testMinutes), findsOneWidget); }); testWidgets('should update active cooking time fields', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testActiveHours = '0'; const testActiveMinutes = '45'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenActiveHoursField), testActiveHours); await tester.enterText(find.byKey(AppKeys.recipeCreateScreenActiveMinutesField), testActiveMinutes); await tester.pump(); // Assert expect(find.text(testActiveHours), findsOneWidget); expect(find.text(testActiveMinutes), findsOneWidget); }); testWidgets('should add ingredient when add ingredient button is tapped', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(const IngredientsWidget())); await tester.pumpAndSettle(); // Act await tester.tap(find.byKey(AppKeys.recipeCreateScreenAddIngredientButton)); await tester.pump(const Duration(milliseconds: 300)); // Assert - should show ingredient modal or form expect(find.byKey(AppKeys.recipeCreateScreenIngredientNameField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenIngredientQuantityField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenIngredientAddButton), findsOneWidget); }); testWidgets('should add step when add step button is tapped', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(StepsWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); // Act await tester.tap(find.byKey(AppKeys.recipeCreateScreenAddStepButton)); await tester.pump(const Duration(milliseconds: 300)); // Assert - should show additional step field expect(find.byKey(AppKeys.recipeCreateScreenStepDescriptionField), findsAtLeastNWidgets(2)); }); testWidgets('should add tag when add tag button is tapped', (WidgetTester tester) async { // Arrange await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); const testTag = 'тестовый тег'; // Act await tester.enterText(find.byKey(AppKeys.recipeCreateScreenTagField), testTag); await tester.tap(find.byKey(AppKeys.recipeCreateScreenAddTagButton)); await tester.pump(const Duration(milliseconds: 300)); // Assert - should show the added tag expect(find.text(testTag), findsOneWidget); }); testWidgets('should display loading state when cubit is loading', (WidgetTester tester) async { // Arrange final loadingCubit = CreateRecipeCubit(recipeRepository: mockRecipeRepository, glossaryRepository: mockGlossaryRepository); Widget loadingWidget() { return MaterialApp( theme: ThemeHelper().themeData(), home: BlocProvider( create: (context) => loadingCubit, child: const Scaffold(body: Center(child: CircularProgressIndicator())), ), ); } // Act await tester.pumpWidget(loadingWidget()); await tester.pump(); // Assert - should show loading indicator expect(find.byType(CircularProgressIndicator), findsOneWidget); loadingCubit.close(); }); testWidgets('should display form labels correctly', (WidgetTester tester) async { // Arrange & Act await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); // Assert expect(find.text('Название'), findsOneWidget); expect(find.text('Тип блюда'), findsOneWidget); expect(find.text('Количество порций'), findsOneWidget); expect(find.text('Калорийность'), findsOneWidget); expect(find.text('Общее время приготовления'), findsOneWidget); expect(find.text('Активное время приготовления'), findsOneWidget); expect(find.text('Описание'), findsOneWidget); }); testWidgets('should display placeholder text in form fields', (WidgetTester tester) async { // Arrange & Act await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); // Assert expect(find.text('Например: тар-тар из говядины'), findsOneWidget); }); testWidgets('should display time input fields with correct labels', (WidgetTester tester) async { // Arrange & Act await tester.pumpWidget(createTestWidget(InfoAboutRecipeWidget(createRecipeCubit: createRecipeCubit))); await tester.pumpAndSettle(); // Assert expect(find.text('Часы'), findsAtLeastNWidgets(2)); // Total and Active hours expect(find.text('Минуты'), findsAtLeastNWidgets(2)); // Total and Active minutes }); }); }