Files
eatvio_app/test/features/create_diet/basic_widget_test.dart

490 lines
19 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../fixtures/doubles/create_diet_doubles.dart';
import '../../fixtures/doubles/profile_doubles.dart';
void main() {
group('Diet Creation Basic Widget Tests', () {
late FixtureCreateDietRepository createDietRepository;
late FixtureProfileRepository profileRepository;
late FixtureGlossaryRepository glossaryRepository;
late CreateDietCubit createDietCubit;
setUp(() async {
// Initialize AppConfig for tests to enable compression bypass
await sl.reset();
dotenv.loadFromString(envString: 'DEV_BASE_URL=http://localhost\nBASE_URL=http://localhost');
sl.registerLazySingleton<AppConfig>(() => AppConfig(buildType: AppBuildType.tests)..setBaseUrl('http://localhost'));
createDietRepository = FixtureCreateDietRepository();
profileRepository = FixtureProfileRepository();
glossaryRepository = FixtureGlossaryRepository();
createDietCubit = CreateDietCubit(
createDietRepository: createDietRepository,
profileRepository: profileRepository,
glossaryRepository: glossaryRepository,
);
});
tearDown(() {
createDietCubit.close();
});
Widget createTestWidget(Widget child) {
return MaterialApp(
theme: ThemeHelper().themeData(),
home: BlocProvider<CreateDietCubit>(
create: (context) => createDietCubit,
child: Scaffold(body: SingleChildScrollView(child: child)),
),
);
}
testWidgets('should create CreateDietCubit successfully', (WidgetTester tester) async {
// Arrange & Act
final cubit = CreateDietCubit(
createDietRepository: createDietRepository,
profileRepository: profileRepository,
glossaryRepository: glossaryRepository,
);
// Assert
expect(cubit, isA<CreateDietCubit>());
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.isDietPublishing, isFalse);
cubit.close();
});
testWidgets('should display basic diet form fields', (WidgetTester tester) async {
// Arrange
Widget formWidget = Column(
children: [
TextFormField(
key: const Key('dietNameField'),
decoration: const InputDecoration(labelText: 'Название диеты', hintText: 'Например: Здоровая диета'),
),
const SizedBox(height: 16),
TextFormField(
key: const Key('dietDescriptionField'),
decoration: const InputDecoration(labelText: 'Описание диеты'),
maxLines: 3,
),
const SizedBox(height: 16),
DropdownButtonFormField<int>(
key: const Key('dietDurationField'),
decoration: const InputDecoration(labelText: 'Продолжительность'),
items: const [
DropdownMenuItem(value: 7, child: Text('7 дней')),
DropdownMenuItem(value: 14, child: Text('14 дней')),
DropdownMenuItem(value: 21, child: Text('21 день')),
],
onChanged: (value) {},
),
const SizedBox(height: 16),
ElevatedButton(key: const Key('publishDietButton'), onPressed: () {}, child: const Text('Опубликовать диету')),
],
);
// Act
await tester.pumpWidget(createTestWidget(formWidget));
await tester.pumpAndSettle();
// Assert
expect(find.byKey(const Key('dietNameField')), findsOneWidget);
expect(find.byKey(const Key('dietDescriptionField')), findsOneWidget);
expect(find.byKey(const Key('dietDurationField')), findsOneWidget);
expect(find.byKey(const Key('publishDietButton')), findsOneWidget);
});
testWidgets('should update diet name when user types in name field', (WidgetTester tester) async {
// Arrange
Widget formWidget = TextFormField(
key: const Key('dietNameField'),
decoration: const InputDecoration(labelText: 'Название диеты', hintText: 'Например: Здоровая диета'),
);
await tester.pumpWidget(createTestWidget(formWidget));
await tester.pumpAndSettle();
const testName = 'Тестовая диета';
// Act
await tester.enterText(find.byKey(const Key('dietNameField')), testName);
await tester.pump();
// Assert
expect(find.text(testName), findsOneWidget);
});
testWidgets('should update diet description when user types in description field', (WidgetTester tester) async {
// Arrange
Widget formWidget = TextFormField(
key: const Key('dietDescriptionField'),
decoration: const InputDecoration(labelText: 'Описание диеты'),
maxLines: 3,
);
await tester.pumpWidget(createTestWidget(formWidget));
await tester.pumpAndSettle();
const testDescription = 'Это тестовое описание диеты для похудения';
// Act
await tester.enterText(find.byKey(const Key('dietDescriptionField')), testDescription);
await tester.pump();
// Assert
expect(find.text(testDescription), findsOneWidget);
});
testWidgets('should display diet type selection', (WidgetTester tester) async {
// Arrange
Widget typeWidget = Column(
children: [
const Text('Тип диеты'),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: CheckboxListTile(key: const Key('veganTypeCheckbox'), title: const Text('Веганская'), value: false, onChanged: (value) {}),
),
Expanded(
child: CheckboxListTile(key: const Key('meatTypeCheckbox'), title: const Text('Мясная'), value: false, onChanged: (value) {}),
),
],
),
Row(
children: [
Expanded(
child: CheckboxListTile(key: const Key('carbTypeCheckbox'), title: const Text('Углеводная'), value: false, onChanged: (value) {}),
),
Expanded(
child: CheckboxListTile(key: const Key('lightTypeCheckbox'), title: const Text('Легкая'), value: false, onChanged: (value) {}),
),
],
),
],
);
// Act
await tester.pumpWidget(createTestWidget(typeWidget));
await tester.pumpAndSettle();
// Assert
expect(find.text('Тип диеты'), findsOneWidget);
expect(find.byKey(const Key('veganTypeCheckbox')), findsOneWidget);
expect(find.byKey(const Key('meatTypeCheckbox')), findsOneWidget);
expect(find.byKey(const Key('carbTypeCheckbox')), findsOneWidget);
expect(find.byKey(const Key('lightTypeCheckbox')), findsOneWidget);
});
testWidgets('should handle diet type selection', (WidgetTester tester) async {
// Arrange
bool veganSelected = false;
Widget typeWidget = CheckboxListTile(
key: const Key('veganTypeCheckbox'),
title: const Text('Веганская'),
value: veganSelected,
onChanged: (value) {
veganSelected = value ?? false;
},
);
await tester.pumpWidget(createTestWidget(typeWidget));
await tester.pumpAndSettle();
// Act
await tester.tap(find.byKey(const Key('veganTypeCheckbox')));
await tester.pump();
// Assert
expect(veganSelected, isTrue);
});
testWidgets('should display diet duration dropdown', (WidgetTester tester) async {
// Arrange
Widget durationWidget = DropdownButtonFormField<int>(
key: const Key('dietDurationField'),
decoration: const InputDecoration(labelText: 'Продолжительность диеты'),
items: const [
DropdownMenuItem(value: 7, child: Text('7 дней')),
DropdownMenuItem(value: 14, child: Text('14 дней')),
DropdownMenuItem(value: 21, child: Text('21 день')),
DropdownMenuItem(value: 30, child: Text('30 дней')),
],
onChanged: (value) {},
);
// Act
await tester.pumpWidget(createTestWidget(durationWidget));
await tester.pumpAndSettle();
// Assert
expect(find.byKey(const Key('dietDurationField')), findsOneWidget);
expect(find.text('Продолжительность диеты'), findsOneWidget);
});
testWidgets('should display diet status dropdown', (WidgetTester tester) async {
// Arrange
Widget statusWidget = DropdownButtonFormField<String>(
key: const Key('dietStatusField'),
decoration: const InputDecoration(labelText: 'Статус диеты'),
items: const [
DropdownMenuItem(value: 'active', child: Text('Активная')),
DropdownMenuItem(value: 'draft', child: Text('Черновик')),
DropdownMenuItem(value: 'personal', child: Text('Личная')),
],
onChanged: (value) {},
);
// Act
await tester.pumpWidget(createTestWidget(statusWidget));
await tester.pumpAndSettle();
// Assert
expect(find.byKey(const Key('dietStatusField')), findsOneWidget);
expect(find.text('Статус диеты'), findsOneWidget);
});
testWidgets('should display form labels correctly', (WidgetTester tester) async {
// Arrange
Widget formWidget = const Column(
children: [Text('Название диеты'), 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);
expect(find.text('Статус'), findsOneWidget);
});
testWidgets('should display placeholder text in name field', (WidgetTester tester) async {
// Arrange
Widget formWidget = TextFormField(
key: const Key('dietNameField'),
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 buttonWidget = ElevatedButton(key: const Key('publishDietButton'), onPressed: () {}, child: const Text('Опубликовать диету'));
// Act
await tester.pumpWidget(createTestWidget(buttonWidget));
await tester.pumpAndSettle();
// Assert
expect(find.byKey(const Key('publishDietButton')), findsOneWidget);
expect(find.text('Опубликовать диету'), findsOneWidget);
});
testWidgets('should handle publish button tap', (WidgetTester tester) async {
// Arrange
bool buttonPressed = false;
Widget buttonWidget = ElevatedButton(
key: const Key('publishDietButton'),
onPressed: () {
buttonPressed = true;
},
child: const Text('Опубликовать диету'),
);
await tester.pumpWidget(createTestWidget(buttonWidget));
await tester.pumpAndSettle();
// Act
await tester.tap(find.byKey(const Key('publishDietButton')));
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: const Key('dietNameField'),
decoration: const InputDecoration(labelText: 'Название диеты', errorText: 'Название диеты обязательно'),
),
const SizedBox(height: 16),
TextFormField(
key: const Key('dietDescriptionField'),
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 complete diet creation form', (WidgetTester tester) async {
// Arrange
Widget completeForm = Column(
children: [
TextFormField(
key: const Key('dietNameField'),
decoration: const InputDecoration(labelText: 'Название диеты', hintText: 'Например: Здоровая диета'),
),
const SizedBox(height: 16),
TextFormField(
key: const Key('dietDescriptionField'),
decoration: const InputDecoration(labelText: 'Описание диеты'),
maxLines: 3,
),
const SizedBox(height: 16),
DropdownButtonFormField<int>(
key: const Key('dietDurationField'),
decoration: const InputDecoration(labelText: 'Продолжительность'),
items: const [
DropdownMenuItem(value: 7, child: Text('7 дней')),
DropdownMenuItem(value: 14, child: Text('14 дней')),
DropdownMenuItem(value: 21, child: Text('21 день')),
],
onChanged: (value) {},
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
key: const Key('dietStatusField'),
decoration: const InputDecoration(labelText: 'Статус диеты'),
items: const [
DropdownMenuItem(value: 'active', child: Text('Активная')),
DropdownMenuItem(value: 'draft', child: Text('Черновик')),
],
onChanged: (value) {},
),
const SizedBox(height: 32),
ElevatedButton(key: const Key('publishDietButton'), onPressed: () {}, child: const Text('Опубликовать диету')),
],
);
// Act
await tester.pumpWidget(createTestWidget(completeForm));
await tester.pumpAndSettle();
// Assert
expect(find.byKey(const Key('dietNameField')), findsOneWidget);
expect(find.byKey(const Key('dietDescriptionField')), findsOneWidget);
expect(find.byKey(const Key('dietDurationField')), findsOneWidget);
expect(find.byKey(const Key('dietStatusField')), findsOneWidget);
expect(find.byKey(const Key('publishDietButton')), findsOneWidget);
});
testWidgets('should display diet type options', (WidgetTester tester) async {
// Arrange
Widget typeOptionsWidget = const Column(
children: [
Text('Выберите тип диеты:'),
SizedBox(height: 8),
Text('• Веганская - без продуктов животного происхождения'),
Text('• Мясная - с мясными продуктами'),
Text('• Углеводная - с высоким содержанием углеводов'),
Text('• Легкая - низкокалорийная диета'),
],
);
// Act
await tester.pumpWidget(createTestWidget(typeOptionsWidget));
await tester.pumpAndSettle();
// Assert
expect(find.text('Выберите тип диеты:'), findsOneWidget);
expect(find.text('• Веганская - без продуктов животного происхождения'), findsOneWidget);
expect(find.text('• Мясная - с мясными продуктами'), findsOneWidget);
expect(find.text('• Углеводная - с высоким содержанием углеводов'), findsOneWidget);
expect(find.text('• Легкая - низкокалорийная диета'), findsOneWidget);
});
testWidgets('should display diet duration options', (WidgetTester tester) async {
// Arrange
Widget durationOptionsWidget = const Column(
children: [
Text('Доступные продолжительности:'),
SizedBox(height: 8),
Text('• 7 дней - недельная диета'),
Text('• 14 дней - двухнедельная диета'),
Text('• 21 день - трехнедельная диета'),
Text('• 30 дней - месячная диета'),
],
);
// Act
await tester.pumpWidget(createTestWidget(durationOptionsWidget));
await tester.pumpAndSettle();
// Assert
expect(find.text('Доступные продолжительности:'), findsOneWidget);
expect(find.text('• 7 дней - недельная диета'), findsOneWidget);
expect(find.text('• 14 дней - двухнедельная диета'), findsOneWidget);
expect(find.text('• 21 день - трехнедельная диета'), findsOneWidget);
expect(find.text('• 30 дней - месячная диета'), findsOneWidget);
});
});
}