immich/mobile/test/domain/services/local_sync_service_test.dart
2026-07-28 16:11:31 +05:30

91 lines
3.5 KiB
Dart

import 'package:drift/drift.dart' as drift;
import 'package:drift/native.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/services/local_sync.service.dart';
import 'package:immich_mobile/domain/services/store.service.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
import 'package:immich_mobile/platform/native_sync_api.g.dart';
import 'package:mocktail/mocktail.dart';
import '../../infrastructure/repository.mock.dart';
import '../../service.mocks.dart';
void main() {
late LocalSyncService sut;
late DriftLocalAlbumRepository mockLocalAlbumRepository;
late DriftLocalAssetRepository mockLocalAssetRepository;
late MockTrashSyncRepository mockTrashSyncRepository;
late MockNativeSyncApi mockNativeSyncApi;
late Drift db;
setUpAll(() async {
TestWidgetsFlutterBinding.ensureInitialized();
debugDefaultTargetPlatformOverride = TargetPlatform.android;
db = Drift(drift.DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true));
await StoreService.init(storeRepository: DriftStoreRepository(db));
});
tearDownAll(() async {
debugDefaultTargetPlatformOverride = null;
await Store.clear();
await db.close();
});
setUp(() async {
mockLocalAlbumRepository = MockLocalAlbumRepository();
mockLocalAssetRepository = MockLocalAssetRepository();
mockTrashSyncRepository = MockTrashSyncRepository();
mockNativeSyncApi = MockNativeSyncApi();
when(() => mockNativeSyncApi.shouldFullSync()).thenAnswer((_) async => false);
when(() => mockNativeSyncApi.getMediaChanges()).thenAnswer(
(_) async => SyncDelta(hasChanges: false, updates: const [], deletes: const [], assetAlbums: const {}),
);
when(() => mockTrashSyncRepository.restoreChecksums()).thenAnswer((_) async {});
sut = LocalSyncService(
localAlbumRepository: mockLocalAlbumRepository,
localAssetRepository: mockLocalAssetRepository,
trashSyncRepository: mockTrashSyncRepository,
nativeSyncApi: mockNativeSyncApi,
);
});
group('LocalSyncService - no changes', () {
test('does nothing when there are no media changes', () async {
await sut.sync();
verify(() => mockNativeSyncApi.getMediaChanges()).called(1);
verifyNever(() => mockLocalAlbumRepository.updateAll(any()));
});
});
group('LocalSyncService - PlatformAsset conversion', () {
test('toLocalAsset uses correct updatedAt timestamp', () {
final platformAsset = PlatformAsset(
id: 'test-id',
name: 'test.jpg',
type: AssetType.image.index,
durationMs: 0,
orientation: 0,
isFavorite: false,
createdAt: 1700000000,
updatedAt: 1732000000,
playbackStyle: PlatformAssetPlaybackStyle.image,
);
final localAsset = platformAsset.toLocalAsset();
expect(localAsset.createdAt.millisecondsSinceEpoch ~/ 1000, 1700000000);
expect(localAsset.updatedAt.millisecondsSinceEpoch ~/ 1000, 1732000000);
expect(localAsset.updatedAt, isNot(localAsset.createdAt));
});
});
}