forked from eatvio/eatvio_app
361 lines
14 KiB
Dart
361 lines
14 KiB
Dart
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<CreateRecipeCubit>(
|
|
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<CreateRecipeCubit>());
|
|
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 = Column(children: const [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);
|
|
});
|
|
});
|
|
}
|