refactor: medium repository context helpers (#28311)

* refactor: medium repository context helpers

* test: add regress test for 26723

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2026-05-09 20:19:31 +07:00
committed by GitHub
parent 5ba3efafd8
commit faab9e620d
4 changed files with 194 additions and 112 deletions

View File

@@ -33,7 +33,7 @@ void main() {
test('returns single album when only one album exists', () async {
final album = await ctx.newRemoteAlbum(ownerId: userId);
final asset = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 1));
await ctx.insertRemoteAlbumAsset(albumId: album.id, assetId: asset.id);
await ctx.newRemoteAlbumAsset(albumId: album.id, assetId: asset.id);
final result = await sut.getSortedAlbumIds([album.id], aggregation: AssetDateAggregation.start);
expect(result, [album.id]);
@@ -44,22 +44,22 @@ void main() {
final album1 = await ctx.newRemoteAlbum(ownerId: userId);
final asset1 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 10));
final asset2 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 20));
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset2.id);
// Album 2: Assets from Jan 5 to Jan 15 (start: Jan 5)
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset3 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 5));
final asset4 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 15));
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset3.id);
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset4.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset3.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset4.id);
// Album 3: Assets from Jan 25 to Jan 30 (start: Jan 25)
final album3 = await ctx.newRemoteAlbum(ownerId: userId);
final asset5 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 25));
final asset6 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 30));
await ctx.insertRemoteAlbumAsset(albumId: album3.id, assetId: asset5.id);
await ctx.insertRemoteAlbumAsset(albumId: album3.id, assetId: asset6.id);
await ctx.newRemoteAlbumAsset(albumId: album3.id, assetId: asset5.id);
await ctx.newRemoteAlbumAsset(albumId: album3.id, assetId: asset6.id);
final result = await sut.getSortedAlbumIds([
album1.id,
@@ -76,22 +76,22 @@ void main() {
final album1 = await ctx.newRemoteAlbum(ownerId: userId);
final asset1 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 10));
final asset2 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 20));
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset2.id);
// Album 2: Assets from Jan 5 to Jan 15 (end: Jan 15)
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset3 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 5));
final asset4 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 15));
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset3.id);
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset4.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset3.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset4.id);
// Album 3: Assets from Jan 25 to Jan 30 (end: Jan 30)
final album3 = await ctx.newRemoteAlbum(ownerId: userId);
final asset5 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 25));
final asset6 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 30));
await ctx.insertRemoteAlbumAsset(albumId: album3.id, assetId: asset5.id);
await ctx.insertRemoteAlbumAsset(albumId: album3.id, assetId: asset6.id);
await ctx.newRemoteAlbumAsset(albumId: album3.id, assetId: asset5.id);
await ctx.newRemoteAlbumAsset(albumId: album3.id, assetId: asset6.id);
final result = await sut.getSortedAlbumIds([
album1.id,
@@ -106,11 +106,11 @@ void main() {
test('handles albums with single asset', () async {
final album1 = await ctx.newRemoteAlbum(ownerId: userId);
final asset1 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 15));
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset2 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 10));
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
final result = await sut.getSortedAlbumIds([album1.id, album2.id], aggregation: AssetDateAggregation.start);
@@ -121,15 +121,15 @@ void main() {
// Create 3 albums
final album1 = await ctx.newRemoteAlbum(ownerId: userId);
final asset1 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 10));
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset2 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 5));
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
final album3 = await ctx.newRemoteAlbum(ownerId: userId);
final asset3 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 15));
await ctx.insertRemoteAlbumAsset(albumId: album3.id, assetId: asset3.id);
await ctx.newRemoteAlbumAsset(albumId: album3.id, assetId: asset3.id);
// Only request album1 and album3
final result = await sut.getSortedAlbumIds([album1.id, album3.id], aggregation: AssetDateAggregation.start);
@@ -143,11 +143,11 @@ void main() {
final album1 = await ctx.newRemoteAlbum(ownerId: userId);
final asset1 = await ctx.newRemoteAsset(ownerId: userId, createdAt: sameDate);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset2 = await ctx.newRemoteAsset(ownerId: userId, createdAt: sameDate);
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
final result = await sut.getSortedAlbumIds([album1.id, album2.id], aggregation: AssetDateAggregation.start);
@@ -159,15 +159,15 @@ void main() {
test('handles albums across different years', () async {
final album1 = await ctx.newRemoteAlbum(ownerId: userId);
final asset1 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2023, 12, 25));
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset2 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 5));
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset2.id);
final album3 = await ctx.newRemoteAlbum(ownerId: userId);
final asset3 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2025, 1, 1));
await ctx.insertRemoteAlbumAsset(albumId: album3.id, assetId: asset3.id);
await ctx.newRemoteAlbumAsset(albumId: album3.id, assetId: asset3.id);
final result = await sut.getSortedAlbumIds([
album1.id,
@@ -186,15 +186,15 @@ void main() {
final asset3 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 15));
final asset4 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 20));
final asset5 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 25));
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset2.id);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset3.id);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset4.id);
await ctx.insertRemoteAlbumAsset(albumId: album1.id, assetId: asset5.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset1.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset2.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset3.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset4.id);
await ctx.newRemoteAlbumAsset(albumId: album1.id, assetId: asset5.id);
final album2 = await ctx.newRemoteAlbum(ownerId: userId);
final asset6 = await ctx.newRemoteAsset(ownerId: userId, createdAt: DateTime(2024, 1, 1));
await ctx.insertRemoteAlbumAsset(albumId: album2.id, assetId: asset6.id);
await ctx.newRemoteAlbumAsset(albumId: album2.id, assetId: asset6.id);
final resultStart = await sut.getSortedAlbumIds([album1.id, album2.id], aggregation: AssetDateAggregation.start);

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/timeline.model.dart';
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
import 'package:intl/date_symbol_data_local.dart';
import '../repository_context.dart';
@@ -9,6 +9,10 @@ void main() {
late MediumRepositoryContext ctx;
late DriftTimelineRepository sut;
setUpAll(() async {
await initializeDateFormatting();
});
setUp(() {
ctx = MediumRepositoryContext();
sut = DriftTimelineRepository(ctx.db);
@@ -26,16 +30,44 @@ void main() {
final checksum = 'yolo';
final album = await ctx.newRemoteAlbum(ownerId: user.id);
final remoteAsset = await ctx.newRemoteAsset(ownerId: user.id, checksum: checksum);
await ctx.insertRemoteAlbumAsset(albumId: album.id, assetId: remoteAsset.id);
await ctx.newRemoteAlbumAsset(albumId: album.id, assetId: remoteAsset.id);
final localAsset1 = await ctx.newLocalAsset(checksum: checksum);
final localAsset2 = await ctx.newLocalAsset(checksum: checksum);
final assets = await sut.remoteAlbum(album.id, GroupAssetsBy.day).assetSource(0, 10);
final query = sut.remoteAlbum(album.id, .day);
final buckets = await query.bucketSource().first;
expect(buckets, hasLength(1));
expect(buckets.single.assetCount, 1);
final assets = await query.assetSource(0, 10);
expect(assets, hasLength(1));
expect((assets.first as RemoteAsset).id, remoteAsset.id);
expect([localAsset1.id, localAsset2.id], contains((assets.first as RemoteAsset).localId));
});
});
group('person assets', () {
test('does not duplicate an asset that has multiple face records for the same person', () async {
// Regression check for #26723: an INNER JOIN between remote_asset_entity and asset_face_entity
// fanned out one asset into N rows when N face records pointed at the same (asset, person) pair
final user = await ctx.newUser();
final asset = await ctx.newRemoteAsset(ownerId: user.id);
final person = await ctx.newPerson(ownerId: user.id);
await ctx.newFace(assetId: asset.id, personId: person.id);
await ctx.newFace(assetId: asset.id, personId: person.id);
final query = sut.person(user.id, person.id, .day);
final buckets = await query.bucketSource().first;
expect(buckets, hasLength(1));
expect(buckets.single.assetCount, 1);
final assets = await query.assetSource(0, 10);
expect(assets, hasLength(1));
expect((assets.first as RemoteAsset).id, asset.id);
});
});
}

View File

@@ -1,14 +1,14 @@
import 'dart:math';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart';
@@ -23,7 +23,6 @@ import '../utils.dart';
class MediumRepositoryContext {
final Drift db;
final Random _random = Random();
MediumRepositoryContext() : db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true));
@@ -33,7 +32,7 @@ class MediumRepositoryContext {
static Value<T> _resolveUndefined<T>(T? plain, Option<T>? option, T fallback) {
if (plain != null) {
return Value(plain);
return .new(plain);
}
return _resolveOption(option, fallback);
@@ -44,7 +43,7 @@ class MediumRepositoryContext {
return option.fold(Value.new, Value.absent);
}
return Value(fallback);
return .new(fallback);
}
Future<UserEntityData> newUser({
@@ -54,17 +53,17 @@ class MediumRepositoryContext {
DateTime? profileChangedAt,
bool? hasProfileImage,
}) async {
id = TestUtils.uuid(id);
id ??= TestUtils.uuid();
return await db
.into(db.userEntity)
.insertReturning(
UserEntityCompanion(
id: Value(id),
email: Value(email ?? '$id@test.com'),
name: Value(email ?? 'user_$id'),
avatarColor: Value(avatarColor ?? AvatarColor.values[_random.nextInt(AvatarColor.values.length)]),
profileChangedAt: Value(TestUtils.date(profileChangedAt)),
hasProfileImage: Value(hasProfileImage ?? false),
id: .new(id),
email: .new(email ?? '$id@test.com'),
name: .new(email ?? 'user_$id'),
avatarColor: .new(avatarColor ?? TestUtils.randElement(AvatarColor.values)),
profileChangedAt: .new(TestUtils.date(profileChangedAt)),
hasProfileImage: .new(hasProfileImage ?? false),
),
);
}
@@ -88,31 +87,31 @@ class MediumRepositoryContext {
String? thumbHash,
String? libraryId,
}) async {
id = TestUtils.uuid(id);
createdAt = TestUtils.date(createdAt);
id ??= TestUtils.uuid();
createdAt ??= TestUtils.date();
return db
.into(db.remoteAssetEntity)
.insertReturning(
RemoteAssetEntityCompanion(
id: Value(id),
name: Value('remote_$id.jpg'),
checksum: Value(TestUtils.uuid(checksum)),
type: Value(type ?? AssetType.image),
createdAt: Value(createdAt),
updatedAt: Value(TestUtils.date(updatedAt)),
ownerId: Value(TestUtils.uuid(ownerId)),
visibility: Value(visibility ?? AssetVisibility.timeline),
deletedAt: Value(deletedAt),
durationMs: Value(durationMs ?? 0),
width: Value(width ?? _random.nextInt(1000)),
height: Value(height ?? _random.nextInt(1000)),
isFavorite: Value(isFavorite ?? false),
isEdited: Value(isEdited ?? false),
livePhotoVideoId: Value(livePhotoVideoId),
stackId: Value(stackId),
localDateTime: Value(createdAt.toLocal()),
thumbHash: Value(TestUtils.uuid(thumbHash)),
libraryId: Value(TestUtils.uuid(libraryId)),
id: .new(id),
name: .new('remote_$id.jpg'),
checksum: .new(TestUtils.uuid(checksum)),
type: .new(type ?? .image),
createdAt: .new(createdAt),
updatedAt: .new(TestUtils.date(updatedAt)),
ownerId: .new(TestUtils.uuid(ownerId)),
visibility: .new(visibility ?? .timeline),
deletedAt: .new(deletedAt),
durationMs: .new(durationMs ?? 0),
width: .new(width ?? TestUtils.randInt(1000)),
height: .new(height ?? TestUtils.randInt(1000)),
isFavorite: .new(isFavorite ?? false),
isEdited: .new(isEdited ?? false),
livePhotoVideoId: .new(livePhotoVideoId),
stackId: .new(stackId),
localDateTime: .new(createdAt.toLocal()),
thumbHash: .new(TestUtils.uuid(thumbHash)),
libraryId: .new(TestUtils.uuid(libraryId)),
),
);
}
@@ -130,12 +129,12 @@ class MediumRepositoryContext {
.into(db.remoteAssetCloudIdEntity)
.insertReturning(
RemoteAssetCloudIdEntityCompanion(
assetId: Value(TestUtils.uuid(id)),
cloudId: Value(TestUtils.uuid(cloudId)),
createdAt: Value(TestUtils.date(createdAt)),
assetId: .new(TestUtils.uuid(id)),
cloudId: .new(TestUtils.uuid(cloudId)),
createdAt: .new(TestUtils.date(createdAt)),
adjustmentTime: _resolveUndefined(adjustmentTime, adjustmentTimeOption, DateTime.now()),
latitude: _resolveOption(latitude, _random.nextDouble() * 180 - 90),
longitude: _resolveOption(longitude, _random.nextDouble() * 360 - 180),
latitude: _resolveOption(latitude, TestUtils.randDouble(-90, 90)),
longitude: _resolveOption(longitude, TestUtils.randDouble(-180, 180)),
),
);
}
@@ -151,40 +150,81 @@ class MediumRepositoryContext {
AlbumAssetOrder? order,
String? thumbnailAssetId,
}) async {
id = TestUtils.uuid(id);
id ??= TestUtils.uuid();
final album = await db
.into(db.remoteAlbumEntity)
.insertReturning(
RemoteAlbumEntityCompanion(
id: Value(id),
name: Value(name ?? 'remote_album_$id'),
createdAt: Value(TestUtils.date(createdAt)),
updatedAt: Value(TestUtils.date(updatedAt)),
description: Value(description ?? 'Description for album $id'),
isActivityEnabled: Value(isActivityEnabled ?? false),
order: Value(order ?? AlbumAssetOrder.asc),
thumbnailAssetId: Value(thumbnailAssetId),
id: .new(id),
name: .new(name ?? 'remote_album_$id'),
createdAt: .new(TestUtils.date(createdAt)),
updatedAt: .new(TestUtils.date(updatedAt)),
description: .new(description ?? 'Description for album $id'),
isActivityEnabled: .new(isActivityEnabled ?? false),
order: .new(order ?? .asc),
thumbnailAssetId: .new(thumbnailAssetId),
),
);
await db
.into(db.remoteAlbumUserEntity)
.insert(
RemoteAlbumUserEntityCompanion.insert(
albumId: id,
userId: ownerId ?? const Uuid().v4(),
role: AlbumUserRole.owner,
RemoteAlbumUserEntityCompanion(
albumId: .new(id),
userId: .new(TestUtils.uuid(ownerId)),
role: const .new(.owner),
),
);
return album;
}
Future<void> insertRemoteAlbumAsset({required String albumId, required String assetId}) {
Future<void> newRemoteAlbumAsset({required String albumId, required String assetId}) {
return db
.into(db.remoteAlbumAssetEntity)
.insert(RemoteAlbumAssetEntityCompanion.insert(albumId: albumId, assetId: assetId));
.insert(RemoteAlbumAssetEntityCompanion(albumId: .new(albumId), assetId: .new(assetId)));
}
Future<PersonEntityData> newPerson({String? id, String? ownerId, String? name, bool? isFavorite, bool? isHidden}) {
id ??= TestUtils.uuid();
return db
.into(db.personEntity)
.insertReturning(
PersonEntityCompanion(
id: .new(id),
ownerId: .new(TestUtils.uuid(ownerId)),
name: .new(name ?? 'person_$id'),
isFavorite: .new(isFavorite ?? false),
isHidden: .new(isHidden ?? false),
),
);
}
Future<AssetFaceEntityData> newFace({String? assetId, String? personId, int? imageWidth, int? imageHeight}) {
imageWidth ??= TestUtils.randInt(999) + 1;
imageHeight ??= TestUtils.randInt(999) + 1;
final x1 = TestUtils.randInt(imageWidth - 1);
final y1 = TestUtils.randInt(imageHeight - 1);
final x2 = x1 + 1 + TestUtils.randInt(imageWidth - x1 - 1);
final y2 = y1 + 1 + TestUtils.randInt(imageHeight - y1 - 1);
return db
.into(db.assetFaceEntity)
.insertReturning(
AssetFaceEntityCompanion(
id: .new(TestUtils.uuid()),
assetId: .new(TestUtils.uuid(assetId)),
personId: .new(TestUtils.uuid(personId)),
imageWidth: .new(imageWidth),
imageHeight: .new(imageHeight),
boundingBoxX1: .new(x1),
boundingBoxY1: .new(y1),
boundingBoxX2: .new(x2),
boundingBoxY2: .new(y2),
sourceType: const .new('machine-learning'),
),
);
}
Future<LocalAssetEntityData> newLocalAsset({
@@ -206,26 +246,26 @@ class MediumRepositoryContext {
int? orientation,
DateTime? updatedAt,
}) async {
id = TestUtils.uuid(id);
id ??= TestUtils.uuid();
return db
.into(db.localAssetEntity)
.insertReturning(
LocalAssetEntityCompanion(
id: Value(id),
name: Value(name ?? 'local_$id.jpg'),
height: Value(height ?? _random.nextInt(1000)),
width: Value(width ?? _random.nextInt(1000)),
durationMs: Value(durationMs ?? 0),
orientation: Value(orientation ?? 0),
updatedAt: Value(TestUtils.date(updatedAt)),
id: .new(id),
name: .new(name ?? 'local_$id.jpg'),
height: .new(height ?? TestUtils.randInt(1000)),
width: .new(width ?? TestUtils.randInt(1000)),
durationMs: .new(durationMs ?? 0),
orientation: .new(orientation ?? 0),
updatedAt: .new(TestUtils.date(updatedAt)),
checksum: _resolveUndefined(checksum, checksumOption, const Uuid().v4()),
createdAt: Value(TestUtils.date(createdAt)),
type: Value(type ?? AssetType.image),
isFavorite: Value(isFavorite ?? false),
iCloudId: Value(TestUtils.uuid(iCloudId)),
createdAt: .new(TestUtils.date(createdAt)),
type: .new(type ?? .image),
isFavorite: .new(isFavorite ?? false),
iCloudId: .new(TestUtils.uuid(iCloudId)),
adjustmentTime: _resolveUndefined(adjustmentTime, adjustmentTimeOption, DateTime.now()),
latitude: Value(latitude ?? _random.nextDouble() * 180 - 90),
longitude: Value(longitude ?? _random.nextDouble() * 360 - 180),
latitude: .new(latitude ?? TestUtils.randDouble(-90, 90)),
longitude: .new(longitude ?? TestUtils.randDouble(-180, 180)),
),
);
}
@@ -238,24 +278,22 @@ class MediumRepositoryContext {
bool? isIosSharedAlbum,
String? linkedRemoteAlbumId,
}) {
id = TestUtils.uuid(id);
id ??= TestUtils.uuid();
return db
.into(db.localAlbumEntity)
.insertReturning(
LocalAlbumEntityCompanion(
id: Value(id),
name: Value(name ?? 'local_album_$id'),
updatedAt: Value(TestUtils.date(updatedAt)),
backupSelection: Value(backupSelection ?? BackupSelection.none),
isIosSharedAlbum: Value(isIosSharedAlbum ?? false),
linkedRemoteAlbumId: Value(linkedRemoteAlbumId),
id: .new(id),
name: .new(name ?? 'local_album_$id'),
updatedAt: .new(TestUtils.date(updatedAt)),
backupSelection: .new(backupSelection ?? .none),
isIosSharedAlbum: .new(isIosSharedAlbum ?? false),
linkedRemoteAlbumId: .new(linkedRemoteAlbumId),
),
);
}
Future<void> newLocalAlbumAsset({required String albumId, required String assetId}) {
return db
.into(db.localAlbumAssetEntity)
.insert(LocalAlbumAssetEntityCompanion.insert(albumId: albumId, assetId: assetId));
}
Future<void> newLocalAlbumAsset({required String albumId, required String assetId}) => db
.into(db.localAlbumAssetEntity)
.insert(LocalAlbumAssetEntityCompanion(albumId: .new(albumId), assetId: .new(assetId)));
}

View File

@@ -1,10 +1,22 @@
import 'dart:math';
import 'package:uuid/uuid.dart';
class TestUtils {
static final _random = Random();
static String uuid([String? id]) => id ?? const Uuid().v4();
static DateTime date([DateTime? date]) => date ?? DateTime.now();
static DateTime now() => DateTime.now();
static DateTime yesterday() => DateTime.now().subtract(const Duration(days: 1));
static DateTime tomorrow() => DateTime.now().add(const Duration(days: 1));
static T randElement<T>(List<T> list) => list[_random.nextInt(list.length)];
static int randInt([int? max]) => max != null ? _random.nextInt(max) : _random.nextInt(1 << 32);
static double randDouble([int? max, int? min]) {
final minValue = min ?? 0;
final maxValue = max ?? 1;
return minValue + _random.nextDouble() * (maxValue - minValue);
}
}