test(tests): add whitespace to multiple test files for consistency and improved readability

This commit is contained in:
mso7nueh
2025-12-11 21:43:36 +03:00
parent c378c7fc16
commit 2408443a26
45 changed files with 1375 additions and 0 deletions

View File

@@ -134,3 +134,4 @@ void main() {

View File

@@ -69,3 +69,4 @@ void main() {

View File

@@ -83,3 +83,4 @@ void main() {

View File

@@ -32,3 +32,4 @@ void main() {

View File

@@ -28,3 +28,4 @@ void main() {

View File

@@ -25,3 +25,4 @@ void main() {

View File

@@ -29,3 +29,4 @@ void main() {

View File

@@ -108,3 +108,4 @@ void main() {

View File

@@ -32,3 +32,4 @@ void main() {

View File

@@ -26,3 +26,4 @@ void main() {

View File

@@ -62,3 +62,4 @@ void main() {

View File

@@ -114,3 +114,4 @@ void main() {

View File

@@ -51,3 +51,4 @@ void main() {

View File

@@ -133,3 +133,4 @@ void main() {

View File

@@ -94,3 +94,4 @@ void main() {

View File

@@ -162,3 +162,4 @@ void main() {

View File

@@ -55,3 +55,4 @@ void main() {

View File

@@ -40,3 +40,4 @@ void main() {

View File

@@ -94,3 +94,4 @@ void main() {

View File

@@ -74,3 +74,4 @@ void main() {

View File

@@ -63,3 +63,4 @@ void main() {

View File

@@ -0,0 +1,111 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_history_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
void main() {
group('RatingHistoryWidget', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child) {
return MaterialApp(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
home: Portal(
child: Scaffold(body: SingleChildScrollView(child: child)),
),
);
}
testWidgets('should display loader when isLoading is true', (WidgetTester tester) async {
// Arrange
const widget = RatingHistoryWidget(isLoading: true, ratingHistory: []);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(Loader), findsOneWidget);
});
testWidgets('should display rating history items when isLoading is false', (WidgetTester tester) async {
// Arrange
final ratingHistory = [
RatingModel(
type: RatingEnum.addedRecipe,
amount: 10,
date: DateTime(2024, 1, 1),
),
RatingModel(
type: RatingEnum.addedBlogPost,
amount: 5,
date: DateTime(2024, 1, 2),
),
];
final widget = RatingHistoryWidget(isLoading: false, ratingHistory: ratingHistory);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pumpAndSettle();
// Assert
expect(find.byType(Loader), findsNothing);
expect(find.byType(ListView), findsOneWidget);
});
testWidgets('should display empty list when ratingHistory is empty', (WidgetTester tester) async {
// Arrange
const widget = RatingHistoryWidget(isLoading: false, ratingHistory: []);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pumpAndSettle();
// Assert
expect(find.byType(Loader), findsNothing);
expect(find.byType(ListView), findsOneWidget);
});
testWidgets('should display all rating types correctly', (WidgetTester tester) async {
// Arrange
final ratingHistory = [
RatingModel(type: RatingEnum.addedRecipe, amount: 1, date: DateTime.now()),
RatingModel(type: RatingEnum.addedPublicDiet, amount: 2, date: DateTime.now()),
RatingModel(type: RatingEnum.addedBlogPost, amount: 3, date: DateTime.now()),
RatingModel(type: RatingEnum.invitedUser, amount: 4, date: DateTime.now()),
RatingModel(type: RatingEnum.hasMedicalDegree, amount: 5, date: DateTime.now()),
RatingModel(type: RatingEnum.consulted, amount: 6, date: DateTime.now()),
RatingModel(type: RatingEnum.addedGlossary, amount: 7, date: DateTime.now()),
];
final widget = RatingHistoryWidget(isLoading: false, ratingHistory: ratingHistory);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pumpAndSettle();
// Assert
expect(find.byType(ListView), findsOneWidget);
});
});
}

View File

@@ -0,0 +1,91 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/consultant_rating/models/statistics_model.dart';
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
void main() {
group('StatisticWidget', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child) {
return MaterialApp(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
home: Portal(
child: Scaffold(body: SingleChildScrollView(child: child)),
),
);
}
testWidgets('should display loader when isLoading is true', (WidgetTester tester) async {
// Arrange
const widget = StatisticWidget(isLoading: true, statistics: null);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(Loader), findsOneWidget);
});
testWidgets('should display statistics when isLoading is false and statistics provided', (WidgetTester tester) async {
// Arrange
final statistics = StatisticsModel(
countReferal: 10,
blogPostsCount: 5,
recipesCount: 3,
dietsCount: 2,
consultationsCount: 8,
qwe: 1,
);
final widget = StatisticWidget(isLoading: false, statistics: statistics);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pumpAndSettle();
// Assert
expect(find.byType(Loader), findsNothing);
expect(find.text('10'), findsOneWidget);
expect(find.text('5'), findsOneWidget);
expect(find.text('3'), findsOneWidget);
expect(find.text('2'), findsOneWidget);
expect(find.text('8'), findsOneWidget);
expect(find.text('1'), findsOneWidget);
});
testWidgets('should display zeros when statistics is null', (WidgetTester tester) async {
// Arrange
const widget = StatisticWidget(isLoading: false, statistics: null);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pumpAndSettle();
// Assert
expect(find.byType(Loader), findsNothing);
expect(find.text('0'), findsNWidgets(6));
});
});
}

View File

@@ -0,0 +1,395 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
import 'package:eatvio_app/features/consultations/services/consultation_service.dart';
import 'package:eatvio_app/features/finances_and_consultations_archive/models/consultant_finance_model.dart';
import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
import 'package:eatvio_app/features/finances_and_consultations_archive/models/user_purchases_model.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'consultation_service_test.mocks.dart';
@GenerateMocks([Dio])
void main() {
group('ConsultationService', () {
late ConsultationService service;
late MockDio mockDio;
setUp(() {
mockDio = MockDio();
service = ConsultationService(mockDio);
});
test('getConsultations - успешное получение консультаций', () async {
final mockData = {
'data': [],
'links': {},
'meta': {
'current_page': 1,
'last_page': 1,
'total': 0,
'per_page': 10,
},
};
when(mockDio.get(
'/api/consultations',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/consultations'),
statusCode: 200,
data: mockData,
));
final result = await service.getConsultations();
expect(result, isA<ConsultationPaginationModel>());
verify(mockDio.get(
'/api/consultations',
queryParameters: {
'filters[last_state][\$notIn][]': const [
'initied',
'in_coordination',
'start_date_has_been_set',
'pending_payment',
'canceled_by_the_initiator',
'charge_was_collected',
],
'sort[]': 'created_at:desc'
},
)).called(1);
});
test('getConsultations - пробрасывает ошибку', () async {
when(mockDio.get(
any,
queryParameters: anyNamed('queryParameters'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/consultations'),
));
expect(() => service.getConsultations(), throwsA(isA<DioException>()));
});
test('getFilteredConsultations - успешное получение с фильтрами notInArray', () async {
final mockData = {
'data': [],
'links': {},
'meta': {
'current_page': 1,
'last_page': 1,
'total': 0,
'per_page': 10,
},
};
when(mockDio.get(
'/api/consultations',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/consultations'),
statusCode: 200,
data: mockData,
));
final result = await service.getFilteredConsultations(
stateComparison: FiltersComparisonEnum.notInArray,
);
expect(result, isA<ConsultationPaginationModel>());
verify(mockDio.get(
'/api/consultations',
queryParameters: {
'filters[last_state][\$notIn][]': const [
'initied',
'in_coordination',
'start_date_has_been_set',
'pending_payment',
'canceled_by_the_initiator',
'charge_was_collected',
],
'sort[]': 'created_at:desc',
},
)).called(1);
});
test('getFilteredConsultations - успешное получение с фильтром state', () async {
final mockData = {
'data': [],
'links': {},
'meta': {
'current_page': 1,
'last_page': 1,
'total': 0,
'per_page': 10,
},
};
when(mockDio.get(
'/api/consultations',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/consultations'),
statusCode: 200,
data: mockData,
));
final result = await service.getFilteredConsultations(
state: 'done',
stateComparison: FiltersComparisonEnum.equal,
);
expect(result, isA<ConsultationPaginationModel>());
verify(mockDio.get(
'/api/consultations',
queryParameters: {
'filters[last_state][\$eq]': 'done',
'sort[]': 'created_at:desc',
},
)).called(1);
});
test('getFilteredConsultations - успешное получение с фильтром date', () async {
final mockData = {
'data': [],
'links': {},
'meta': {
'current_page': 1,
'last_page': 1,
'total': 0,
'per_page': 10,
},
};
when(mockDio.get(
'/api/consultations',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/consultations'),
statusCode: 200,
data: mockData,
));
final result = await service.getFilteredConsultations(
date: '2024-01-01',
dateComparison: FiltersComparisonEnum.greaterThan,
);
expect(result, isA<ConsultationPaginationModel>());
verify(mockDio.get(
'/api/consultations',
queryParameters: {
'filters[start_date][\$gt]': '2024-01-01',
'sort[]': 'created_at:desc',
},
)).called(1);
});
test('getFilteredConsultations - пробрасывает ошибку', () async {
when(mockDio.get(
any,
queryParameters: anyNamed('queryParameters'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/consultations'),
));
expect(
() => service.getFilteredConsultations(),
throwsA(isA<DioException>()),
);
});
test('getStatistics - успешное получение статистики', () async {
final mockData = {
'total': 10,
'in_progress': 5,
'finished': 3,
'canceled': 2,
};
when(mockDio.get('/api/consultations/statistics')).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/consultations/statistics'),
statusCode: 200,
data: mockData,
));
final result = await service.getStatistics();
expect(result, isA<StatisticModel>());
expect(result.total, 10);
expect(result.inProgress, 5);
expect(result.finished, 3);
expect(result.canceled, 2);
verify(mockDio.get('/api/consultations/statistics')).called(1);
});
test('getStatistics - пробрасывает ошибку', () async {
when(mockDio.get('/api/consultations/statistics')).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/consultations/statistics'),
));
expect(() => service.getStatistics(), throwsA(isA<DioException>()));
});
test('getConsultantFinances - успешное получение финансов', () async {
final mockData = {
'data': [
{
'start_date': '2024-01-01T00:00:00Z',
'bank_id': 'bank-1',
'title': 'Consultation',
'clientName': 'Client Name',
'duration': 60,
'payment_price': 100000,
'payment_status': 'COMPLETED',
}
],
};
when(mockDio.get(
'/api/finances/my_finances',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/finances/my_finances'),
statusCode: 200,
data: mockData,
));
final result = await service.getConsultantFinances(null, null);
expect(result, isA<List<ConsultantFinanceModel>>());
expect(result.length, 1);
verify(mockDio.get(
'/api/finances/my_finances',
queryParameters: {
'sort[]': 'start_date:desc',
},
)).called(1);
});
test('getConsultantFinances - успешное получение с фильтром date', () async {
final mockData = {
'data': [],
};
when(mockDio.get(
'/api/finances/my_finances',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/finances/my_finances'),
statusCode: 200,
data: mockData,
));
final result = await service.getConsultantFinances(
'2024-01-01',
FiltersComparisonEnum.equal,
);
expect(result, isA<List<ConsultantFinanceModel>>());
verify(mockDio.get(
'/api/finances/my_finances',
queryParameters: {
'filters[start_date][\$eq]': '2024-01-01',
'sort[]': 'start_date:desc',
},
)).called(1);
});
test('getConsultantFinances - пробрасывает ошибку', () async {
when(mockDio.get(
any,
queryParameters: anyNamed('queryParameters'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/finances/my_finances'),
));
expect(
() => service.getConsultantFinances(null, null),
throwsA(isA<DioException>()),
);
});
test('getUserPurchases - успешное получение покупок', () async {
final mockData = {
'data': [
{
'start_date': '2024-01-01T00:00:00Z',
'bank_id': 'bank-1',
'title': 'Plan Title',
'consultantName': 'Consultant Name',
'duration': 30,
'price': 1000,
'chosen_plan_last_state': 'paid',
}
],
};
when(mockDio.get(
'/api/finances/my_purchases',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/finances/my_purchases'),
statusCode: 200,
data: mockData,
));
final result = await service.getUserPurchases(null, null);
expect(result, isA<List<UserPurchasesModel>>());
expect(result.length, 1);
verify(mockDio.get(
'/api/finances/my_purchases',
queryParameters: {
'sort[]': 'start_date:desc',
},
)).called(1);
});
test('getUserPurchases - успешное получение с фильтром date', () async {
final mockData = {
'data': [],
};
when(mockDio.get(
'/api/finances/my_purchases',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/finances/my_purchases'),
statusCode: 200,
data: mockData,
));
final result = await service.getUserPurchases(
'2024-01-01',
FiltersComparisonEnum.greaterThan,
);
expect(result, isA<List<UserPurchasesModel>>());
verify(mockDio.get(
'/api/finances/my_purchases',
queryParameters: {
'filters[start_date][\$gt]': '2024-01-01',
'sort[]': 'start_date:desc',
},
)).called(1);
});
test('getUserPurchases - пробрасывает ошибку', () async {
when(mockDio.get(
any,
queryParameters: anyNamed('queryParameters'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/finances/my_purchases'),
));
expect(
() => service.getUserPurchases(null, null),
throwsA(isA<DioException>()),
);
});
});
}

View File

@@ -69,3 +69,4 @@ void main() {

View File

@@ -56,3 +56,4 @@ void main() {

View File

@@ -88,3 +88,4 @@ void main() {

View File

@@ -0,0 +1,98 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/cancel_diet_bottom_sheet.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'cancel_diet_bottom_sheet_test.mocks.dart';
@GenerateNiceMocks([MockSpec<AboutDietCubit>()])
void main() {
group('CancelDietBottomSheet', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child, AboutDietCubit cubit) {
return MaterialApp(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
home: Portal(
child: BlocProvider<AboutDietCubit>(
create: (_) => cubit,
child: Scaffold(body: child),
),
),
);
}
testWidgets('should display cancel diet bottom sheet with default title', (WidgetTester tester) async {
// Arrange
final mockCubit = MockAboutDietCubit();
final widget = CancelDietBottomSheet(
aboutDietCubit: mockCubit,
);
// Act
await tester.pumpWidget(createTestWidget(widget, mockCubit));
await tester.pump();
// Assert
expect(find.byType(CancelDietBottomSheet), findsOneWidget);
expect(find.byType(CustomOutlinedButton), findsOneWidget);
});
testWidgets('should display cancel diet bottom sheet with custom title', (WidgetTester tester) async {
// Arrange
final mockCubit = MockAboutDietCubit();
final widget = CancelDietBottomSheet(
aboutDietCubit: mockCubit,
title: 'Custom title',
);
// Act
await tester.pumpWidget(createTestWidget(widget, mockCubit));
await tester.pump();
// Assert
expect(find.byType(CancelDietBottomSheet), findsOneWidget);
expect(find.text('Custom title'), findsOneWidget);
});
testWidgets('should display cancel diet bottom sheet with diet name', (WidgetTester tester) async {
// Arrange
final mockCubit = MockAboutDietCubit();
final widget = CancelDietBottomSheet(
aboutDietCubit: mockCubit,
dietName: 'Test Diet',
);
// Act
await tester.pumpWidget(createTestWidget(widget, mockCubit));
await tester.pump();
// Assert
expect(find.byType(CancelDietBottomSheet), findsOneWidget);
});
});
}

View File

@@ -106,3 +106,4 @@ void main() {

View File

@@ -0,0 +1,65 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/start_diet_bottom_sheet.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'start_diet_bottom_sheet_test.mocks.dart';
@GenerateNiceMocks([MockSpec<AboutDietCubit>()])
void main() {
group('StartDietBottomSheet', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child, AboutDietCubit cubit) {
return MaterialApp(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
home: Portal(
child: BlocProvider<AboutDietCubit>(
create: (_) => cubit,
child: Scaffold(body: child),
),
),
);
}
testWidgets('should display start diet bottom sheet', (WidgetTester tester) async {
// Arrange
final mockCubit = MockAboutDietCubit();
final widget = StartDietBottomSheet(
aboutDietCubit: mockCubit,
);
// Act
await tester.pumpWidget(createTestWidget(widget, mockCubit));
await tester.pump();
// Assert
expect(find.byType(StartDietBottomSheet), findsOneWidget);
expect(find.byType(CustomOutlinedButton), findsOneWidget);
});
});
}

View File

@@ -136,3 +136,4 @@ void main() {

View File

@@ -48,3 +48,4 @@ void main() {

View File

@@ -49,3 +49,4 @@ void main() {

View File

@@ -174,3 +174,4 @@ void main() {

View File

@@ -0,0 +1,132 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/features/order_info/presentation/widgets/collect_charge_banner.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart' show PlanModel, PlanType;
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart' show Author;
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:go_router/go_router.dart';
void main() {
group('CollectChargeBanner', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child) {
return MaterialApp.router(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
routerConfig: GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => Portal(
child: Scaffold(body: SingleChildScrollView(child: child)),
),
),
],
),
);
}
testWidgets('should display collect charge banner with plan name and price', (WidgetTester tester) async {
// Arrange
final chosenPlan = ChosenPlanModel(
id: 1,
optionType: 'standard',
startDate: DateTime.now(),
chosenPlanState: ChosenPlanStateEnum.stateDone,
chatId: 'chat-1',
consultantId: 1,
plan: const PlanModel(
id: 1,
slug: 'test-plan',
name: 'Test Plan',
image: 'test.jpg',
duration: 30,
state: 'active',
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
details: 'Test details',
packetsCount: 1,
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
minPriceOfOptions: 100.0,
maxPriceOfOptions: 500.0,
wasLikedByMe: false,
),
);
const price = 1000.0;
final widget = CollectChargeBanner(chosenPlan: chosenPlan, price: price);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(CollectChargeBanner), findsOneWidget);
expect(find.byType(CustomOutlinedButton), findsOneWidget);
});
testWidgets('should have button that navigates to card settings', (WidgetTester tester) async {
// Arrange
final chosenPlan = ChosenPlanModel(
id: 1,
optionType: 'standard',
startDate: DateTime.now(),
chosenPlanState: ChosenPlanStateEnum.stateDone,
chatId: 'chat-1',
consultantId: 1,
plan: const PlanModel(
id: 1,
slug: 'test-plan',
name: 'Test Plan',
image: 'test.jpg',
duration: 30,
state: 'active',
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
details: 'Test details',
packetsCount: 1,
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
minPriceOfOptions: 100.0,
maxPriceOfOptions: 500.0,
wasLikedByMe: false,
),
);
const price = 1000.0;
final widget = CollectChargeBanner(chosenPlan: chosenPlan, price: price);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert - проверяем, что кнопка существует
expect(find.byType(CustomOutlinedButton), findsOneWidget);
});
});
}

View File

@@ -0,0 +1,84 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/order_info/cubit/order_info_cubit.dart';
import 'package:eatvio_app/features/order_info/presentation/widgets/payment_banner.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:go_router/go_router.dart';
import 'payment_banner_test.mocks.dart';
@GenerateNiceMocks([MockSpec<OrderInfoCubit>()])
void main() {
group('PaymentBanner', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child, OrderInfoCubit cubit) {
return MaterialApp.router(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
routerConfig: GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => Portal(
child: BlocProvider<OrderInfoCubit>(
create: (_) => cubit,
child: Scaffold(body: SingleChildScrollView(child: child)),
),
),
),
],
),
);
}
testWidgets('should display payment banner with successful payment', (WidgetTester tester) async {
// Arrange
final mockCubit = MockOrderInfoCubit();
const widget = PaymentBanner(successfulPayment: true);
// Act
await tester.pumpWidget(createTestWidget(widget, mockCubit));
await tester.pump();
// Assert
expect(find.byType(PaymentBanner), findsOneWidget);
});
testWidgets('should display payment banner with failed payment', (WidgetTester tester) async {
// Arrange
final mockCubit = MockOrderInfoCubit();
const widget = PaymentBanner(successfulPayment: false);
// Act
await tester.pumpWidget(createTestWidget(widget, mockCubit));
await tester.pump();
// Assert
expect(find.byType(PaymentBanner), findsOneWidget);
});
});
}

View File

@@ -0,0 +1,99 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/order_info/presentation/widgets/plan_props.dart';
import 'package:eatvio_app/features/order_info/presentation/widgets/plan_status_box.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
void main() {
group('PlanProps', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child) {
return MaterialApp(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
home: Portal(
child: Scaffold(body: SingleChildScrollView(child: child)),
),
);
}
testWidgets('should display plan props with all information', (WidgetTester tester) async {
// Arrange
const planDuration = 30;
const planPrice = 1000.0;
const planStatus = PlanStatusValues.paid;
const widget = PlanProps(
planDuration: planDuration,
planPrice: planPrice,
planStatus: planStatus,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanProps), findsOneWidget);
expect(find.byType(PlanStatusBox), findsOneWidget);
});
testWidgets('should display plan props with pending payment status', (WidgetTester tester) async {
// Arrange
const planDuration = 15;
const planPrice = 500.0;
const planStatus = PlanStatusValues.pendingPayment;
const widget = PlanProps(
planDuration: planDuration,
planPrice: planPrice,
planStatus: planStatus,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanProps), findsOneWidget);
expect(find.byType(PlanStatusBox), findsOneWidget);
});
testWidgets('should display plan props with payment failed status', (WidgetTester tester) async {
// Arrange
const planDuration = 7;
const planPrice = 200.0;
const planStatus = PlanStatusValues.paymentFailed;
const widget = PlanProps(
planDuration: planDuration,
planPrice: planPrice,
planStatus: planStatus,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanProps), findsOneWidget);
expect(find.byType(PlanStatusBox), findsOneWidget);
});
});
}

View File

@@ -0,0 +1,114 @@
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/order_info/presentation/widgets/plan_state.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
void main() {
group('PlanState', () {
setUp(() async {
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'));
});
Widget createTestWidget(Widget child) {
return MaterialApp(
theme: ThemeHelper().themeData(),
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ru')],
home: Portal(
child: Scaffold(body: SingleChildScrollView(child: child)),
),
);
}
testWidgets('should display plan state without personal diet', (WidgetTester tester) async {
// Arrange
const widget = PlanState(
state: ChosenPlanStateEnum.statePaid,
hasPersonalDiet: false,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanState), findsOneWidget);
});
testWidgets('should display plan state with personal diet', (WidgetTester tester) async {
// Arrange
const widget = PlanState(
state: ChosenPlanStateEnum.statePaid,
hasPersonalDiet: true,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanState), findsOneWidget);
});
testWidgets('should display different states correctly', (WidgetTester tester) async {
// Arrange
const widget = PlanState(
state: ChosenPlanStateEnum.stateInProgress,
hasPersonalDiet: false,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanState), findsOneWidget);
});
testWidgets('should display done state', (WidgetTester tester) async {
// Arrange
const widget = PlanState(
state: ChosenPlanStateEnum.stateDone,
hasPersonalDiet: false,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanState), findsOneWidget);
});
testWidgets('should display state with personal diet set', (WidgetTester tester) async {
// Arrange
const widget = PlanState(
state: ChosenPlanStateEnum.personalDietSet,
hasPersonalDiet: true,
);
// Act
await tester.pumpWidget(createTestWidget(widget));
await tester.pump();
// Assert
expect(find.byType(PlanState), findsOneWidget);
});
});
}

View File

@@ -0,0 +1,151 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
import 'package:eatvio_app/features/personal_diet_suggestion/services/personal_diet_suggestion_service.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'personal_diet_suggestion_service_test.mocks.dart';
@GenerateMocks([Dio])
void main() {
group('PersonalDietSuggestionService', () {
late PersonalDietSuggestionService service;
late MockDio mockDio;
setUp(() {
mockDio = MockDio();
service = PersonalDietSuggestionService(mockDio);
});
test('getConsultationWithPersonalDiets - успешное получение консультаций', () async {
final mockData = {
'data': [],
'links': {},
'meta': {
'current_page': 1,
'last_page': 1,
'total': 0,
'per_page': 10,
},
};
when(mockDio.get(
'/api/consultations',
queryParameters: anyNamed('queryParameters'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/consultations'),
statusCode: 200,
data: mockData,
));
final result = await service.getConsultationWithPersonalDiets();
expect(result, isA<ConsultationPaginationModel>());
verify(mockDio.get(
'/api/consultations',
queryParameters: {
'filters[plan][has_personal_diet][\$personal_diet]': '1',
'filters[last_state][\$notIn][]': [
'done',
'charge_was_collected',
'complained',
'last_day_finished',
'canceled_by_the_initiator',
'inited'
],
'sort[]': 'start_date:desc',
},
)).called(1);
});
test('getConsultationWithPersonalDiets - пробрасывает ошибку', () async {
when(mockDio.get(
any,
queryParameters: anyNamed('queryParameters'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/consultations'),
));
expect(
() => service.getConsultationWithPersonalDiets(),
throwsA(isA<DioException>()),
);
});
test('attachPersonalDiet - успешное прикрепление диеты', () async {
const consultationId = 1;
const dietId = 2;
when(mockDio.post(
'/api/chosen_plans/$consultationId/attach_diet',
data: anyNamed('data'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/chosen_plans/$consultationId/attach_diet'),
statusCode: 200,
));
await service.attachPersonalDiet(consultationId: consultationId, dietId: dietId);
verify(mockDio.post(
'/api/chosen_plans/$consultationId/attach_diet',
data: {'diet_id': dietId},
)).called(1);
});
test('attachPersonalDiet - пробрасывает ошибку', () async {
const consultationId = 1;
const dietId = 2;
when(mockDio.post(
any,
data: anyNamed('data'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/chosen_plans/$consultationId/attach_diet'),
));
expect(
() => service.attachPersonalDiet(consultationId: consultationId, dietId: dietId),
throwsA(isA<DioException>()),
);
});
test('reattachPersonalDiet - успешное повторное прикрепление диеты', () async {
const consultationId = 1;
const dietId = 3;
when(mockDio.post(
'/api/chosen_plans/$consultationId/re_attach_diet',
data: anyNamed('data'),
)).thenAnswer((_) async => Response(
requestOptions: RequestOptions(path: '/api/chosen_plans/$consultationId/re_attach_diet'),
statusCode: 200,
));
await service.reattachPersonalDiet(consultationId: consultationId, dietId: dietId);
verify(mockDio.post(
'/api/chosen_plans/$consultationId/re_attach_diet',
data: {'diet_id': dietId},
)).called(1);
});
test('reattachPersonalDiet - пробрасывает ошибку', () async {
const consultationId = 1;
const dietId = 3;
when(mockDio.post(
any,
data: anyNamed('data'),
)).thenThrow(DioException(
requestOptions: RequestOptions(path: '/api/chosen_plans/$consultationId/re_attach_diet'),
));
expect(
() => service.reattachPersonalDiet(consultationId: consultationId, dietId: dietId),
throwsA(isA<DioException>()),
);
});
});
}