import 'package:eatvio_app/app_keys.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../fixtures/doubles/blog_post_doubles.dart'; void main() { group('Blog Post Creation Basic Widget Tests', () { late FixtureBlogPostRepository blogPostRepository; late BlogPostCreateCubit blogPostCreateCubit; setUp(() { blogPostRepository = FixtureBlogPostRepository(); blogPostCreateCubit = BlogPostCreateCubit(blogPostRepository: blogPostRepository); }); tearDown(() { blogPostCreateCubit.close(); }); Widget createTestWidget(Widget child) { return MaterialApp( theme: ThemeHelper().themeData(), home: BlocProvider( create: (context) => blogPostCreateCubit, child: Scaffold(body: SingleChildScrollView(child: child)), ), ); } testWidgets('should create BlogPostCreateCubit successfully', (WidgetTester tester) async { // Arrange & Act final cubit = BlogPostCreateCubit(blogPostRepository: blogPostRepository); // Assert expect(cubit, isA()); cubit.close(); }); testWidgets('should display basic blog post form fields', (WidgetTester tester) async { // Arrange Widget formWidget = Column( children: [ TextFormField( key: AppKeys.blogPostCreateScreenTitleTextField, decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'), ), const SizedBox(height: 16), TextFormField( key: AppKeys.blogPostCreateScreenContentTextField, decoration: const InputDecoration(labelText: 'Описание'), maxLines: 6, minLines: 4, ), const SizedBox(height: 16), TextFormField( key: AppKeys.blogPostCreateScreenVideoLinkTextField, decoration: const InputDecoration(labelText: 'Ссылка на видео'), ), const SizedBox(height: 16), ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')), ], ); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenContentTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget); }); testWidgets('should update title when user types in title field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.blogPostCreateScreenTitleTextField, decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'), ); await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); const testTitle = 'Тестовый заголовок поста'; // Act await tester.enterText(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), 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.blogPostCreateScreenContentTextField, decoration: const InputDecoration(labelText: 'Описание'), maxLines: 6, minLines: 4, ); await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); const testDescription = 'Это тестовое описание блог поста'; // Act await tester.enterText(find.byKey(AppKeys.blogPostCreateScreenContentTextField), testDescription); await tester.pump(); // Assert expect(find.text(testDescription), findsOneWidget); }); testWidgets('should update video URL when user types in video field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.blogPostCreateScreenVideoLinkTextField, decoration: const InputDecoration(labelText: 'Ссылка на видео'), ); await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); const testVideoUrl = 'https://youtube.com/watch?v=example'; // Act await tester.enterText(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), testVideoUrl); await tester.pump(); // Assert expect(find.text(testVideoUrl), findsOneWidget); }); testWidgets('should display form labels correctly', (WidgetTester tester) async { // Arrange Widget formWidget = const Column(children: [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); }); testWidgets('should display placeholder text in title field', (WidgetTester tester) async { // Arrange Widget formWidget = TextFormField( key: AppKeys.blogPostCreateScreenTitleTextField, decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'), ); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.text('Введите заголовок поста'), findsOneWidget); }); testWidgets('should display create button', (WidgetTester tester) async { // Arrange Widget formWidget = ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')); // Act await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget); expect(find.text('Опубликовать'), findsOneWidget); }); testWidgets('should handle button tap', (WidgetTester tester) async { // Arrange bool buttonPressed = false; Widget formWidget = ElevatedButton( key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () { buttonPressed = true; }, child: const Text('Опубликовать'), ); await tester.pumpWidget(createTestWidget(formWidget)); await tester.pumpAndSettle(); // Act await tester.tap(find.byKey(AppKeys.blogPostCreateScreenCreateButton)); 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.blogPostCreateScreenTitleTextField, decoration: const InputDecoration(labelText: 'Заголовок', errorText: 'Заголовок обязателен'), ), const SizedBox(height: 16), TextFormField( key: AppKeys.blogPostCreateScreenContentTextField, 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.blogPostCreateScreenTitleTextField, decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'), ), const SizedBox(height: 16), TextFormField( key: AppKeys.blogPostCreateScreenContentTextField, decoration: const InputDecoration(labelText: 'Описание'), maxLines: 6, minLines: 4, ), const SizedBox(height: 16), TextFormField( key: AppKeys.blogPostCreateScreenVideoLinkTextField, decoration: const InputDecoration(labelText: 'Ссылка на видео'), ), const SizedBox(height: 32), ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')), ], ); // Act await tester.pumpWidget(createTestWidget(completeForm)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenContentTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget); }); testWidgets('should display image upload widget', (WidgetTester tester) async { // Arrange Widget imageWidget = GestureDetector( key: AppKeys.imageWidget, onTap: () {}, child: Container( height: 200, width: double.infinity, decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add_photo_alternate, size: 48, color: Colors.grey), SizedBox(height: 8), Text('Добавить изображение'), ], ), ), ), ); // Act await tester.pumpWidget(createTestWidget(imageWidget)); await tester.pumpAndSettle(); // Assert expect(find.byKey(AppKeys.imageWidget), findsOneWidget); expect(find.text('Добавить изображение'), findsOneWidget); }); testWidgets('should handle image upload tap', (WidgetTester tester) async { // Arrange bool imageUploadTapped = false; Widget imageWidget = GestureDetector( key: AppKeys.imageWidget, onTap: () { imageUploadTapped = true; }, child: Container( height: 200, width: double.infinity, decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add_photo_alternate, size: 48, color: Colors.grey), SizedBox(height: 8), Text('Добавить изображение'), ], ), ), ), ); await tester.pumpWidget(createTestWidget(imageWidget)); await tester.pumpAndSettle(); // Act await tester.tap(find.byKey(AppKeys.imageWidget)); await tester.pump(); // Assert expect(imageUploadTapped, isTrue); }); testWidgets('should display blog post creation form with image and video options', (WidgetTester tester) async { // Arrange Widget completeForm = Column( children: [ const Text('Заголовок'), const SizedBox(height: 8), TextFormField( key: AppKeys.blogPostCreateScreenTitleTextField, decoration: const InputDecoration(hintText: 'Введите заголовок поста'), ), const SizedBox(height: 16), const Text('Описание'), const SizedBox(height: 8), TextFormField(key: AppKeys.blogPostCreateScreenContentTextField, decoration: const InputDecoration(), maxLines: 6, minLines: 4), const SizedBox(height: 16), const Text('Изображение поста'), const SizedBox(height: 8), GestureDetector( key: AppKeys.imageWidget, onTap: () {}, child: Container( height: 200, width: double.infinity, decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add_photo_alternate, size: 48, color: Colors.grey), SizedBox(height: 8), Text('Добавить изображение'), ], ), ), ), ), const SizedBox(height: 16), const Text('Ссылка на видео'), const SizedBox(height: 8), TextFormField(key: AppKeys.blogPostCreateScreenVideoLinkTextField, decoration: const InputDecoration()), const SizedBox(height: 32), ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')), ], ); // Act await tester.pumpWidget(createTestWidget(completeForm)); await tester.pumpAndSettle(); // Assert expect(find.text('Заголовок'), findsOneWidget); expect(find.text('Описание'), findsOneWidget); expect(find.text('Изображение поста'), findsOneWidget); expect(find.text('Ссылка на видео'), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenContentTextField), findsOneWidget); expect(find.byKey(AppKeys.imageWidget), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), findsOneWidget); expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget); }); }); }