import 'package:eatvio_app/core/models/pagination_model.dart'; import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart'; import 'package:eatvio_app/features/feed/repositories/feed_repository.dart'; import 'package:eatvio_app/features/plans/repositories/plan_repository.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'plans_cubit_test.mocks.dart'; @GenerateNiceMocks([MockSpec(), MockSpec()]) void main() { group('PlansCubit', () { PlansCubit? plansCubit; late MockFeedRepository mockFeedRepository; late MockPlanRepository mockPlanRepository; const testPlan = PlanModel( id: 1, slug: 'test-plan', name: 'Test Plan', image: 'https://someurl.com/img.jpg', duration: 30, state: 'active', type: PlanType(fit: true, slim: false, behavior: false, wellness: false), details: 'Test plan description', packetsCount: 1, author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), totalLikes: 1, totalViews: 1, totalComments: 1, isFavorite: false, minPriceOfOptions: 100.0, maxPriceOfOptions: 500.0, wasLikedByMe: false, ); const testPlansPagination = PlanPaginationModel( data: [testPlan], links: Links(first: '', last: '', prev: null, next: null), meta: Meta( currentPage: 1, lastPage: 1, total: 1, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null, totalMinPrice: 100, totalMaxPrice: 500, ), ); setUp(() { mockFeedRepository = MockFeedRepository(); mockPlanRepository = MockPlanRepository(); }); tearDown(() async { if (plansCubit != null && !plansCubit!.isClosed) { await Future.delayed(const Duration(milliseconds: 100)); plansCubit!.close(); plansCubit = null; } }); test('начальное состояние - initial state', () { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); expect(plansCubit!.state.plans, isEmpty); expect(plansCubit!.state.isLoading, true); expect(plansCubit!.state.errorMessage, null); expect(plansCubit!.state.filterState.durationIndex, 0); expect(plansCubit!.state.filterState.typeIndex, 0); }); test('loadPlans - загружает планы успешно', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); when(mockFeedRepository.getPlans(query: null, types: null, duration: null, minPrice: null, maxPrice: null)).thenAnswer((_) async => testPlansPagination); await plansCubit!.loadPlans(); await Future.delayed(const Duration(milliseconds: 100)); expect(plansCubit!.state.plans.length, 1); expect(plansCubit!.state.plans.first.name, 'Test Plan'); expect(plansCubit!.state.errorMessage, null); }); test('loadPlans - обрабатывает ошибку', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); when(mockFeedRepository.getPlans(query: null, types: null, duration: null, minPrice: null, maxPrice: null)).thenThrow(Exception('Network error')); await plansCubit!.loadPlans(); await Future.delayed(const Duration(milliseconds: 100)); expect(plansCubit!.state.errorMessage, isNotNull); }); test('changeTypeFilter - меняет фильтр типа', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); plansCubit!.changeTypeFilter(1); await Future.delayed(const Duration(milliseconds: 100)); expect(plansCubit!.state.filterState.typeIndex, 1); }); test('changeDurationFilter - меняет фильтр длительности', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); plansCubit!.changeDurationFilter(1); await Future.delayed(const Duration(milliseconds: 100)); expect(plansCubit!.state.filterState.durationIndex, 1); }); test('changePriceFilter - меняет фильтр цены', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); plansCubit!.changePriceFilter(100, 500, disableDebounce: true); await Future.delayed(const Duration(milliseconds: 100)); expect(plansCubit!.state.filterState.priceFilter.$1, 100); expect(plansCubit!.state.filterState.priceFilter.$2, 500); }); test('likePlan - лайкает план', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); when(mockFeedRepository.getPlans(query: null, types: null, duration: null, minPrice: null, maxPrice: null)).thenAnswer((_) async => testPlansPagination); await plansCubit!.loadPlans(); await Future.delayed(const Duration(milliseconds: 100)); when(mockPlanRepository.likePlan('test-plan')).thenAnswer((_) async => Future.value()); plansCubit!.likePlan('test-plan', 0); await Future.delayed(const Duration(milliseconds: 300)); expect(plansCubit!.state.plans[0].wasLikedByMe, true); expect(plansCubit!.state.plans[0].totalLikes, 2); }); test('addPlanToFavorite - добавляет план в избранное', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); when(mockFeedRepository.getPlans(query: null, types: null, duration: null, minPrice: null, maxPrice: null)).thenAnswer((_) async => testPlansPagination); await plansCubit!.loadPlans(); await Future.delayed(const Duration(milliseconds: 100)); when(mockPlanRepository.addToFavorite('test-plan')).thenAnswer((_) async => Future.value()); plansCubit!.addPlanToFavorite('test-plan', 0); await Future.delayed(const Duration(milliseconds: 300)); expect(plansCubit!.state.plans[0].isFavorite, true); }); test('removePlanFromFavorite - удаляет план из избранного', () async { plansCubit = PlansCubit(feedRepository: mockFeedRepository, planRepository: mockPlanRepository); when( mockFeedRepository.getPlans(query: null, types: null, duration: null, minPrice: null, maxPrice: null), ).thenAnswer((_) async => testPlansPagination.copyWith(data: [testPlan.copyWith(isFavorite: true)])); await plansCubit!.loadPlans(); await Future.delayed(const Duration(milliseconds: 100)); when(mockPlanRepository.removeFromFavorite('test-plan')).thenAnswer((_) async => Future.value()); plansCubit!.removePlanFromFavorite('test-plan', 0); await Future.delayed(const Duration(milliseconds: 300)); expect(plansCubit!.state.plans[0].isFavorite, false); }); }); }