feat(diary): fixes

This commit is contained in:
mso7nueh
2026-05-10 20:08:51 +03:00
parent 2859607f4d
commit 63fc824449
17 changed files with 628 additions and 48 deletions

View File

@@ -7,6 +7,7 @@ import 'package:eatvio_app/core/internet_connection_cubit/internet_connection_st
import 'package:eatvio_app/core/local_db/app_database.dart';
import 'package:eatvio_app/core/local_db/dao/diary_dao.dart';
import 'package:eatvio_app/core/local_db/dao/glossary_dao.dart';
import 'package:eatvio_app/core/local_db/dao/media_dao.dart';
import 'package:eatvio_app/core/local_db/dao/pending_ops_dao.dart';
import 'package:eatvio_app/core/local_db/dao/sync_meta_dao.dart';
import 'package:eatvio_app/core/local_db/diary_local_data_source.dart';
@@ -50,6 +51,7 @@ void main() {
localDataSource = DiaryLocalDataSource(
diaryDao: DiaryDao(db),
glossaryDao: GlossaryDao(db),
mediaDao: MediaDao(db),
pendingOpsDao: PendingOpsDao(db),
syncMetaDao: SyncMetaDao(db),
);
@@ -86,22 +88,27 @@ void main() {
expect(payload['portion_id'], 55);
});
test('онлайн — вызывает сервис напрямую', () async {
test('онлайн — вызывает idempotent сервис напрямую', () async {
stubOnline();
when(mockDiaryService.deleteProductFromMeal(
when(mockDiaryService.deleteProductFromMealIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: 10, typeNo: 2, portionModel: 55,
)).thenAnswer((_) async {});
await repository.deleteProductFromMeal(diaryId: 10, mealId: 2, portionId: 55);
verify(mockDiaryService.deleteProductFromMeal(diary: 10, typeNo: 2, portionModel: 55)).called(1);
verify(mockDiaryService.deleteProductFromMealIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: 10, typeNo: 2, portionModel: 55,
)).called(1);
final ops = await localDataSource.getPendingOps();
expect(ops.isEmpty, isTrue);
});
test('онлайн 5xx — кладёт в очередь', () async {
stubOnline();
when(mockDiaryService.deleteProductFromMeal(
when(mockDiaryService.deleteProductFromMealIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: anyNamed('diary'), typeNo: anyNamed('typeNo'), portionModel: anyNamed('portionModel'),
)).thenThrow(DioException(
requestOptions: RequestOptions(),
@@ -118,7 +125,8 @@ void main() {
test('онлайн 4xx — пробрасывает ошибку, не кладёт в очередь', () async {
stubOnline();
when(mockDiaryService.deleteProductFromMeal(
when(mockDiaryService.deleteProductFromMealIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: anyNamed('diary'), typeNo: anyNamed('typeNo'), portionModel: anyNamed('portionModel'),
)).thenThrow(DioException(
requestOptions: RequestOptions(),
@@ -467,24 +475,16 @@ void main() {
// ──────────────────────────────────────────────────────────────────────────
group('_loadCachedDiaryDay edge cases', () {
test('возвращает null если serverId == null (офлайн-созданный день)', () async {
test('serverId == null (офлайн-созданный день) — возвращает отрицательный ID', () async {
// Кэшируем день без serverId
await localDataSource.cacheDiaryDay(date: '2026-05-02');
stubOffline();
// getDiaryDayV2 должен попробовать загрузить из кэша, но serverId == null → null
// Потом пробует сеть
when(mockDiaryService.getDiaryDayV2(day: anyNamed('day')))
.thenThrow(DioException(
requestOptions: RequestOptions(),
type: DioExceptionType.connectionError,
));
expect(
() => repository.getDiaryDayV2(day: '2026-05-02T00:00:00+00:00'),
throwsA(isA<DioException>()),
);
// getDiaryDayV2 должен вернуть день с отрицательным ID
final result = await repository.getDiaryDayV2(day: '2026-05-02T00:00:00+00:00');
expect(result.id, isNegative);
expect(result.date, '2026-05-02');
});
});

View File

@@ -8,6 +8,7 @@ import 'package:eatvio_app/core/interceptors/offline_error_interceptor.dart';
import 'package:eatvio_app/core/local_db/app_database.dart';
import 'package:eatvio_app/core/local_db/dao/diary_dao.dart';
import 'package:eatvio_app/core/local_db/dao/glossary_dao.dart';
import 'package:eatvio_app/core/local_db/dao/media_dao.dart';
import 'package:eatvio_app/core/local_db/dao/pending_ops_dao.dart';
import 'package:eatvio_app/core/local_db/dao/sync_meta_dao.dart';
import 'package:eatvio_app/core/local_db/diary_local_data_source.dart';
@@ -81,6 +82,7 @@ void main() {
localDataSource = DiaryLocalDataSource(
diaryDao: DiaryDao(db),
glossaryDao: GlossaryDao(db),
mediaDao: MediaDao(db),
pendingOpsDao: PendingOpsDao(db),
syncMetaDao: SyncMetaDao(db),
);

View File

@@ -384,7 +384,8 @@ void main() {
const mealId = 2;
const portionId = 5;
when(mockDiaryService.deleteProductFromMeal(
when(mockDiaryService.deleteProductFromMealIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
@@ -396,7 +397,8 @@ void main() {
portionId: portionId,
);
verify(mockDiaryService.deleteProductFromMeal(
verify(mockDiaryService.deleteProductFromMealIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: diaryId,
typeNo: mealId,
portionModel: portionId,
@@ -408,7 +410,8 @@ void main() {
const mealId = 2;
final files = [File('test1.jpg'), File('test2.jpg')];
when(mockDiaryService.uploadPhotoOfMeal(
when(mockDiaryService.uploadPhotoIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: diaryId,
typeNo: mealId,
photo: anyNamed('photo'),
@@ -420,7 +423,8 @@ void main() {
files: files,
);
verify(mockDiaryService.uploadPhotoOfMeal(
verify(mockDiaryService.uploadPhotoIdempotent(
idempotencyKey: anyNamed('idempotencyKey'),
diary: diaryId,
typeNo: mealId,
photo: anyNamed('photo'),