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:
shenlong
2025-07-29 00:34:03 +05:30
committed by GitHub
parent 9b3718120b
commit e52b9d15b5
643 changed files with 32561 additions and 35292 deletions
+27 -63
View File
@@ -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);
});
+3 -5
View File
@@ -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);
});
});
+24 -60
View File
@@ -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);
});
});
}
+25 -29
View File
@@ -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);
+29 -71
View File
@@ -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);