feat(diary_test): Issue-755

This commit is contained in:
mso7nueh
2025-11-06 00:38:08 +03:00
parent bbc99ec9f4
commit 2a06a5476a
4 changed files with 2674 additions and 0 deletions

View File

@@ -0,0 +1,906 @@
import 'dart:io';
import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart';
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
import 'package:eatvio_app/features/diary/services/diary_service.dart';
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'diary_repository_test.mocks.dart';
@GenerateNiceMocks([MockSpec<DiaryService>()])
void main() {
group('DiaryRepository', () {
late DiaryRepository diaryRepository;
late MockDiaryService mockDiaryService;
setUp(() {
mockDiaryService = MockDiaryService();
diaryRepository = DiaryRepository(diaryService: mockDiaryService);
});
test('getDiaryIndexByDate - возвращает список дневников по дате', () async {
const date = '2024-01-15';
final expectedDiaryList = [
const DiaryDayModel(
id: 1,
date: date,
closed: 0,
comment: '',
typeOfDiary: TypeOfDiaryModel(
hasChosenDiet: false,
hasChosenPlan: false,
diaryState: null,
),
meals: [],
chosenPlanId: null,
dayOfChosenDiet: null,
diet: null,
),
];
when(mockDiaryService.getDiaryIndexByDate(date: date))
.thenAnswer((_) async => expectedDiaryList);
final result = await diaryRepository.getDiaryIndexByDate(date);
expect(result, isA<List<DiaryDayModel>>());
expect(result.length, 1);
verify(mockDiaryService.getDiaryIndexByDate(date: date)).called(1);
});
test('getDiaryByDate - возвращает дневник с обогащенными данными глоссария', () async {
const date = '2024-01-15';
final diaryList = [
const DiaryDayModel(
id: 1,
date: date,
closed: 0,
comment: '',
typeOfDiary: TypeOfDiaryModel(
hasChosenDiet: false,
hasChosenPlan: false,
diaryState: null,
),
meals: [
MealModel(
id: 1,
time: '12:00',
typeNumber: 1,
satiety: 0,
mood: 0,
portions: [
PortionModel(
id: 1,
productNutritionalValueId: 10,
productName: 'Яблоко',
quantity: 2,
portion: '100г',
fromDiet: false,
portionState: PortionState.eaten,
),
],
photos: [],
),
],
chosenPlanId: null,
dayOfChosenDiet: null,
diet: null,
),
];
const glossaryItem = GlossaryPaginationModel(
glossariesList: [
GlossaryModel(
id: 10,
name: 'Яблоко',
grInPortion: 100,
energyOn100Gr: 52.0,
proteinsOn100Gr: 0.3,
fatsOn100Gr: 0.2,
carbohydratesOn100Gr: 14.0,
energyOnPortion: 52.0,
proteinsOnPortion: 0.3,
fatsOnPortion: 0.2,
carbohydratesOnPortion: 14.0,
),
],
);
when(mockDiaryService.getDiaryIndexByDate(date: date))
.thenAnswer((_) async => diaryList);
when(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')))
.thenAnswer((_) async => glossaryItem);
final result = await diaryRepository.getDiaryByDate(date);
expect(result, isA<DiaryDayModel>());
expect(result.meals.first.portions.first.productCaloriesInfo, isNotNull);
expect(
result.meals.first.portions.first.productCaloriesInfo?.productName,
'Яблоко');
});
test('getDiaryByDate - возвращает дневник без глоссария если нет nutritionalValueId',
() async {
const date = '2024-01-15';
final diaryList = [
const DiaryDayModel(
id: 1,
date: date,
closed: 0,
comment: '',
typeOfDiary: TypeOfDiaryModel(
hasChosenDiet: false,
hasChosenPlan: false,
diaryState: null,
),
meals: [
MealModel(
id: 1,
time: '12:00',
typeNumber: 1,
satiety: 0,
mood: 0,
portions: [
PortionModel(
id: 1,
productNutritionalValueId: null,
productName: 'Яблоко',
quantity: 2,
portion: '100г',
fromDiet: false,
portionState: PortionState.eaten,
),
],
photos: [],
),
],
chosenPlanId: null,
dayOfChosenDiet: null,
diet: null,
),
];
when(mockDiaryService.getDiaryIndexByDate(date: date))
.thenAnswer((_) async => diaryList);
final result = await diaryRepository.getDiaryByDate(date);
expect(result, isA<DiaryDayModel>());
verifyNever(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')));
});
test('getDiaryDay - возвращает дневник по ID с обогащенными данными', () async {
const diaryId = 1;
const diaryWrapper = DiaryDayWrapperModel(
diary: DiaryDayModel(
id: diaryId,
date: '2024-01-15',
closed: 0,
comment: '',
typeOfDiary: TypeOfDiaryModel(
hasChosenDiet: false,
hasChosenPlan: false,
diaryState: null,
),
meals: [
MealModel(
id: 1,
time: '12:00',
typeNumber: 1,
satiety: 0,
mood: 0,
portions: [
PortionModel(
id: 1,
productNutritionalValueId: 10,
productName: 'Яблоко',
quantity: 2,
portion: '100г',
fromDiet: false,
portionState: PortionState.eaten,
),
],
photos: [],
),
],
chosenPlanId: null,
dayOfChosenDiet: null,
diet: null,
),
);
const glossaryItem = GlossaryPaginationModel(
glossariesList: [
GlossaryModel(
id: 10,
name: 'Яблоко',
grInPortion: 100,
energyOn100Gr: 52.0,
proteinsOn100Gr: 0.3,
fatsOn100Gr: 0.2,
carbohydratesOn100Gr: 14.0,
energyOnPortion: 52.0,
proteinsOnPortion: 0.3,
fatsOnPortion: 0.2,
carbohydratesOnPortion: 14.0,
),
],
);
when(mockDiaryService.getDiaryDay(diary: diaryId))
.thenAnswer((_) async => diaryWrapper);
when(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')))
.thenAnswer((_) async => glossaryItem);
final result = await diaryRepository.getDiaryDay(diaryId);
expect(result, isA<DiaryDayModel>());
expect(result.id, diaryId);
expect(result.meals.first.portions.first.productCaloriesInfo, isNotNull);
});
test('getNutritionData - возвращает данные о питании', () async {
const diaryId = 1;
const expectedNutrition = NutritionDataModel(
dailyNutritionIntake: NutritionModel(
energy: 2000.0,
proteins: 150.0,
fats: 80.0,
carbohydrates: 250.0,
),
dailyNutritionRecommendation: NutritionModel(
energy: 2200.0,
proteins: 160.0,
fats: 90.0,
carbohydrates: 270.0,
),
);
when(mockDiaryService.getNutrition(diary: diaryId))
.thenAnswer((_) async => expectedNutrition);
final result = await diaryRepository.getNutritionData(diaryId);
expect(result, isA<NutritionDataModel>());
expect(result.dailyNutritionIntake.energy, 2000.0);
verify(mockDiaryService.getNutrition(diary: diaryId)).called(1);
});
test('addPortionToMeal - добавляет порцию в прием пищи', () async {
const diaryId = 1;
const mealId = 2;
const productName = 'Яблоко';
const portion = '100г';
const quantity = 2;
const productNutritionalValueId = 10;
when(mockDiaryService.addProductToMeal(
diary: diaryId,
typeNo: mealId,
productName: productName,
portion: portion,
quantity: quantity,
productNutritionalValueId: productNutritionalValueId,
)).thenAnswer((_) async => Future.value());
await diaryRepository.addPortionToMeal(
diaryId: diaryId,
mealId: mealId,
productName: productName,
portion: portion,
quantity: quantity,
productNutritionalValueId: productNutritionalValueId,
);
verify(mockDiaryService.addProductToMeal(
diary: diaryId,
typeNo: mealId,
productName: productName,
portion: portion,
quantity: quantity,
productNutritionalValueId: productNutritionalValueId,
)).called(1);
});
test('updateProductInMeal - обновляет продукт в приеме пищи', () async {
const diaryId = 1;
const mealId = 2;
const portionId = 5;
const productName = 'Яблоко';
const portion = '150г';
const quantity = 3;
const productNutritionalValueId = 10;
when(mockDiaryService.updateProductInMeal(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
productInMeal: anyNamed('productInMeal'),
)).thenAnswer((_) async => Future.value());
await diaryRepository.updateProductInMeal(
diaryId: diaryId,
mealId: mealId,
portionId: portionId,
productName: productName,
portion: portion,
quantity: quantity,
productNutritionalValueId: productNutritionalValueId,
portionState: PortionState.eaten,
);
verify(mockDiaryService.updateProductInMeal(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
productInMeal: anyNamed('productInMeal'),
)).called(1);
});
test('markEaten - отмечает продукт как съеденный', () async {
const diaryId = 1;
const mealId = 2;
const portionId = 5;
when(mockDiaryService.markEaten(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).thenAnswer((_) async => Future.value());
await diaryRepository.markEaten(
diaryId: diaryId,
mealId: mealId,
portionId: portionId,
);
verify(mockDiaryService.markEaten(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).called(1);
});
test('unmarkEaten - снимает отметку о съеденном продукте', () async {
const diaryId = 1;
const mealId = 2;
const portionId = 5;
when(mockDiaryService.unmarkEaten(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).thenAnswer((_) async => Future.value());
await diaryRepository.unmarkEaten(
diaryId: diaryId,
mealId: mealId,
portionId: portionId,
);
verify(mockDiaryService.unmarkEaten(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).called(1);
});
test('restore - восстанавливает продукт', () async {
const diaryId = 1;
const mealId = 2;
const portionId = 5;
when(mockDiaryService.restore(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).thenAnswer((_) async => Future.value());
await diaryRepository.restore(
diaryId: diaryId,
mealId: mealId,
portionId: portionId,
);
verify(mockDiaryService.restore(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).called(1);
});
test('deleteProductFromMeal - удаляет продукт из приема пищи', () async {
const diaryId = 1;
const mealId = 2;
const portionId = 5;
when(mockDiaryService.deleteProductFromMeal(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).thenAnswer((_) async => Future.value());
await diaryRepository.deleteProductFromMeal(
diaryId: diaryId,
mealId: mealId,
portionId: portionId,
);
verify(mockDiaryService.deleteProductFromMeal(
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
)).called(1);
});
test('uploadPhotos - загружает несколько фотографий', () async {
const diaryId = 1;
const mealId = 2;
final files = [File('test1.jpg'), File('test2.jpg')];
when(mockDiaryService.uploadPhotoOfMeal(
diary: diaryId,
typeNo: mealId,
photo: anyNamed('photo'),
)).thenAnswer((_) async => Future.value());
await diaryRepository.uploadPhotos(
diaryId: diaryId,
mealId: mealId,
files: files,
);
verify(mockDiaryService.uploadPhotoOfMeal(
diary: diaryId,
typeNo: mealId,
photo: anyNamed('photo'),
)).called(files.length);
});
test('deletePhoto - удаляет фотографию', () async {
const diaryId = 1;
const mealId = 2;
const photo = DiaryPhotoModel(
id: 5,
originalName: 'test.jpg',
path: '/path/to/test.jpg',
size: 1024,
);
when(mockDiaryService.deletePhotoOfMeal(
diaryId: diaryId,
typeNo: mealId,
userAttachment: photo.id,
)).thenAnswer((_) async => Future.value());
await diaryRepository.deletePhoto(
diaryId: diaryId,
mealId: mealId,
photo: photo,
);
verify(mockDiaryService.deletePhotoOfMeal(
diaryId: diaryId,
typeNo: mealId,
userAttachment: photo.id,
)).called(1);
});
test('finishDiaryDay - завершает день дневника', () async {
const diaryId = 1;
const wakeUp = '07:00';
const retire = '23:00';
const comment = 'Хороший день';
when(mockDiaryService.finishDiaryDay(
diary: diaryId,
finishDiaryDayModel: anyNamed('finishDiaryDayModel'),
)).thenAnswer((_) async => Future.value());
await diaryRepository.finishDiaryDay(
diaryId: diaryId,
wakeUp: wakeUp,
retire: retire,
comment: comment,
);
verify(mockDiaryService.finishDiaryDay(
diary: diaryId,
finishDiaryDayModel: anyNamed('finishDiaryDayModel'),
)).called(1);
});
test('finishDiaryDay - завершает день без комментария', () async {
const diaryId = 1;
const wakeUp = '07:00';
const retire = '23:00';
when(mockDiaryService.finishDiaryDay(
diary: diaryId,
finishDiaryDayModel: anyNamed('finishDiaryDayModel'),
)).thenAnswer((_) async => Future.value());
await diaryRepository.finishDiaryDay(
diaryId: diaryId,
wakeUp: wakeUp,
retire: retire,
comment: null,
);
verify(mockDiaryService.finishDiaryDay(
diary: diaryId,
finishDiaryDayModel: anyNamed('finishDiaryDayModel'),
)).called(1);
});
test('sendProductToModeration - отправляет продукт на модерацию', () async {
const name = 'Новый продукт';
const energy = 100.0;
const proteins = 10.0;
const fats = 5.0;
const carbohydrates = 15.0;
const expectedModeration = GlossaryModerationModel(
glossary: GlossaryModel(
id: 1,
name: name,
grInPortion: 100,
energyOn100Gr: energy,
proteinsOn100Gr: proteins,
fatsOn100Gr: fats,
carbohydratesOn100Gr: carbohydrates,
energyOnPortion: energy,
proteinsOnPortion: proteins,
fatsOnPortion: fats,
carbohydratesOnPortion: carbohydrates,
),
);
when(mockDiaryService.sendProductToModeration(
data: anyNamed('data'),
)).thenAnswer((_) async => expectedModeration);
final result = await diaryRepository.sendProductToModeration(
name: name,
energy: energy,
proteins: proteins,
fats: fats,
carbohydrates: carbohydrates,
);
expect(result, isA<GlossaryModerationModel>());
verify(mockDiaryService.sendProductToModeration(
data: anyNamed('data'),
)).called(1);
});
test('fillSatiety - заполняет сытость', () async {
const diaryId = 1;
const mealId = 2;
const satiety = 5;
when(mockDiaryService.fillSatiety(
diary: diaryId,
typeNo: mealId,
satiety: satiety,
)).thenAnswer((_) async => Future.value());
await diaryRepository.fillSatiety(
diaryId: diaryId,
mealId: mealId,
satiety: satiety,
);
verify(mockDiaryService.fillSatiety(
diary: diaryId,
typeNo: mealId,
satiety: satiety,
)).called(1);
});
test('fillMood - заполняет настроение', () async {
const diaryId = 1;
const mealId = 2;
const mood = 4;
when(mockDiaryService.fillMood(
diary: diaryId,
typeNo: mealId,
mood: mood,
)).thenAnswer((_) async => Future.value());
await diaryRepository.fillMood(
diaryId: diaryId,
mealId: mealId,
mood: mood,
);
verify(mockDiaryService.fillMood(
diary: diaryId,
typeNo: mealId,
mood: mood,
)).called(1);
});
test('fillTime - заполняет время приема пищи', () async {
const diaryId = 1;
const mealId = 2;
const time = '12:30';
when(mockDiaryService.fillTime(
diary: diaryId,
typeNo: mealId,
time: time,
)).thenAnswer((_) async => Future.value());
await diaryRepository.fillTime(
diaryId: diaryId,
mealId: mealId,
time: time,
);
verify(mockDiaryService.fillTime(
diary: diaryId,
typeNo: mealId,
time: time,
)).called(1);
});
test('fillWakeup - заполняет время пробуждения', () async {
const diaryId = 1;
const time = '07:00';
when(mockDiaryService.fillWakeup(
diary: diaryId,
wakeUp: time,
)).thenAnswer((_) async => Future.value());
await diaryRepository.fillWakeup(
diaryId: diaryId,
time: time,
);
verify(mockDiaryService.fillWakeup(
diary: diaryId,
wakeUp: time,
)).called(1);
});
test('fillRetire - заполняет время отхода ко сну', () async {
const diaryId = 1;
const time = '23:00';
when(mockDiaryService.fillRetire(
diary: diaryId,
retire: time,
)).thenAnswer((_) async => Future.value());
await diaryRepository.fillRetire(
diaryId: diaryId,
time: time,
);
verify(mockDiaryService.fillRetire(
diary: diaryId,
retire: time,
)).called(1);
});
test('commentUserDay - комментирует день пользователя и отправляет событие',
() async {
const diaryId = 1;
final commentModel = ConsultantCommentModel(
comment: 'Хороший прогресс',
mealsComments: {},
portions: [],
);
when(mockDiaryService.commentUserDay(id: diaryId, body: commentModel))
.thenAnswer((_) async => Future.value());
await diaryRepository.commentUserDay(
diaryId: diaryId,
commentModel: commentModel,
);
verify(mockDiaryService.commentUserDay(id: diaryId, body: commentModel))
.called(1);
});
test('getDiaryComments - получает комментарии дневника', () async {
const planId = 1;
const diaryId = 1;
final expectedReview = ConsultantReviewModel(
planName: 'План питания',
planDuration: 30,
currentPlanDay: 5,
consultantComments: ConsultantComments(
dayComment: 'Хороший день',
mealsComments: [],
portionsComments: [],
),
);
when(mockDiaryService.getDiaryComments(planId: planId, diaryId: diaryId))
.thenAnswer((_) async => expectedReview);
final result = await diaryRepository.getDiaryComments(
planId: planId,
diaryId: diaryId,
);
expect(result, isA<ConsultantReviewModel>());
expect(result.planName, 'План питания');
verify(mockDiaryService.getDiaryComments(planId: planId, diaryId: diaryId))
.called(1);
});
test('viewCommentOfDiaryDayByConsultant - отмечает комментарий как просмотренный',
() async {
const diaryId = 1;
when(mockDiaryService.viewCommentOfDiaryDayByConsultant(diaryId: diaryId))
.thenAnswer((_) async => Future.value());
await diaryRepository.viewCommentOfDiaryDayByConsultant(diaryId: diaryId);
verify(mockDiaryService.viewCommentOfDiaryDayByConsultant(diaryId: diaryId))
.called(1);
});
test('getGlossariesIndex - получает список глоссариев по ID', () async {
final ids = [1, 2, 3];
const expectedGlossary = GlossaryPaginationModel(
glossariesList: [
GlossaryModel(
id: 1,
name: 'Яблоко',
grInPortion: 100,
energyOn100Gr: 52.0,
proteinsOn100Gr: 0.3,
fatsOn100Gr: 0.2,
carbohydratesOn100Gr: 14.0,
energyOnPortion: 52.0,
proteinsOnPortion: 0.3,
fatsOnPortion: 0.2,
carbohydratesOnPortion: 14.0,
),
],
);
when(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')))
.thenAnswer((_) async => expectedGlossary);
final result = await diaryRepository.getGlossariesIndex(ids: ids);
expect(result, isA<GlossaryPaginationModel>());
verify(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')))
.called(1);
});
test('getGlossariesIndex - обрабатывает пустой список ID', () async {
final ids = <int>[];
const expectedGlossary = GlossaryPaginationModel(glossariesList: []);
when(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')))
.thenAnswer((_) async => expectedGlossary);
final result = await diaryRepository.getGlossariesIndex(ids: ids);
expect(result, isA<GlossaryPaginationModel>());
expect(result.glossariesList.isEmpty, true);
});
test('getDiaryDayV2 - получает день дневника v2 с обогащенными данными',
() async {
const day = '2024-01-15';
const diaryDay = DiaryDayModel(
id: 1,
date: day,
closed: 0,
comment: '',
typeOfDiary: TypeOfDiaryModel(
hasChosenDiet: false,
hasChosenPlan: false,
diaryState: null,
),
meals: [
MealModel(
id: 1,
time: '12:00',
typeNumber: 1,
satiety: 0,
mood: 0,
portions: [
PortionModel(
id: 1,
productNutritionalValueId: 10,
productName: 'Яблоко',
quantity: 2,
portion: '100г',
fromDiet: false,
portionState: PortionState.eaten,
),
],
photos: [],
),
],
chosenPlanId: null,
dayOfChosenDiet: null,
diet: null,
);
const glossaryItem = GlossaryPaginationModel(
glossariesList: [
GlossaryModel(
id: 10,
name: 'Яблоко',
grInPortion: 100,
energyOn100Gr: 52.0,
proteinsOn100Gr: 0.3,
fatsOn100Gr: 0.2,
carbohydratesOn100Gr: 14.0,
energyOnPortion: 52.0,
proteinsOnPortion: 0.3,
fatsOnPortion: 0.2,
carbohydratesOnPortion: 14.0,
),
],
);
when(mockDiaryService.getDiaryDayV2(day: day))
.thenAnswer((_) async => diaryDay);
when(mockDiaryService.getGlossariesIndex(filters: anyNamed('filters')))
.thenAnswer((_) async => glossaryItem);
final result = await diaryRepository.getDiaryDayV2(day: day);
expect(result, isA<DiaryDayModel>());
expect(result.meals.first.portions.first.productCaloriesInfo, isNotNull);
});
test('createDiaryDay - создает новый день дневника', () async {
const day = '2024-01-15';
final diaryList = [
const DiaryDayModel(
id: 1,
date: day,
closed: 0,
comment: '',
typeOfDiary: TypeOfDiaryModel(
hasChosenDiet: false,
hasChosenPlan: false,
diaryState: null,
),
meals: [],
chosenPlanId: null,
dayOfChosenDiet: null,
diet: null,
),
];
when(mockDiaryService.createDay(body: anyNamed('body')))
.thenAnswer((_) async => Future.value());
when(mockDiaryService.getDiaryIndexByDate(date: day))
.thenAnswer((_) async => diaryList);
await diaryRepository.createDiaryDay(day: day);
verify(mockDiaryService.createDay(body: anyNamed('body'))).called(1);
verify(mockDiaryService.getDiaryIndexByDate(date: day)).called(1);
});
test('forceFetchStream - возвращает поток событий', () {
final stream = diaryRepository.forceFetchStream;
expect(stream, isNotNull);
expect(stream, isA<Stream<String>>());
});
});
}