feat(tests): tests coverage 67.2

This commit is contained in:
misha
2026-01-19 12:32:11 +03:00
parent 13ccf56df0
commit 44ede73ceb
20 changed files with 5084 additions and 409 deletions

View File

@@ -1,3 +1,4 @@
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_cubit.dart';
@@ -12,6 +13,8 @@ import 'about_recipe_cubit_test.mocks.dart';
@GenerateNiceMocks([MockSpec<AboutRecipeRepository>(), MockSpec<ProfileRepository>()])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('AboutRecipeCubit', () {
AboutRecipeCubit? aboutRecipeCubit;
late MockAboutRecipeRepository mockRecipeRepository;
@@ -23,6 +26,8 @@ void main() {
});
tearDown(() async {
EasyDebounce.cancel('like_recipe');
EasyDebounce.cancel('add_or_remove_diet_to_favorites');
if (aboutRecipeCubit != null && !aboutRecipeCubit!.isClosed) {
await aboutRecipeCubit!.close();
aboutRecipeCubit = null;
@@ -346,5 +351,430 @@ void main() {
await Future.delayed(const Duration(milliseconds: 1200));
verify(mockRecipeRepository.removeFromFavorite('1')).called(1);
});
test('getRecipe - с index параметром', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: false,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
await aboutRecipeCubit!.getRecipe('1', index: 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
verify(mockRecipeRepository.emitCommentsStateToFeed(any)).called(1);
});
test('initRecipe - с index параметром', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: false,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
await aboutRecipeCubit!.initRecipe('1', index: 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
verify(mockRecipeRepository.emitCommentsStateToFeed(any)).called(1);
});
test('likeRecipe - с recipeIndexInFeed параметром', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: false,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
when(mockRecipeRepository.likeRecipe('1')).thenAnswer((_) async => {});
await aboutRecipeCubit!.getRecipe('1');
await aboutRecipeCubit!.likeRecipe('1', 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
final loadedState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(loadedState.recipe.wasLikedByMe, isTrue);
verify(mockRecipeRepository.emitLikesStateToFeed(any)).called(1);
await Future.delayed(const Duration(milliseconds: 1200));
verify(mockRecipeRepository.likeRecipe('1')).called(1);
});
test('likeRecipe - обработка ошибки', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: false,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
when(mockRecipeRepository.likeRecipe('1')).thenThrow(Exception('Ошибка'));
await aboutRecipeCubit!.getRecipe('1');
await aboutRecipeCubit!.likeRecipe('1', 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
final loadedState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(loadedState.recipe.wasLikedByMe, isTrue);
await Future.delayed(const Duration(milliseconds: 1200));
// После ошибки состояние должно вернуться к исходному
final finalState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(finalState.recipe.wasLikedByMe, isFalse);
expect(finalState.recipe.likesCount, 10);
verify(mockRecipeRepository.emitLikesStateToFeed(any)).called(2); // Один раз при лайке, второй раз при ошибке
});
test('addToFavorite - с recipeIndex параметром', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: false,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
when(mockRecipeRepository.addToFavorite('1')).thenAnswer((_) async => {});
await aboutRecipeCubit!.getRecipe('1');
await aboutRecipeCubit!.addToFavorite('1', 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
final loadedState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(loadedState.recipe.isFavorite, true);
verify(mockRecipeRepository.emitFavoriteStateToFeed(any)).called(1);
await Future.delayed(const Duration(milliseconds: 1200));
verify(mockRecipeRepository.addToFavorite('1')).called(1);
});
test('addToFavorite - обработка ошибки', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: false,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
when(mockRecipeRepository.addToFavorite('1')).thenThrow(Exception('Ошибка'));
await aboutRecipeCubit!.getRecipe('1');
await aboutRecipeCubit!.addToFavorite('1', 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
final loadedState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(loadedState.recipe.isFavorite, true);
// Не ждем debounce, так как showErrorToast требует плагин
// Просто проверяем, что состояние изменилось сразу
verify(mockRecipeRepository.emitFavoriteStateToFeed(any)).called(1);
});
test('removeFromFavorite - с recipeIndex параметром', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: true,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
when(mockRecipeRepository.removeFromFavorite('1')).thenAnswer((_) async => {});
await aboutRecipeCubit!.getRecipe('1');
await aboutRecipeCubit!.removeFromFavorite('1', 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
final loadedState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(loadedState.recipe.isFavorite, false);
verify(mockRecipeRepository.emitFavoriteStateToFeed(any)).called(1);
await Future.delayed(const Duration(milliseconds: 1200));
verify(mockRecipeRepository.removeFromFavorite('1')).called(1);
});
test('removeFromFavorite - обработка ошибки', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
const testRecipe = Recipe(
id: 1,
image: 'https://example.com/image.jpg',
state: 'active',
cookingTime: 30,
activeCookingTime: 15,
ingredients: [],
description: 'Test description',
steps: [],
videoUrl: null,
createdAt: null,
updatedAt: null,
title: 'Test Recipe',
type: 'main',
slug: 'test-recipe',
commentsCount: 5,
wasLikedByMe: false,
isFavorite: true,
calories: 300.0,
servings: 4,
likesCount: 10,
viewsCount: 100,
tags: [],
author: Author(
authorSlug: 'author',
authorName: 'Author Name',
authorProfileIcon: 'https://example.com/icon.jpg',
authorIsMe: false,
isEntitySubscribedByMe: null,
authorPlaceInRating: null,
),
);
when(mockRecipeRepository.getRecipe('1')).thenAnswer((_) async => testRecipe);
when(mockRecipeRepository.removeFromFavorite('1')).thenThrow(Exception('Ошибка'));
await aboutRecipeCubit!.getRecipe('1');
await aboutRecipeCubit!.removeFromFavorite('1', 0);
expect(aboutRecipeCubit!.state, isA<AboutRecipeStateLoaded>());
final loadedState = aboutRecipeCubit!.state as AboutRecipeStateLoaded;
expect(loadedState.recipe.isFavorite, false);
// Не ждем debounce, так как showErrorToast требует плагин
// Просто проверяем, что состояние изменилось сразу
verify(mockRecipeRepository.emitFavoriteStateToFeed(any)).called(1);
});
test('likeRecipe - не выполняет действие если state не loaded', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
await aboutRecipeCubit!.likeRecipe('1', null);
expect(aboutRecipeCubit!.state, isA<AboutRecipeState>());
verifyNever(mockRecipeRepository.likeRecipe(any));
});
test('addToFavorite - не выполняет действие если state не loaded', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
await aboutRecipeCubit!.addToFavorite('1', null);
expect(aboutRecipeCubit!.state, isA<AboutRecipeState>());
verifyNever(mockRecipeRepository.addToFavorite(any));
});
test('removeFromFavorite - не выполняет действие если state не loaded', () async {
aboutRecipeCubit = AboutRecipeCubit(recipeRepository: mockRecipeRepository, profileRepository: mockProfileRepository);
await aboutRecipeCubit!.removeFromFavorite('1', null);
expect(aboutRecipeCubit!.state, isA<AboutRecipeState>());
verifyNever(mockRecipeRepository.removeFromFavorite(any));
});
});
}