forked from eatvio/eatvio_app
chore(version): update app version to 1.3.5+85 and improve test coverage reporting in CI
This commit is contained in:
@@ -4,158 +4,169 @@ 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/repositories/feed_repository.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import 'blog_post_cubit_test.mocks.dart';
|
||||
class MockFeedRepository extends Mock implements FeedRepository {}
|
||||
|
||||
@GenerateNiceMocks([MockSpec<FeedRepository>()])
|
||||
void main() {
|
||||
group('BlogPostCubit', () {
|
||||
BlogPostCubit? blogPostCubit;
|
||||
late MockFeedRepository mockFeedRepository;
|
||||
late BlogPostCubit cubit;
|
||||
late MockFeedRepository mockRepository;
|
||||
|
||||
setUp(() {
|
||||
mockFeedRepository = MockFeedRepository();
|
||||
mockRepository = MockFeedRepository();
|
||||
cubit = BlogPostCubit(mockRepository);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
if (blogPostCubit != null && !blogPostCubit!.isClosed) {
|
||||
await blogPostCubit!.close();
|
||||
blogPostCubit = null;
|
||||
}
|
||||
tearDown(() {
|
||||
cubit.close();
|
||||
});
|
||||
|
||||
test('начальное состояние - пустое', () {
|
||||
blogPostCubit = BlogPostCubit(mockFeedRepository);
|
||||
|
||||
expect(blogPostCubit!.state, isA<BlogPostState>());
|
||||
expect(blogPostCubit!.state.isLoading, isFalse);
|
||||
expect(blogPostCubit!.state.blogPostModel, isNull);
|
||||
test('начальное состояние - BlogPostState с isLoading: false', () {
|
||||
expect(cubit.state, isA<BlogPostState>());
|
||||
expect(cubit.state.isLoading, false);
|
||||
});
|
||||
|
||||
test('getBlogPost - успешная загрузка поста', () async {
|
||||
blogPostCubit = BlogPostCubit(mockFeedRepository);
|
||||
|
||||
final testPost = FeedBlogPostModel(
|
||||
id: 1,
|
||||
state: 'published',
|
||||
image: 'https://example.com/image.jpg',
|
||||
description: 'Test description',
|
||||
author: const Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
const postId = 1;
|
||||
final mockPost = FeedBlogPostModel(
|
||||
id: postId,
|
||||
title: 'Test Post',
|
||||
state: 'active',
|
||||
image: '',
|
||||
description: 'Test Content',
|
||||
videoUrl: '',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
title: 'Test Post',
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
totalLikes: 0,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
wasLikedByMe: false,
|
||||
author: const Author(authorName: 'Test Author', authorSlug: 'test-author', authorProfileIcon: '', authorIsMe: false),
|
||||
);
|
||||
|
||||
when(mockFeedRepository.getBlogPost(id: 1))
|
||||
.thenAnswer((_) async => testPost);
|
||||
when(() => mockRepository.getBlogPost(id: postId)).thenAnswer((_) async => mockPost);
|
||||
|
||||
await blogPostCubit!.getBlogPost(1);
|
||||
await cubit.getBlogPost(postId);
|
||||
|
||||
expect(blogPostCubit!.state.blogPostModel, isNotNull);
|
||||
expect(blogPostCubit!.state.blogPostModel!.id, 1);
|
||||
expect(blogPostCubit!.state.isLoading, isFalse);
|
||||
expect(cubit.state.isLoading, false);
|
||||
expect(cubit.state.blogPostModel, mockPost);
|
||||
verify(() => mockRepository.getBlogPost(id: postId)).called(1);
|
||||
});
|
||||
|
||||
test('getBlogPost - обработка ошибки', () async {
|
||||
blogPostCubit = BlogPostCubit(mockFeedRepository);
|
||||
const postId = 1;
|
||||
|
||||
when(mockFeedRepository.getBlogPost(id: anyNamed('id')))
|
||||
.thenThrow(Exception('Ошибка загрузки'));
|
||||
when(() => mockRepository.getBlogPost(id: postId)).thenThrow(Exception('Error'));
|
||||
|
||||
await blogPostCubit!.getBlogPost(1);
|
||||
await cubit.getBlogPost(postId);
|
||||
|
||||
expect(blogPostCubit!.state.isLoading, isFalse);
|
||||
expect(cubit.state.isLoading, false);
|
||||
expect(cubit.state.blogPostModel, null);
|
||||
});
|
||||
|
||||
test('toggleLike - лайк поста', () async {
|
||||
blogPostCubit = BlogPostCubit(mockFeedRepository);
|
||||
|
||||
final testPost = FeedBlogPostModel(
|
||||
id: 1,
|
||||
state: 'published',
|
||||
image: 'https://example.com/image.jpg',
|
||||
description: 'Test description',
|
||||
author: const Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
const postId = 1;
|
||||
final mockPost = FeedBlogPostModel(
|
||||
id: postId,
|
||||
title: 'Test Post',
|
||||
state: 'active',
|
||||
image: '',
|
||||
description: 'Test Content',
|
||||
videoUrl: '',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
title: 'Test Post',
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
totalLikes: 5,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
wasLikedByMe: false,
|
||||
author: const Author(authorName: 'Test Author', authorSlug: 'test-author', authorProfileIcon: '', authorIsMe: false),
|
||||
);
|
||||
|
||||
when(mockFeedRepository.getBlogPost(id: 1))
|
||||
.thenAnswer((_) async => testPost);
|
||||
when(mockFeedRepository.likeBlogPost(id: 1))
|
||||
.thenAnswer((_) async => {});
|
||||
when(() => mockRepository.likeBlogPost(id: postId)).thenAnswer((_) async => {});
|
||||
|
||||
await blogPostCubit!.getBlogPost(1);
|
||||
await blogPostCubit!.toggleLike();
|
||||
// Сначала загружаем пост
|
||||
when(() => mockRepository.getBlogPost(id: postId)).thenAnswer((_) async => mockPost);
|
||||
await cubit.getBlogPost(postId);
|
||||
|
||||
expect(blogPostCubit!.state.blogPostModel!.wasLikedByMe, isTrue);
|
||||
expect(blogPostCubit!.state.blogPostModel!.totalLikes, 11);
|
||||
// Затем лайкаем
|
||||
await cubit.toggleLike();
|
||||
|
||||
expect(cubit.state.blogPostModel?.wasLikedByMe, true);
|
||||
expect(cubit.state.blogPostModel?.totalLikes, 6);
|
||||
verify(() => mockRepository.likeBlogPost(id: postId)).called(1);
|
||||
});
|
||||
|
||||
test('toggleLike - убирает лайк', () async {
|
||||
blogPostCubit = BlogPostCubit(mockFeedRepository);
|
||||
|
||||
final testPost = FeedBlogPostModel(
|
||||
id: 1,
|
||||
state: 'published',
|
||||
image: 'https://example.com/image.jpg',
|
||||
description: 'Test description',
|
||||
author: const Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
const postId = 1;
|
||||
final mockPost = FeedBlogPostModel(
|
||||
id: postId,
|
||||
title: 'Test Post',
|
||||
state: 'active',
|
||||
image: '',
|
||||
description: 'Test Content',
|
||||
videoUrl: '',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
title: 'Test Post',
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
totalLikes: 5,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
wasLikedByMe: true,
|
||||
author: const Author(authorName: 'Test Author', authorSlug: 'test-author', authorProfileIcon: '', authorIsMe: false),
|
||||
);
|
||||
|
||||
when(mockFeedRepository.getBlogPost(id: 1))
|
||||
.thenAnswer((_) async => testPost);
|
||||
when(mockFeedRepository.unlikedBlogPost(id: 1))
|
||||
.thenAnswer((_) async => {});
|
||||
when(() => mockRepository.unlikedBlogPost(id: postId)).thenAnswer((_) async => {});
|
||||
|
||||
await blogPostCubit!.getBlogPost(1);
|
||||
await blogPostCubit!.toggleLike();
|
||||
// Сначала загружаем пост
|
||||
when(() => mockRepository.getBlogPost(id: postId)).thenAnswer((_) async => mockPost);
|
||||
await cubit.getBlogPost(postId);
|
||||
|
||||
expect(blogPostCubit!.state.blogPostModel!.wasLikedByMe, isFalse);
|
||||
expect(blogPostCubit!.state.blogPostModel!.totalLikes, 9);
|
||||
// Затем убираем лайк
|
||||
await cubit.toggleLike();
|
||||
|
||||
expect(cubit.state.blogPostModel?.wasLikedByMe, false);
|
||||
expect(cubit.state.blogPostModel?.totalLikes, 4);
|
||||
verify(() => mockRepository.unlikedBlogPost(id: postId)).called(1);
|
||||
});
|
||||
|
||||
test('toggleLike - откат при ошибке', () async {
|
||||
const postId = 1;
|
||||
final mockPost = FeedBlogPostModel(
|
||||
id: postId,
|
||||
title: 'Test Post',
|
||||
state: 'active',
|
||||
image: '',
|
||||
description: 'Test Content',
|
||||
videoUrl: '',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
totalLikes: 5,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
wasLikedByMe: false,
|
||||
author: const Author(authorName: 'Test Author', authorSlug: 'test-author', authorProfileIcon: '', authorIsMe: false),
|
||||
);
|
||||
|
||||
when(() => mockRepository.likeBlogPost(id: postId)).thenThrow(Exception('Error'));
|
||||
|
||||
// Сначала загружаем пост
|
||||
when(() => mockRepository.getBlogPost(id: postId)).thenAnswer((_) async => mockPost);
|
||||
await cubit.getBlogPost(postId);
|
||||
|
||||
// Затем пытаемся лайкнуть (с ошибкой)
|
||||
await cubit.toggleLike();
|
||||
|
||||
// Должен откатиться к исходному состоянию
|
||||
expect(cubit.state.blogPostModel?.wasLikedByMe, false);
|
||||
expect(cubit.state.blogPostModel?.totalLikes, 5);
|
||||
});
|
||||
|
||||
test('toggleLike - ничего не делает если пост не загружен', () async {
|
||||
await cubit.toggleLike();
|
||||
|
||||
expect(cubit.state.blogPostModel, null);
|
||||
verifyNever(() => mockRepository.likeBlogPost(id: any(named: 'id')));
|
||||
verifyNever(() => mockRepository.unlikedBlogPost(id: any(named: 'id')));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user