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/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 'basic_widget_test.mocks.dart'; @GenerateMocks([RecipeRepository, GlossaryRepository]) void main() { group('Recipe Creation Basic 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: SingleChildScrollView(child: child)), ), ); } testWidgets('should create CreateRecipeCubit successfully', (WidgetTester tester) async { // Arrange & Act final cubit = CreateRecipeCubit(recipeRepository: mockRecipeRepository, glossaryRepository: mockGlossaryRepository); // Assert expect(cubit, isA()); expect(cubit.state.loading, isTrue); cubit.close(); }); testWidgets('should display basic form fields', (WidgetTester tester) async { // Arrange Widget formWidget = Column( children: [ TextFormField( key: AppKeys.recipeCreateScreenTitleField, decoration: const InputDecoration(labelText: 'Название', hintText: 'Например: тар-тар из говядины'), ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenDescriptionField, decoration: const InputDecoration(labelText: 'Описание'), maxLines: 3, ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenPortionsField, decoration: const InputDecoration(labelText: 'Количество порций'), keyboardType: TextInputType.number, ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenCaloriesField, decoration: const InputDecoration(labelText: 'Калорийность'), keyboardType: TextInputType.number, ), const SizedBox(height: 16), ElevatedButton(key: AppKeys.recipeCreateScreenPublishButton, onPressed: () {}, child: const Text('Опубликовать')), ], ); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.recipeCreateScreenTitleField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenDescriptionField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenPortionsField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenCaloriesField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenPublishButton), findsOneWidget); }); testWidgets('should update title when user types in title field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.recipeCreateScreenTitleField, decoration: const InputDecoration(labelText: 'Название', hintText: 'Например: тар-тар из говядины'), ); await tester.pumpWidget(createTestWidget(formWidget)); 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 description when user types in description field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.recipeCreateScreenDescriptionField, decoration: const InputDecoration(labelText: 'Описание'), maxLines: 3, ); await tester.pumpWidget(createTestWidget(formWidget)); 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 portions when user types in portions field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.recipeCreateScreenPortionsField, decoration: const InputDecoration(labelText: 'Количество порций'), keyboardType: TextInputType.number, ); await tester.pumpWidget(createTestWidget(formWidget)); 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 Widget formWidget = TextFormField( key: AppKeys.recipeCreateScreenCaloriesField, decoration: const InputDecoration(labelText: 'Калорийность'), keyboardType: TextInputType.number, ); await tester.pumpWidget(createTestWidget(formWidget)); 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 display form labels correctly', (WidgetTester tester) async { // Arrange Widget formWidget = const Column(children: [Text('Название'), Text('Описание'), Text('Количество порций'), Text('Калорийность')]); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.text('Название'), findsOneWidget); expect(find.text('Описание'), findsOneWidget); expect(find.text('Количество порций'), findsOneWidget); expect(find.text('Калорийность'), findsOneWidget); }); testWidgets('should display placeholder text in title field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.recipeCreateScreenTitleField, decoration: const InputDecoration(labelText: 'Название', hintText: 'Например: тар-тар из говядины'), ); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.text('Например: тар-тар из говядины'), findsOneWidget); }); testWidgets('should display publish button', (WidgetTester tester) async { // Arrange Widget formWidget = ElevatedButton(key: AppKeys.recipeCreateScreenPublishButton, onPressed: () {}, child: const Text('Опубликовать')); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.recipeCreateScreenPublishButton), findsOneWidget); expect(find.text('Опубликовать'), findsOneWidget); }); testWidgets('should handle button tap', (WidgetTester tester) async { // Arrange bool buttonPressed = false; Widget formWidget = ElevatedButton( key: AppKeys.recipeCreateScreenPublishButton, onPressed: () { buttonPressed = true; }, child: const Text('Опубликовать'), ); await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Act await tester.tap(find.byKey(AppKeys.recipeCreateScreenPublishButton)); await tester.pump(); // Assert expect(buttonPressed, isTrue); }); testWidgets('should display loading state', (WidgetTester tester) async { // Arrange Widget loadingWidget = const Center(child: CircularProgressIndicator()); // Act await tester.pumpWidget(createTestWidget(loadingWidget)); await tester.pump(); // Assert expect(find.byType(CircularProgressIndicator), findsOneWidget); }); testWidgets('should display error message', (WidgetTester tester) async { // Arrange Widget errorWidget = const Center(child: Text('Произошла ошибка при создании рецепта')); // Act await tester.pumpWidget(createTestWidget(errorWidget)); await tester.pumpAndSettle(); // Assert expect(find.text('Произошла ошибка при создании рецепта'), findsOneWidget); }); testWidgets('should display success message', (WidgetTester tester) async { // Arrange Widget successWidget = const Center(child: Text('Рецепт успешно создан!')); // Act await tester.pumpWidget(createTestWidget(successWidget)); await tester.pumpAndSettle(); // Assert expect(find.text('Рецепт успешно создан!'), findsOneWidget); }); testWidgets('should validate required fields', (WidgetTester tester) async { // Arrange Widget validationWidget = Column( children: [ TextFormField( key: AppKeys.recipeCreateScreenTitleField, decoration: const InputDecoration(labelText: 'Название', errorText: 'Название рецепта обязательно'), ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenDescriptionField, decoration: const InputDecoration(labelText: 'Описание', errorText: 'Описание рецепта обязательно'), ), ], ); // Act await tester.pumpWidget(createTestWidget(validationWidget)); await tester.pumpAndSettle(); // Assert expect(find.text('Название рецепта обязательно'), findsOneWidget); expect(find.text('Описание рецепта обязательно'), findsOneWidget); }); testWidgets('should display form with all required fields', (WidgetTester tester) async { // Arrange Widget completeForm = Column( children: [ TextFormField( key: AppKeys.recipeCreateScreenTitleField, decoration: const InputDecoration(labelText: 'Название', hintText: 'Например: тар-тар из говядины'), ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenDescriptionField, decoration: const InputDecoration(labelText: 'Описание'), maxLines: 3, ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenPortionsField, decoration: const InputDecoration(labelText: 'Количество порций'), keyboardType: TextInputType.number, ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenCaloriesField, decoration: const InputDecoration(labelText: 'Калорийность'), keyboardType: TextInputType.number, ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenTotalHoursField, decoration: const InputDecoration(labelText: 'Часы'), keyboardType: TextInputType.number, ), const SizedBox(height: 16), TextFormField( key: AppKeys.recipeCreateScreenTotalMinutesField, decoration: const InputDecoration(labelText: 'Минуты'), keyboardType: TextInputType.number, ), const SizedBox(height: 32), ElevatedButton(key: AppKeys.recipeCreateScreenPublishButton, onPressed: () {}, child: const Text('Опубликовать')), ], ); // Act await tester.pumpWidget(createTestWidget(completeForm)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.recipeCreateScreenTitleField), findsOneWidget); expect(find.byKey(AppKeys.recipeCreateScreenDescriptionField), 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.recipeCreateScreenPublishButton), findsOneWidget); }); }); }