mirror of
https://github.com/immich-app/immich.git
synced 2026-01-19 10:26:04 -05:00
* feat(trash_sync): do not restore assets deleted locally only small fixes * feat(trash_sync): revert tag name * feat(trash_sync): resolve merge conflicts * refactor(trash_sync): consolidate local asset deletion logic * feat(mobile): Add TrashOrigin enum Replace isRestorable to sourse change related logic in repo * feat(mobile): fix format * fix(mobile): fix restoration scope * fix(mobile): Add coverage for ActionService deleteLocal paths Update LocalSyncService tests Set default value for source column * fix(mobile): db - require trash origin and update drift schema --------- Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>
119 lines
4.4 KiB
Dart
119 lines
4.4 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/store.model.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/store.repository.dart';
|
|
import 'package:immich_mobile/repositories/download.repository.dart';
|
|
import 'package:immich_mobile/services/action.service.dart';
|
|
import 'package:mocktail/mocktail.dart';
|
|
|
|
import '../infrastructure/repository.mock.dart';
|
|
import '../repository.mocks.dart';
|
|
|
|
class MockDownloadRepository extends Mock implements DownloadRepository {}
|
|
|
|
void main() {
|
|
late ActionService sut;
|
|
|
|
late MockAssetApiRepository assetApiRepository;
|
|
late MockRemoteAssetRepository remoteAssetRepository;
|
|
late MockDriftLocalAssetRepository localAssetRepository;
|
|
late MockDriftAlbumApiRepository albumApiRepository;
|
|
late MockRemoteAlbumRepository remoteAlbumRepository;
|
|
late MockTrashedLocalAssetRepository trashedLocalAssetRepository;
|
|
late MockAssetMediaRepository assetMediaRepository;
|
|
late MockDownloadRepository downloadRepository;
|
|
|
|
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(() {
|
|
assetApiRepository = MockAssetApiRepository();
|
|
remoteAssetRepository = MockRemoteAssetRepository();
|
|
localAssetRepository = MockDriftLocalAssetRepository();
|
|
albumApiRepository = MockDriftAlbumApiRepository();
|
|
remoteAlbumRepository = MockRemoteAlbumRepository();
|
|
trashedLocalAssetRepository = MockTrashedLocalAssetRepository();
|
|
assetMediaRepository = MockAssetMediaRepository();
|
|
downloadRepository = MockDownloadRepository();
|
|
|
|
sut = ActionService(
|
|
assetApiRepository,
|
|
remoteAssetRepository,
|
|
localAssetRepository,
|
|
albumApiRepository,
|
|
remoteAlbumRepository,
|
|
trashedLocalAssetRepository,
|
|
assetMediaRepository,
|
|
downloadRepository,
|
|
);
|
|
});
|
|
|
|
tearDown(() async {
|
|
await Store.clear();
|
|
});
|
|
|
|
group('ActionService.deleteLocal', () {
|
|
test('routes deleted ids to trashed repository when Android trash handling is enabled', () async {
|
|
await Store.put(StoreKey.manageLocalMediaAndroid, true);
|
|
const ids = ['a', 'b'];
|
|
|
|
when(() => assetMediaRepository.deleteAll(ids)).thenAnswer((_) async => ids);
|
|
when(() => trashedLocalAssetRepository.applyTrashedAssets(ids)).thenAnswer((_) async {});
|
|
|
|
final result = await sut.deleteLocal(ids);
|
|
|
|
expect(result, ids.length);
|
|
verify(() => assetMediaRepository.deleteAll(ids)).called(1);
|
|
verify(() => trashedLocalAssetRepository.applyTrashedAssets(ids)).called(1);
|
|
verifyNever(() => localAssetRepository.delete(any()));
|
|
});
|
|
|
|
test('deletes locally when Android trash handling is disabled', () async {
|
|
await Store.put(StoreKey.manageLocalMediaAndroid, false);
|
|
const ids = ['c'];
|
|
|
|
when(() => assetMediaRepository.deleteAll(ids)).thenAnswer((_) async => ids);
|
|
when(() => localAssetRepository.delete(ids)).thenAnswer((_) async {});
|
|
|
|
final result = await sut.deleteLocal(ids);
|
|
|
|
expect(result, ids.length);
|
|
verify(() => assetMediaRepository.deleteAll(ids)).called(1);
|
|
verify(() => localAssetRepository.delete(ids)).called(1);
|
|
verifyNever(() => trashedLocalAssetRepository.applyTrashedAssets(any()));
|
|
});
|
|
|
|
test('short-circuits when nothing was deleted', () async {
|
|
await Store.put(StoreKey.manageLocalMediaAndroid, true);
|
|
const ids = ['x'];
|
|
|
|
when(() => assetMediaRepository.deleteAll(ids)).thenAnswer((_) async => <String>[]);
|
|
|
|
final result = await sut.deleteLocal(ids);
|
|
|
|
expect(result, 0);
|
|
verify(() => assetMediaRepository.deleteAll(ids)).called(1);
|
|
verifyNever(() => trashedLocalAssetRepository.applyTrashedAssets(any()));
|
|
verifyNever(() => localAssetRepository.delete(any()));
|
|
});
|
|
});
|
|
}
|