1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-08 23:07:06 +02:00

refactor(mobile): album api repository for album service (#12791)

* refactor(mobile): album api repository for album service
This commit is contained in:
Fynn Petersen-Frey
2024-09-20 15:32:37 +02:00
committed by GitHub
parent 94fc1f213a
commit 3868736799
20 changed files with 751 additions and 223 deletions

View File

@ -39,8 +39,10 @@ void main() {
group('Test SyncService grouped', () {
late final Isar db;
final MockHashService hs = MockHashService();
final MockEntityService entityService = MockEntityService();
final MockAlbumMediaRepository albumMediaRepository =
MockAlbumMediaRepository();
final MockAlbumApiRepository albumApiRepository = MockAlbumApiRepository();
final owner = User(
id: "1",
updatedAt: DateTime.now(),
@ -48,6 +50,7 @@ void main() {
name: "first last",
isAdmin: false,
);
late SyncService s;
setUpAll(() async {
WidgetsFlutterBinding.ensureInitialized();
db = await TestUtils.initIsar();
@ -68,9 +71,15 @@ void main() {
db.assets.clearSync();
db.assets.putAllSync(initialAssets);
});
s = SyncService(
db,
hs,
entityService,
albumMediaRepository,
albumApiRepository,
);
});
test('test inserting existing assets', () async {
SyncService s = SyncService(db, hs, albumMediaRepository);
final List<Asset> remoteAssets = [
makeAsset(checksum: "a", remoteId: "0-1"),
makeAsset(checksum: "b", remoteId: "2-1"),
@ -88,7 +97,6 @@ void main() {
});
test('test inserting new assets', () async {
SyncService s = SyncService(db, hs, albumMediaRepository);
final List<Asset> remoteAssets = [
makeAsset(checksum: "a", remoteId: "0-1"),
makeAsset(checksum: "b", remoteId: "2-1"),
@ -109,7 +117,6 @@ void main() {
});
test('test syncing duplicate assets', () async {
SyncService s = SyncService(db, hs, albumMediaRepository);
final List<Asset> remoteAssets = [
makeAsset(checksum: "a", remoteId: "0-1"),
makeAsset(checksum: "b", remoteId: "1-1"),
@ -157,7 +164,6 @@ void main() {
});
test('test efficient sync', () async {
SyncService s = SyncService(db, hs, albumMediaRepository);
final List<Asset> toUpsert = [
makeAsset(checksum: "a", remoteId: "0-1"), // changed
makeAsset(checksum: "f", remoteId: "0-2"), // new

View File

@ -1,4 +1,5 @@
import 'package:immich_mobile/interfaces/album.interface.dart';
import 'package:immich_mobile/interfaces/album_api.interface.dart';
import 'package:immich_mobile/interfaces/album_media.interface.dart';
import 'package:immich_mobile/interfaces/asset.interface.dart';
import 'package:immich_mobile/interfaces/asset_media.interface.dart';
@ -20,3 +21,5 @@ class MockAlbumMediaRepository extends Mock implements IAlbumMediaRepository {}
class MockAssetMediaRepository extends Mock implements IAssetMediaRepository {}
class MockFileMediaRepository extends Mock implements IFileMediaRepository {}
class MockAlbumApiRepository extends Mock implements IAlbumApiRepository {}

View File

@ -1,4 +1,5 @@
import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/services/entity.service.dart';
import 'package:immich_mobile/services/hash.service.dart';
import 'package:immich_mobile/services/sync.service.dart';
import 'package:immich_mobile/services/user.service.dart';
@ -11,3 +12,5 @@ class MockUserService extends Mock implements UserService {}
class MockSyncService extends Mock implements SyncService {}
class MockHashService extends Mock implements HashService {}
class MockEntityService extends Mock implements EntityService {}

View File

@ -3,39 +3,41 @@ import 'package:immich_mobile/entities/backup_album.entity.dart';
import 'package:immich_mobile/services/album.service.dart';
import 'package:mocktail/mocktail.dart';
import '../fixtures/album.stub.dart';
import '../fixtures/asset.stub.dart';
import '../fixtures/user.stub.dart';
import '../repository.mocks.dart';
import '../service.mocks.dart';
void main() {
late AlbumService sut;
late MockApiService apiService;
late MockUserService userService;
late MockSyncService syncService;
late MockEntityService entityService;
late MockAlbumRepository albumRepository;
late MockAssetRepository assetRepository;
late MockUserRepository userRepository;
late MockBackupRepository backupRepository;
late MockAlbumMediaRepository albumMediaRepository;
late MockAlbumApiRepository albumApiRepository;
setUp(() {
apiService = MockApiService();
userService = MockUserService();
syncService = MockSyncService();
entityService = MockEntityService();
albumRepository = MockAlbumRepository();
assetRepository = MockAssetRepository();
userRepository = MockUserRepository();
backupRepository = MockBackupRepository();
albumMediaRepository = MockAlbumMediaRepository();
albumApiRepository = MockAlbumApiRepository();
sut = AlbumService(
apiService,
userService,
syncService,
entityService,
albumRepository,
assetRepository,
userRepository,
backupRepository,
albumMediaRepository,
albumApiRepository,
);
});
@ -70,4 +72,125 @@ void main() {
verifyNoMoreInteractions(syncService);
});
});
group('refreshRemoteAlbums', () {
test('isShared: false', () async {
when(() => userService.refreshUsers()).thenAnswer((_) async => true);
when(() => albumApiRepository.getAll(shared: null))
.thenAnswer((_) async => [AlbumStub.oneAsset, AlbumStub.twoAsset]);
when(
() => syncService.syncRemoteAlbumsToDb(
[AlbumStub.oneAsset, AlbumStub.twoAsset],
isShared: false,
),
).thenAnswer((_) async => true);
final result = await sut.refreshRemoteAlbums(isShared: false);
expect(result, true);
verify(() => userService.refreshUsers()).called(1);
verify(() => albumApiRepository.getAll(shared: null)).called(1);
verify(
() => syncService.syncRemoteAlbumsToDb(
[AlbumStub.oneAsset, AlbumStub.twoAsset],
isShared: false,
),
).called(1);
verifyNoMoreInteractions(userService);
verifyNoMoreInteractions(albumApiRepository);
verifyNoMoreInteractions(syncService);
});
});
group('createAlbum', () {
test('shared with assets', () async {
when(
() => albumApiRepository.create(
"name",
assetIds: any(named: "assetIds"),
sharedUserIds: any(named: "sharedUserIds"),
),
).thenAnswer((_) async => AlbumStub.oneAsset);
when(
() => entityService.fillAlbumWithDatabaseEntities(AlbumStub.oneAsset),
).thenAnswer((_) async => AlbumStub.oneAsset);
when(
() => albumRepository.create(AlbumStub.oneAsset),
).thenAnswer((_) async => AlbumStub.twoAsset);
final result =
await sut.createAlbum("name", [AssetStub.image1], [UserStub.user1]);
expect(result, AlbumStub.twoAsset);
verify(
() => albumApiRepository.create(
"name",
assetIds: [AssetStub.image1.remoteId!],
sharedUserIds: [UserStub.user1.id],
),
).called(1);
verify(
() => entityService.fillAlbumWithDatabaseEntities(AlbumStub.oneAsset),
).called(1);
});
});
group('addAdditionalAssetToAlbum', () {
test('one added, one duplicate', () async {
when(
() => albumApiRepository.addAssets(AlbumStub.oneAsset.remoteId!, any()),
).thenAnswer(
(_) async => (
added: [AssetStub.image2.remoteId!],
duplicates: [AssetStub.image1.remoteId!]
),
);
when(
() => albumRepository.getById(AlbumStub.oneAsset.id),
).thenAnswer((_) async => AlbumStub.oneAsset);
when(
() => albumRepository.addAssets(AlbumStub.oneAsset, [AssetStub.image2]),
).thenAnswer((_) async {});
when(
() => albumRepository.removeAssets(AlbumStub.oneAsset, []),
).thenAnswer((_) async {});
when(
() => albumRepository.recalculateMetadata(AlbumStub.oneAsset),
).thenAnswer((_) async => AlbumStub.oneAsset);
when(
() => albumRepository.update(AlbumStub.oneAsset),
).thenAnswer((_) async => AlbumStub.oneAsset);
final result = await sut.addAdditionalAssetToAlbum(
[AssetStub.image1, AssetStub.image2],
AlbumStub.oneAsset,
);
expect(result != null, true);
expect(result!.alreadyInAlbum, [AssetStub.image1.remoteId!]);
expect(result.successfullyAdded, 1);
});
});
group('addAdditionalUserToAlbum', () {
test('one added', () async {
when(
() =>
albumApiRepository.addUsers(AlbumStub.emptyAlbum.remoteId!, any()),
).thenAnswer(
(_) async => AlbumStub.sharedWithUser,
);
when(
() => entityService
.fillAlbumWithDatabaseEntities(AlbumStub.sharedWithUser),
).thenAnswer((_) async => AlbumStub.sharedWithUser);
when(
() => albumRepository.update(AlbumStub.sharedWithUser),
).thenAnswer((_) async => AlbumStub.sharedWithUser);
final result = await sut.addAdditionalUserToAlbum(
[UserStub.user2.id],
AlbumStub.emptyAlbum,
);
expect(result, true);
});
});
}

View File

@ -0,0 +1,76 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/entities/album.entity.dart';
import 'package:immich_mobile/services/entity.service.dart';
import 'package:mocktail/mocktail.dart';
import '../fixtures/asset.stub.dart';
import '../fixtures/user.stub.dart';
import '../repository.mocks.dart';
void main() {
late EntityService sut;
late MockAssetRepository assetRepository;
late MockUserRepository userRepository;
setUp(() {
assetRepository = MockAssetRepository();
userRepository = MockUserRepository();
sut = EntityService(assetRepository, userRepository);
});
group('fillAlbumWithDatabaseEntities', () {
test('remote album with owner, thumbnail, sharedUsers and assets',
() async {
final Album album = Album(
name: "album-with-two-assets-and-two-users",
localId: "album-with-two-assets-and-two-users-local",
remoteId: "album-with-two-assets-and-two-users-remote",
createdAt: DateTime(2001),
modifiedAt: DateTime(2010),
shared: true,
activityEnabled: true,
startDate: DateTime(2019),
endDate: DateTime(2020),
)
..remoteThumbnailAssetId = AssetStub.image1.remoteId
..assets.addAll([AssetStub.image1, AssetStub.image1])
..owner.value = UserStub.user1
..sharedUsers.addAll([UserStub.admin, UserStub.admin]);
when(() => userRepository.get(album.ownerId!))
.thenAnswer((_) async => UserStub.admin);
when(() => assetRepository.getByRemoteId(AssetStub.image1.remoteId!))
.thenAnswer((_) async => AssetStub.image1);
when(() => userRepository.getByIds(any()))
.thenAnswer((_) async => [UserStub.user1, UserStub.user2]);
when(() => assetRepository.getAllByRemoteId(any()))
.thenAnswer((_) async => [AssetStub.image1, AssetStub.image2]);
await sut.fillAlbumWithDatabaseEntities(album);
expect(album.owner.value, UserStub.admin);
expect(album.thumbnail.value, AssetStub.image1);
expect(album.remoteUsers.toSet(), {UserStub.user1, UserStub.user2});
expect(album.remoteAssets.toSet(), {AssetStub.image1, AssetStub.image2});
});
test('remote album without any info', () async {
makeEmptyAlbum() => Album(
name: "album-without-info",
localId: "album-without-info-local",
remoteId: "album-without-info-remote",
createdAt: DateTime(2001),
modifiedAt: DateTime(2010),
shared: false,
activityEnabled: false,
);
final album = makeEmptyAlbum();
await sut.fillAlbumWithDatabaseEntities(album);
verifyNoMoreInteractions(assetRepository);
verifyNoMoreInteractions(userRepository);
expect(album, makeEmptyAlbum());
});
});
}