import 'package:eatvio_app/core/models/pagination_model.dart'; import 'package:eatvio_app/features/feed/models/comment_model.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart'; import 'package:eatvio_app/features/feed/models/feed_blog_post_settings_model.dart'; import 'package:eatvio_app/features/feed/models/feed_consultant_model.dart'; import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart'; import 'package:eatvio_app/features/feed/models/recipes_model.dart'; import 'package:eatvio_app/features/feed/models/recipes_pagination_model.dart'; import 'package:eatvio_app/features/feed/models/view_model.dart'; import 'package:eatvio_app/features/feed/services/feed_service.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'feed_service_test.mocks.dart'; @GenerateNiceMocks([MockSpec()]) void main() { group('FeedService', () { late MockFeedService mockFeedService; setUp(() { mockFeedService = MockFeedService(); }); test('getBlogPostList returns settings', () async { const page = 1; final expected = FeedBlogPostSettingsModel( feedBlogPostList: [ FeedBlogPostModel( id: 1, title: 'Post Title', description: 'Test post description', image: 'https://someurl.com/img.jpg', state: 'published', author: const Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), videoUrl: 'https://someurl.com/video.mp4', createdAt: DateTime.now(), updatedAt: DateTime.now(), totalLikes: 5, totalViews: 10, totalComments: 2, wasLikedByMe: false, ), ], meta: const Meta(currentPage: 1, lastPage: 1, total: 1, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getBlogPostList(page: page, query: null)).thenAnswer((_) async => expected); final result = await mockFeedService.getBlogPostList(page: page, query: null); expect(result, isA()); verify(mockFeedService.getBlogPostList(page: page, query: null)).called(1); }); test('getBlogPost returns post', () async { const id = 10; final expected = FeedBlogPostModel( id: id, title: 'Test', description: 'Test post description', image: 'https://someurl.com/img.jpg', state: 'published', author: const Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), videoUrl: 'https://someurl.com/video.mp4', createdAt: DateTime.now(), updatedAt: DateTime.now(), totalLikes: 3, totalViews: 14, totalComments: 1, wasLikedByMe: false, ); when(mockFeedService.getBlogPost(postId: id)).thenAnswer((_) async => expected); final result = await mockFeedService.getBlogPost(postId: id); expect(result.id, id); verify(mockFeedService.getBlogPost(postId: id)).called(1); }); test('getRecipes returns recipes pagination', () async { final expected = RecipesPagination( recipesList: [ Recipe( id: 1, image: 'https://someurl.com/img.jpg', state: 'published', cookingTime: 30, activeCookingTime: 20, ingredients: [const Ingredient(name: 'ingredient1', unit: 'unit1', portion: 'portion1', productId: 1)], description: 'Test post description', steps: [const Step(description: 'step1', image: 'https://someurl.com/img.jpg')], videoUrl: 'https://someurl.com/video.mp4', createdAt: DateTime.now(), updatedAt: DateTime.now(), title: 'Test', type: 'recipe', slug: 'test-recipe', commentsCount: 1, wasLikedByMe: false, isFavorite: false, calories: 100, servings: 1, likesCount: 3, viewsCount: 14, tags: [const Tag(name: '1')], author: const Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), ), ], ); when(mockFeedService.getRecipes(page: 1, tags: [1], query: null)).thenAnswer((_) async => expected); await mockFeedService.getRecipes(page: 1, tags: [1], query: null); verify(mockFeedService.getRecipes(page: 1, tags: [1], query: null)).called(1); }); test('getDiets returns pagination', () async { const expected = DietsPagination( data: [ Diet( id: 1, slug: 'test-diet', name: 'Test Diet', image: 'https://someurl.com/img.jpg', duration: 30, state: DietState.active, type: DietType(light: false, veg: false, carb: false, meat: false), details: 'Test diet description', dailySchedule: {}, author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), totalLikes: 1, totalViews: 1, totalComments: 1, wasLikedByMe: false, isFavorite: false, dailyNutrition: [], ), ], links: Links(first: '', last: '', prev: null, next: null), meta: Meta(currentPage: 1, lastPage: 1, total: 0, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getDiets(page: 1, query: null)).thenAnswer((_) async => expected); await mockFeedService.getDiets(page: 1, query: null); verify(mockFeedService.getDiets(page: 1, query: null)).called(1); }); test('getPlans returns pagination', () async { const expected = PlanPaginationModel( data: [ PlanModel( id: 1, slug: 'test-plan', name: 'Test Plan', image: 'https://someurl.com/img.jpg', duration: 30, state: 'active', type: PlanType(fit: false, slim: false, behavior: false, wellness: false), details: '', packetsCount: 1, author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false), totalLikes: 1, totalViews: 1, totalComments: 1, isFavorite: false, minPriceOfOptions: 100, maxPriceOfOptions: 500, wasLikedByMe: false, ), ], links: Links(first: '', last: '', prev: null, next: null), meta: Meta(currentPage: 1, lastPage: 1, total: 0, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getPlans(page: 1, query: null)).thenAnswer((_) async => expected); await mockFeedService.getPlans(page: 1, query: null); verify(mockFeedService.getPlans(page: 1, query: null)).called(1); }); test('getBlogPostComments returns comments', () async { const id = "1"; final expected = CommentModel( data: [ Comment( id: 1, authorName: 'user1', authorSlug: '', authorProfileIcon: '', body: 'Nice', childrenComments: [ Comment(id: 2, authorName: 'user2', authorSlug: '', authorProfileIcon: '', body: 'Great', childrenComments: [], createdAt: DateTime.now()), ], createdAt: DateTime.now(), ), ], links: const Links(first: '', last: '', prev: null, next: null), meta: const Meta(currentPage: 1, lastPage: 1, total: 1, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getBlogPostComments(id: id)).thenAnswer((_) async => expected); await mockFeedService.getBlogPostComments(id: id); verify(mockFeedService.getBlogPostComments(id: id)).called(1); }); test('sendBlogPostComment sends comment', () async { when(mockFeedService.sendBlogPostComment(id: "1", body: "Great", parentCommentId: null)).thenAnswer((_) async => Future.value()); await mockFeedService.sendBlogPostComment(id: "1", body: "Great", parentCommentId: null); verify(mockFeedService.sendBlogPostComment(id: "1", body: "Great", parentCommentId: null)).called(1); }); test('getDietsComments returns comments', () async { const id = "5"; final expected = CommentModel( data: [Comment(id: 2, authorName: 'user2', authorSlug: '', authorProfileIcon: '', body: 'Cool diet!', childrenComments: [], createdAt: DateTime.now())], links: const Links(first: '', last: '', prev: null, next: null), meta: const Meta(currentPage: 1, lastPage: 1, total: 1, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getDietsComments(id: id)).thenAnswer((_) async => expected); await mockFeedService.getDietsComments(id: id); verify(mockFeedService.getDietsComments(id: id)).called(1); }); test('sendDietsComment sends comment', () async { when(mockFeedService.sendDietsComment(id: "5", body: "Nice diet", parentCommentId: null)).thenAnswer((_) async => Future.value()); await mockFeedService.sendDietsComment(id: "5", body: "Nice diet", parentCommentId: null); verify(mockFeedService.sendDietsComment(id: "5", body: "Nice diet", parentCommentId: null)).called(1); }); test('getPlansComments returns comments', () async { const slug = "plan-1"; final expected = CommentModel( data: [ Comment(id: 3, authorName: 'user3', authorSlug: '', authorProfileIcon: '', body: 'Super plan!', childrenComments: [], createdAt: DateTime.now()), ], links: const Links(first: '', last: '', prev: null, next: null), meta: const Meta(currentPage: 1, lastPage: 1, total: 1, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getPlansComments(slug: slug)).thenAnswer((_) async => expected); await mockFeedService.getPlansComments(slug: slug); verify(mockFeedService.getPlansComments(slug: slug)).called(1); }); test('sendPlansComment sends comment', () async { when(mockFeedService.sendPlansComment(slug: "plan-1", body: "Ok", parentCommentId: null)).thenAnswer((_) async => Future.value()); await mockFeedService.sendPlansComment(slug: "plan-1", body: "Ok", parentCommentId: null); verify(mockFeedService.sendPlansComment(slug: "plan-1", body: "Ok", parentCommentId: null)).called(1); }); test('getRecipesComments returns comments', () async { const id = "33"; final expected = CommentModel( data: [ Comment(id: 4, authorName: 'user4', authorSlug: '', authorProfileIcon: '', body: 'Looks tasty!', childrenComments: [], createdAt: DateTime.now()), ], links: const Links(first: '', last: '', prev: null, next: null), meta: const Meta(currentPage: 1, lastPage: 1, total: 1, perPage: 10, from: null, links: [Link(url: null, label: null, active: null)], to: null), ); when(mockFeedService.getRecipesComments(id: id)).thenAnswer((_) async => expected); await mockFeedService.getRecipesComments(id: id); verify(mockFeedService.getRecipesComments(id: id)).called(1); }); test('sendRecipesComment sends comment', () async { when(mockFeedService.sendRecipesComment(id: "33", body: "Tasty", parentCommentId: null)).thenAnswer((_) async => Future.value()); await mockFeedService.sendRecipesComment(id: "33", body: "Tasty", parentCommentId: null); verify(mockFeedService.sendRecipesComment(id: "33", body: "Tasty", parentCommentId: null)).called(1); }); test('likeBlogPost works', () async { when(mockFeedService.likeBlogPost(id: 1)).thenAnswer((_) async => Future.value()); await mockFeedService.likeBlogPost(id: 1); verify(mockFeedService.likeBlogPost(id: 1)).called(1); }); test('unlikedBlogPost works', () async { when(mockFeedService.unlikedBlogPost(id: 1)).thenAnswer((_) async => Future.value()); await mockFeedService.unlikedBlogPost(id: 1); verify(mockFeedService.unlikedBlogPost(id: 1)).called(1); }); test('getConsultants returns consultant pagination', () async { const expected = FeedConsultantPaginationModel( data: [ FeedConsultantModel( slug: 'consultant-1', name: 'Anna Ivanova', description: 'Test consultant description', totalScores: 5, photo: 'https://someurl.com/consultant1.jpg', badges: [], ), ], 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), ); when(mockFeedService.getConsultants(name: 'Anna')).thenAnswer((_) async => expected); await mockFeedService.getConsultants(name: 'Anna'); verify(mockFeedService.getConsultants(name: 'Anna')).called(1); }); test('viewPost works', () async { when(mockFeedService.viewPost(id: 1)).thenAnswer((_) async => Future.value()); await mockFeedService.viewPost(id: 1); verify(mockFeedService.viewPost(id: 1)).called(1); }); test('viewRecipe works', () async { when(mockFeedService.viewRecipe(slug: 'abc')).thenAnswer((_) async => Future.value()); await mockFeedService.viewRecipe(slug: 'abc'); verify(mockFeedService.viewRecipe(slug: 'abc')).called(1); }); test('viewDiet works', () async { when(mockFeedService.viewDiet(id: 2)).thenAnswer((_) async => Future.value()); await mockFeedService.viewDiet(id: 2); verify(mockFeedService.viewDiet(id: 2)).called(1); }); test('viewPlan works', () async { when(mockFeedService.viewPlan(slug: 'plan-7')).thenAnswer((_) async => Future.value()); await mockFeedService.viewPlan(slug: 'plan-7'); verify(mockFeedService.viewPlan(slug: 'plan-7')).called(1); }); test('viewContent sends view model', () async { final view = ViewModel(type: 'recipe', slugs: ['recipe-1']); when(mockFeedService.viewContent(viewModel: view)).thenAnswer((_) async => Future.value()); await mockFeedService.viewContent(viewModel: view); verify(mockFeedService.viewContent(viewModel: view)).called(1); }); }); }