chore: bump dart sdk to 3.8 (#20355)
* chore: bump dart sdk to 3.8 * chore: make build * make pigeon * chore: format files --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
@@ -33,12 +33,12 @@ void main() {
|
||||
|
||||
when(() => userService.getMyUser()).thenReturn(UserStub.user1);
|
||||
|
||||
when(() => albumRepository.transaction<void>(any())).thenAnswer(
|
||||
(call) => (call.positionalArguments.first as Function).call(),
|
||||
);
|
||||
when(() => assetRepository.transaction<Null>(any())).thenAnswer(
|
||||
(call) => (call.positionalArguments.first as Function).call(),
|
||||
);
|
||||
when(
|
||||
() => albumRepository.transaction<void>(any()),
|
||||
).thenAnswer((call) => (call.positionalArguments.first as Function).call());
|
||||
when(
|
||||
() => assetRepository.transaction<Null>(any()),
|
||||
).thenAnswer((call) => (call.positionalArguments.first as Function).call());
|
||||
|
||||
sut = AlbumService(
|
||||
syncService,
|
||||
@@ -66,15 +66,14 @@ void main() {
|
||||
|
||||
test('one selected albums, two on device', () async {
|
||||
when(() => backupRepository.getIdsBySelection(BackupSelection.exclude)).thenAnswer((_) async => []);
|
||||
when(() => backupRepository.getIdsBySelection(BackupSelection.select))
|
||||
.thenAnswer((_) async => [AlbumStub.oneAsset.localId!]);
|
||||
when(
|
||||
() => backupRepository.getIdsBySelection(BackupSelection.select),
|
||||
).thenAnswer((_) async => [AlbumStub.oneAsset.localId!]);
|
||||
when(() => albumMediaRepository.getAll()).thenAnswer((_) async => [AlbumStub.oneAsset, AlbumStub.twoAsset]);
|
||||
when(() => syncService.syncLocalAlbumAssetsToDb(any(), any())).thenAnswer((_) async => true);
|
||||
final result = await sut.refreshDeviceAlbums();
|
||||
expect(result, true);
|
||||
verify(
|
||||
() => syncService.syncLocalAlbumAssetsToDb([AlbumStub.oneAsset], null),
|
||||
).called(1);
|
||||
verify(() => syncService.syncLocalAlbumAssetsToDb([AlbumStub.oneAsset], null)).called(1);
|
||||
verifyNoMoreInteractions(syncService);
|
||||
});
|
||||
});
|
||||
@@ -85,15 +84,12 @@ void main() {
|
||||
when(() => syncService.syncUsersFromServer(any())).thenAnswer((_) async => true);
|
||||
when(() => albumApiRepository.getAll(shared: true)).thenAnswer((_) async => [AlbumStub.sharedWithUser]);
|
||||
|
||||
when(() => albumApiRepository.getAll(shared: null))
|
||||
.thenAnswer((_) async => [AlbumStub.oneAsset, AlbumStub.twoAsset]);
|
||||
when(
|
||||
() => albumApiRepository.getAll(shared: null),
|
||||
).thenAnswer((_) async => [AlbumStub.oneAsset, AlbumStub.twoAsset]);
|
||||
|
||||
when(
|
||||
() => syncService.syncRemoteAlbumsToDb([
|
||||
AlbumStub.twoAsset,
|
||||
AlbumStub.oneAsset,
|
||||
AlbumStub.sharedWithUser,
|
||||
]),
|
||||
() => syncService.syncRemoteAlbumsToDb([AlbumStub.twoAsset, AlbumStub.oneAsset, AlbumStub.sharedWithUser]),
|
||||
).thenAnswer((_) async => true);
|
||||
final result = await sut.refreshRemoteAlbums();
|
||||
expect(result, true);
|
||||
@@ -102,13 +98,7 @@ void main() {
|
||||
verify(() => albumApiRepository.getAll(shared: true)).called(1);
|
||||
verify(() => albumApiRepository.getAll(shared: null)).called(1);
|
||||
verify(
|
||||
() => syncService.syncRemoteAlbumsToDb(
|
||||
[
|
||||
AlbumStub.twoAsset,
|
||||
AlbumStub.oneAsset,
|
||||
AlbumStub.sharedWithUser,
|
||||
],
|
||||
),
|
||||
() => syncService.syncRemoteAlbumsToDb([AlbumStub.twoAsset, AlbumStub.oneAsset, AlbumStub.sharedWithUser]),
|
||||
).called(1);
|
||||
verifyNoMoreInteractions(userService);
|
||||
verifyNoMoreInteractions(albumApiRepository);
|
||||
@@ -130,9 +120,7 @@ void main() {
|
||||
() => entityService.fillAlbumWithDatabaseEntities(AlbumStub.oneAsset),
|
||||
).thenAnswer((_) async => AlbumStub.oneAsset);
|
||||
|
||||
when(
|
||||
() => albumRepository.create(AlbumStub.oneAsset),
|
||||
).thenAnswer((_) async => AlbumStub.twoAsset);
|
||||
when(() => albumRepository.create(AlbumStub.oneAsset)).thenAnswer((_) async => AlbumStub.twoAsset);
|
||||
|
||||
final result = await sut.createAlbum("name", [AssetStub.image1], [UserStub.user1]);
|
||||
expect(result, AlbumStub.twoAsset);
|
||||
@@ -143,9 +131,7 @@ void main() {
|
||||
sharedUserIds: [UserStub.user1.id],
|
||||
),
|
||||
).called(1);
|
||||
verify(
|
||||
() => entityService.fillAlbumWithDatabaseEntities(AlbumStub.oneAsset),
|
||||
).called(1);
|
||||
verify(() => entityService.fillAlbumWithDatabaseEntities(AlbumStub.oneAsset)).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -153,29 +139,14 @@ void main() {
|
||||
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.get(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);
|
||||
).thenAnswer((_) async => (added: [AssetStub.image2.remoteId!], duplicates: [AssetStub.image1.remoteId!]));
|
||||
when(() => albumRepository.get(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.addAssets(
|
||||
AlbumStub.oneAsset,
|
||||
[AssetStub.image1, AssetStub.image2],
|
||||
);
|
||||
final result = await sut.addAssets(AlbumStub.oneAsset, [AssetStub.image1, AssetStub.image2]);
|
||||
|
||||
expect(result != null, true);
|
||||
expect(result!.alreadyInAlbum, [AssetStub.image1.remoteId!]);
|
||||
@@ -187,9 +158,7 @@ void main() {
|
||||
test('one added', () async {
|
||||
when(
|
||||
() => albumApiRepository.addUsers(AlbumStub.emptyAlbum.remoteId!, any()),
|
||||
).thenAnswer(
|
||||
(_) async => AlbumStub.sharedWithUser,
|
||||
);
|
||||
).thenAnswer((_) async => AlbumStub.sharedWithUser);
|
||||
|
||||
when(
|
||||
() => albumRepository.addUsers(
|
||||
@@ -198,14 +167,9 @@ void main() {
|
||||
),
|
||||
).thenAnswer((_) async => AlbumStub.emptyAlbum);
|
||||
|
||||
when(
|
||||
() => albumRepository.update(AlbumStub.emptyAlbum),
|
||||
).thenAnswer((_) async => AlbumStub.emptyAlbum);
|
||||
when(() => albumRepository.update(AlbumStub.emptyAlbum)).thenAnswer((_) async => AlbumStub.emptyAlbum);
|
||||
|
||||
final result = await sut.addUsers(
|
||||
AlbumStub.emptyAlbum,
|
||||
[UserStub.user2.id],
|
||||
);
|
||||
final result = await sut.addUsers(AlbumStub.emptyAlbum, [UserStub.user2.id]);
|
||||
|
||||
expect(result, true);
|
||||
});
|
||||
|
||||
@@ -81,9 +81,7 @@ void main() {
|
||||
final upsertExifCallback = verify(() => syncService.upsertAssetsWithExif(captureAny()));
|
||||
upsertExifCallback.called(1);
|
||||
final receivedAssets = upsertExifCallback.captured.firstOrNull as List<Object>? ?? [];
|
||||
final receivedDatetime = receivedAssets.cast<Asset>().map(
|
||||
(a) => a.exifInfo?.dateTimeOriginal ?? DateTime(0),
|
||||
);
|
||||
final receivedDatetime = receivedAssets.cast<Asset>().map((a) => a.exifInfo?.dateTimeOriginal ?? DateTime(0));
|
||||
expect(receivedDatetime.every((d) => d == dateTime), isTrue);
|
||||
});
|
||||
|
||||
@@ -97,8 +95,8 @@ void main() {
|
||||
upsertExifCallback.called(1);
|
||||
final receivedAssets = upsertExifCallback.captured.firstOrNull as List<Object>? ?? [];
|
||||
final receivedCoords = receivedAssets.cast<Asset>().map(
|
||||
(a) => LatLng(a.exifInfo?.latitude ?? 0, a.exifInfo?.longitude ?? 0),
|
||||
);
|
||||
(a) => LatLng(a.exifInfo?.latitude ?? 0, a.exifInfo?.longitude ?? 0),
|
||||
);
|
||||
expect(receivedCoords.every((l) => l == latLng), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -95,10 +95,7 @@ void main() {
|
||||
|
||||
when(() => apiService.resolveAndSetEndpoint(testUrl)).thenThrow(Exception('Invalid URL'));
|
||||
|
||||
expect(
|
||||
() async => await sut.validateServerUrl(testUrl),
|
||||
throwsA(isA<Exception>()),
|
||||
);
|
||||
expect(() async => await sut.validateServerUrl(testUrl), throwsA(isA<Exception>()));
|
||||
|
||||
verify(() => apiService.resolveAndSetEndpoint(testUrl)).called(1);
|
||||
verifyNever(() => apiService.setDeviceInfoHeader());
|
||||
@@ -109,10 +106,7 @@ void main() {
|
||||
|
||||
when(() => apiService.resolveAndSetEndpoint(testUrl)).thenThrow(Exception('Server is not reachable'));
|
||||
|
||||
expect(
|
||||
() async => await sut.validateServerUrl(testUrl),
|
||||
throwsA(isA<Exception>()),
|
||||
);
|
||||
expect(() async => await sut.validateServerUrl(testUrl), throwsA(isA<Exception>()));
|
||||
|
||||
verify(() => apiService.resolveAndSetEndpoint(testUrl)).called(1);
|
||||
verifyNever(() => apiService.setDeviceInfoHeader());
|
||||
@@ -126,10 +120,7 @@ void main() {
|
||||
when(() => authRepository.clearLocalData()).thenAnswer((_) => Future.value(null));
|
||||
when(() => uploadService.cancelBackup()).thenAnswer((_) => Future.value(1));
|
||||
when(
|
||||
() => appSettingsService.setSetting(
|
||||
AppSettingsEnum.enableBackup,
|
||||
false,
|
||||
),
|
||||
() => appSettingsService.setSetting(AppSettingsEnum.enableBackup, false),
|
||||
).thenAnswer((_) => Future.value(null));
|
||||
await sut.logout();
|
||||
|
||||
@@ -144,10 +135,7 @@ void main() {
|
||||
when(() => authRepository.clearLocalData()).thenAnswer((_) => Future.value(null));
|
||||
when(() => uploadService.cancelBackup()).thenAnswer((_) => Future.value(1));
|
||||
when(
|
||||
() => appSettingsService.setSetting(
|
||||
AppSettingsEnum.enableBackup,
|
||||
false,
|
||||
),
|
||||
() => appSettingsService.setSetting(AppSettingsEnum.enableBackup, false),
|
||||
).thenAnswer((_) => Future.value(null));
|
||||
await sut.logout();
|
||||
|
||||
@@ -176,8 +164,9 @@ void main() {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('TestWifi');
|
||||
when(() => authRepository.getLocalEndpoint()).thenReturn('http://local.endpoint');
|
||||
when(() => apiService.resolveAndSetEndpoint('http://local.endpoint'))
|
||||
.thenAnswer((_) async => 'http://local.endpoint');
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('http://local.endpoint'),
|
||||
).thenAnswer((_) async => 'http://local.endpoint');
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
@@ -192,12 +181,9 @@ void main() {
|
||||
test('Should set external endpoint if wifi name not matching', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
const AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
]);
|
||||
when(
|
||||
() => authRepository.getExternalEndpointList(),
|
||||
).thenReturn([const AuxilaryEndpoint(url: 'https://external.endpoint', status: AuxCheckStatus.valid)]);
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).thenAnswer((_) async => 'https://external.endpoint/api');
|
||||
@@ -209,23 +195,15 @@ void main() {
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).called(1);
|
||||
verify(() => apiService.resolveAndSetEndpoint('https://external.endpoint')).called(1);
|
||||
});
|
||||
|
||||
test('Should set second external endpoint if the first throw any error', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
const AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
const AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint2',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
const AuxilaryEndpoint(url: 'https://external.endpoint', status: AuxCheckStatus.valid),
|
||||
const AuxilaryEndpoint(url: 'https://external.endpoint2', status: AuxCheckStatus.valid),
|
||||
]);
|
||||
|
||||
when(
|
||||
@@ -242,23 +220,15 @@ void main() {
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint2'),
|
||||
).called(1);
|
||||
verify(() => apiService.resolveAndSetEndpoint('https://external.endpoint2')).called(1);
|
||||
});
|
||||
|
||||
test('Should set second external endpoint if the first throw ApiException', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
const AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
const AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint2',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
const AuxilaryEndpoint(url: 'https://external.endpoint', status: AuxCheckStatus.valid),
|
||||
const AuxilaryEndpoint(url: 'https://external.endpoint2', status: AuxCheckStatus.valid),
|
||||
]);
|
||||
|
||||
when(
|
||||
@@ -275,17 +245,16 @@ void main() {
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint2'),
|
||||
).called(1);
|
||||
verify(() => apiService.resolveAndSetEndpoint('https://external.endpoint2')).called(1);
|
||||
});
|
||||
|
||||
test('Should handle error when setting local connection', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('TestWifi');
|
||||
when(() => authRepository.getLocalEndpoint()).thenReturn('http://local.endpoint');
|
||||
when(() => apiService.resolveAndSetEndpoint('http://local.endpoint'))
|
||||
.thenThrow(Exception('Local endpoint error'));
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('http://local.endpoint'),
|
||||
).thenThrow(Exception('Local endpoint error'));
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
@@ -300,12 +269,9 @@ void main() {
|
||||
test('Should handle error when setting external connection', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
const AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
]);
|
||||
when(
|
||||
() => authRepository.getExternalEndpointList(),
|
||||
).thenReturn([const AuxilaryEndpoint(url: 'https://external.endpoint', status: AuxCheckStatus.valid)]);
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).thenThrow(Exception('External endpoint error'));
|
||||
@@ -317,9 +283,7 @@ void main() {
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).called(1);
|
||||
verify(() => apiService.resolveAndSetEndpoint('https://external.endpoint')).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,23 +22,22 @@ void main() {
|
||||
|
||||
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 = User.fromDto(UserStub.user1)
|
||||
..sharedUsers.addAll(
|
||||
[User.fromDto(UserStub.admin), User.fromDto(UserStub.admin)],
|
||||
);
|
||||
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 = User.fromDto(UserStub.user1)
|
||||
..sharedUsers.addAll([User.fromDto(UserStub.admin), User.fromDto(UserStub.admin)]);
|
||||
|
||||
when(() => userRepository.getByUserId(any())).thenAnswer((_) async => UserStub.admin);
|
||||
when(() => userRepository.getByUserId(any())).thenAnswer((_) async => UserStub.admin);
|
||||
@@ -52,23 +51,20 @@ void main() {
|
||||
await sut.fillAlbumWithDatabaseEntities(album);
|
||||
expect(album.owner.value?.toDto(), UserStub.admin);
|
||||
expect(album.thumbnail.value, AssetStub.image1);
|
||||
expect(
|
||||
album.remoteUsers.map((u) => u.toDto()).toSet(),
|
||||
{UserStub.user1, UserStub.user2},
|
||||
);
|
||||
expect(album.remoteUsers.map((u) => u.toDto()).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,
|
||||
);
|
||||
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);
|
||||
|
||||
@@ -31,15 +31,10 @@ void main() {
|
||||
mockBackgroundService = MockBackgroundService();
|
||||
mockDeviceAssetRepository = MockDeviceAssetRepository();
|
||||
|
||||
sut = HashService(
|
||||
deviceAssetRepository: mockDeviceAssetRepository,
|
||||
backgroundService: mockBackgroundService,
|
||||
);
|
||||
sut = HashService(deviceAssetRepository: mockDeviceAssetRepository, backgroundService: mockBackgroundService);
|
||||
|
||||
when(() => mockDeviceAssetRepository.transaction<Null>(any())).thenAnswer((_) async {
|
||||
final capturedCallback = verify(
|
||||
() => mockDeviceAssetRepository.transaction<Null>(captureAny()),
|
||||
).captured;
|
||||
final capturedCallback = verify(() => mockDeviceAssetRepository.transaction<Null>(captureAny())).captured;
|
||||
// Invoke the transaction callback
|
||||
await (capturedCallback.firstOrNull as Future<Null> Function()?)?.call();
|
||||
});
|
||||
@@ -53,17 +48,13 @@ void main() {
|
||||
|
||||
when(() => mockBackgroundService.digestFiles([file.path])).thenAnswer((_) async => [hash]);
|
||||
// No DB entries for this asset
|
||||
when(
|
||||
() => mockDeviceAssetRepository.getByIds([AssetStub.image1.localId!]),
|
||||
).thenAnswer((_) async => []);
|
||||
when(() => mockDeviceAssetRepository.getByIds([AssetStub.image1.localId!])).thenAnswer((_) async => []);
|
||||
|
||||
final result = await sut.hashAssets([mockAsset]);
|
||||
|
||||
// Verify we stored the new hash in DB
|
||||
when(() => mockDeviceAssetRepository.transaction<Null>(any())).thenAnswer((_) async {
|
||||
final capturedCallback = verify(
|
||||
() => mockDeviceAssetRepository.transaction<Null>(captureAny()),
|
||||
).captured;
|
||||
final capturedCallback = verify(() => mockDeviceAssetRepository.transaction<Null>(captureAny())).captured;
|
||||
// Invoke the transaction callback
|
||||
await (capturedCallback.firstOrNull as Future<Null> Function()?)?.call();
|
||||
verify(
|
||||
@@ -73,10 +64,7 @@ void main() {
|
||||
).called(1);
|
||||
verify(() => mockDeviceAssetRepository.deleteIds([])).called(1);
|
||||
});
|
||||
expect(
|
||||
result,
|
||||
[AssetStub.image1.copyWith(checksum: base64.encode(hash))],
|
||||
);
|
||||
expect(result, [AssetStub.image1.copyWith(checksum: base64.encode(hash))]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -84,15 +72,9 @@ void main() {
|
||||
test("when the asset is not modified", () async {
|
||||
final hash = utf8.encode("image1-hash");
|
||||
|
||||
when(
|
||||
() => mockDeviceAssetRepository.getByIds([AssetStub.image1.localId!]),
|
||||
).thenAnswer(
|
||||
when(() => mockDeviceAssetRepository.getByIds([AssetStub.image1.localId!])).thenAnswer(
|
||||
(_) async => [
|
||||
DeviceAsset(
|
||||
assetId: AssetStub.image1.localId!,
|
||||
hash: hash,
|
||||
modifiedTime: AssetStub.image1.fileModifiedAt,
|
||||
),
|
||||
DeviceAsset(assetId: AssetStub.image1.localId!, hash: hash, modifiedTime: AssetStub.image1.fileModifiedAt),
|
||||
],
|
||||
);
|
||||
final result = await sut.hashAssets([AssetStub.image1]);
|
||||
@@ -102,9 +84,7 @@ void main() {
|
||||
verifyNever(() => mockDeviceAssetRepository.updateAll(any()));
|
||||
verifyNever(() => mockDeviceAssetRepository.deleteIds(any()));
|
||||
|
||||
expect(result, [
|
||||
AssetStub.image1.copyWith(checksum: base64.encode(hash)),
|
||||
]);
|
||||
expect(result, [AssetStub.image1.copyWith(checksum: base64.encode(hash))]);
|
||||
});
|
||||
|
||||
test("hashed successful when asset is modified", () async {
|
||||
@@ -118,9 +98,7 @@ void main() {
|
||||
final result = await sut.hashAssets([mockAsset]);
|
||||
|
||||
when(() => mockDeviceAssetRepository.transaction<Null>(any())).thenAnswer((_) async {
|
||||
final capturedCallback = verify(
|
||||
() => mockDeviceAssetRepository.transaction<Null>(captureAny()),
|
||||
).captured;
|
||||
final capturedCallback = verify(() => mockDeviceAssetRepository.transaction<Null>(captureAny())).captured;
|
||||
// Invoke the transaction callback
|
||||
await (capturedCallback.firstOrNull as Future<Null> Function()?)?.call();
|
||||
verify(
|
||||
@@ -133,9 +111,7 @@ void main() {
|
||||
|
||||
verify(() => mockBackgroundService.digestFiles([file.path])).called(1);
|
||||
|
||||
expect(result, [
|
||||
AssetStub.image1.copyWith(checksum: base64.encode(hash)),
|
||||
]);
|
||||
expect(result, [AssetStub.image1.copyWith(checksum: base64.encode(hash))]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -161,18 +137,14 @@ void main() {
|
||||
verifyNever(() => mockBackgroundService.digestFiles(any()));
|
||||
verifyNever(() => mockBackgroundService.digestFile(any()));
|
||||
verifyNever(() => mockDeviceAssetRepository.updateAll(any()));
|
||||
verify(
|
||||
() => mockDeviceAssetRepository.deleteIds([AssetStub.image1.localId!]),
|
||||
).called(1);
|
||||
verify(() => mockDeviceAssetRepository.deleteIds([AssetStub.image1.localId!])).called(1);
|
||||
|
||||
expect(result, isEmpty);
|
||||
});
|
||||
|
||||
test("cleanups DeviceAsset when hashing failed", () async {
|
||||
when(() => mockDeviceAssetRepository.transaction<Null>(any())).thenAnswer((_) async {
|
||||
final capturedCallback = verify(
|
||||
() => mockDeviceAssetRepository.transaction<Null>(captureAny()),
|
||||
).captured;
|
||||
final capturedCallback = verify(() => mockDeviceAssetRepository.transaction<Null>(captureAny())).captured;
|
||||
// Invoke the transaction callback
|
||||
await (capturedCallback.firstOrNull as Future<Null> Function()?)?.call();
|
||||
|
||||
@@ -194,9 +166,7 @@ void main() {
|
||||
// To avoid this, we capture the callback and execute it within the transaction stub itself
|
||||
// and verify the results inside the transaction stub
|
||||
verify(() => mockDeviceAssetRepository.updateAll([])).called(1);
|
||||
verify(
|
||||
() => mockDeviceAssetRepository.deleteIds([AssetStub.image1.localId!]),
|
||||
).called(1);
|
||||
verify(() => mockDeviceAssetRepository.deleteIds([AssetStub.image1.localId!])).called(1);
|
||||
});
|
||||
|
||||
when(() => mockBackgroundService.digestFiles([file.path])).thenAnswer(
|
||||
@@ -243,14 +213,11 @@ void main() {
|
||||
verify(() => mockBackgroundService.digestFiles([file1.path, file2.path])).called(1);
|
||||
verify(() => mockBackgroundService.digestFiles([file3.path])).called(1);
|
||||
|
||||
expect(
|
||||
result,
|
||||
[
|
||||
AssetStub.image1.copyWith(checksum: base64.encode(hash1)),
|
||||
AssetStub.image2.copyWith(checksum: base64.encode(hash2)),
|
||||
AssetStub.image3.copyWith(checksum: base64.encode(hash3)),
|
||||
],
|
||||
);
|
||||
expect(result, [
|
||||
AssetStub.image1.copyWith(checksum: base64.encode(hash1)),
|
||||
AssetStub.image2.copyWith(checksum: base64.encode(hash2)),
|
||||
AssetStub.image3.copyWith(checksum: base64.encode(hash3)),
|
||||
]);
|
||||
});
|
||||
|
||||
test("processes assets in batches when file limit is reached", () async {
|
||||
@@ -283,14 +250,11 @@ void main() {
|
||||
verify(() => mockBackgroundService.digestFiles([file2.path])).called(1);
|
||||
verify(() => mockBackgroundService.digestFiles([file3.path])).called(1);
|
||||
|
||||
expect(
|
||||
result,
|
||||
[
|
||||
AssetStub.image1.copyWith(checksum: base64.encode(hash1)),
|
||||
AssetStub.image2.copyWith(checksum: base64.encode(hash2)),
|
||||
AssetStub.image3.copyWith(checksum: base64.encode(hash3)),
|
||||
],
|
||||
);
|
||||
expect(result, [
|
||||
AssetStub.image1.copyWith(checksum: base64.encode(hash1)),
|
||||
AssetStub.image2.copyWith(checksum: base64.encode(hash2)),
|
||||
AssetStub.image3.copyWith(checksum: base64.encode(hash3)),
|
||||
]);
|
||||
});
|
||||
|
||||
test("HashService: Sort & Process different states", () async {
|
||||
@@ -345,15 +309,10 @@ void main() {
|
||||
test("handles all file access failures", () async {
|
||||
// No DB entries
|
||||
when(
|
||||
() => mockDeviceAssetRepository.getByIds(
|
||||
[AssetStub.image1.localId!, AssetStub.image2.localId!],
|
||||
),
|
||||
() => mockDeviceAssetRepository.getByIds([AssetStub.image1.localId!, AssetStub.image2.localId!]),
|
||||
).thenAnswer((_) async => []);
|
||||
|
||||
final result = await sut.hashAssets([
|
||||
AssetStub.image1,
|
||||
AssetStub.image2,
|
||||
]);
|
||||
final result = await sut.hashAssets([AssetStub.image1, AssetStub.image2]);
|
||||
|
||||
verifyNever(() => mockBackgroundService.digestFiles(any()));
|
||||
verifyNever(() => mockDeviceAssetRepository.updateAll(any()));
|
||||
@@ -363,9 +322,7 @@ void main() {
|
||||
});
|
||||
}
|
||||
|
||||
Future<(Asset, File, DeviceAsset, Uint8List)> _createAssetMock(
|
||||
Asset asset,
|
||||
) async {
|
||||
Future<(Asset, File, DeviceAsset, Uint8List)> _createAssetMock(Asset asset) async {
|
||||
final random = Random();
|
||||
final hash = Uint8List.fromList(List.generate(20, (i) => random.nextInt(255)));
|
||||
final mockAsset = MockAsset();
|
||||
@@ -384,8 +341,9 @@ Future<(Asset, File, DeviceAsset, Uint8List)> _createAssetMock(
|
||||
when(() => mockAsset.fileName).thenReturn(asset.fileName);
|
||||
when(() => mockAsset.fileCreatedAt).thenReturn(asset.fileCreatedAt);
|
||||
when(() => mockAsset.fileModifiedAt).thenReturn(asset.fileModifiedAt);
|
||||
when(() => mockAsset.copyWith(checksum: any(named: "checksum")))
|
||||
.thenReturn(asset.copyWith(checksum: base64.encode(hash)));
|
||||
when(
|
||||
() => mockAsset.copyWith(checksum: any(named: "checksum")),
|
||||
).thenReturn(asset.copyWith(checksum: base64.encode(hash)));
|
||||
when(() => mockAsset.local).thenAnswer((_) => mockAssetEntity);
|
||||
when(() => mockAssetEntity.originFile).thenAnswer((_) async => file);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user