better query, add medium test

This commit is contained in:
mertalev 2025-10-16 17:35:39 -04:00
parent ce10c27d7a
commit 2879ded8b0
No known key found for this signature in database
GPG key ID: DF6ABC77AAD98C95
2 changed files with 54 additions and 16 deletions

View file

@ -592,7 +592,7 @@ export class AssetRepository {
@GenerateSql({
params: [DummyValue.TIME_BUCKET, { withStacked: true }],
})
getTimeBucket(timeBucket: string, options: TimeBucketOptions, auth?: AuthDto) {
getTimeBucket(timeBucket: string, options: TimeBucketOptions, auth: AuthDto) {
const query = this.db
.with('cte', (qb) =>
qb
@ -602,7 +602,7 @@ export class AssetRepository {
'asset.duration',
'asset.id',
'asset.visibility',
'asset.isFavorite',
sql`asset."isFavorite" and asset."ownerId" = ${auth.user.id}`.as('isFavorite'),
sql`asset.type = 'IMAGE'`.as('isImage'),
sql`asset."deletedAt" is not null`.as('isTrashed'),
'asset.livePhotoVideoId',
@ -691,19 +691,7 @@ export class AssetRepository {
eb.fn.coalesce(eb.fn('array_agg', ['duration']), sql.lit('{}')).as('duration'),
eb.fn.coalesce(eb.fn('array_agg', ['id']), sql.lit('{}')).as('id'),
eb.fn.coalesce(eb.fn('array_agg', ['visibility']), sql.lit('{}')).as('visibility'),
eb.fn
.coalesce(
eb.fn('array_agg', [
eb
.case()
.when(eb.ref('ownerId'), '=', auth?.user.id || '')
.then(eb.ref('isFavorite'))
.else(sql.lit(false))
.end(),
]),
sql.lit('{}'),
)
.as('isFavorite'),
eb.fn.coalesce(eb.fn('array_agg', ['isFavorite']), sql.lit('{}')).as('isFavorite'),
eb.fn.coalesce(eb.fn('array_agg', ['isImage']), sql.lit('{}')).as('isImage'),
// TODO: isTrashed is redundant as it will always be all true or false depending on the options
eb.fn.coalesce(eb.fn('array_agg', ['isTrashed']), sql.lit('{}')).as('isTrashed'),

View file

@ -4,6 +4,7 @@ import { AssetVisibility } from 'src/enum';
import { AccessRepository } from 'src/repositories/access.repository';
import { AssetRepository } from 'src/repositories/asset.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { PartnerRepository } from 'src/repositories/partner.repository';
import { DB } from 'src/schema';
import { TimelineService } from 'src/services/timeline.service';
import { newMediumService } from 'test/medium.factory';
@ -15,7 +16,7 @@ let defaultDatabase: Kysely<DB>;
const setup = (db?: Kysely<DB>) => {
return newMediumService(TimelineService, {
database: db || defaultDatabase,
real: [AssetRepository, AccessRepository],
real: [AssetRepository, AccessRepository, PartnerRepository],
mock: [LoggingRepository],
});
};
@ -155,5 +156,54 @@ describe(TimelineService.name, () => {
const response = JSON.parse(rawResponse);
expect(response).toEqual(expect.objectContaining({ isTrashed: [true] }));
});
it('should return false for favorite status unless asset owner', async () => {
const { sut, ctx } = setup();
const [{ asset: asset1 }, { asset: asset2 }] = await Promise.all([
ctx.newUser().then(async ({ user }) => {
const result = await ctx.newAsset({
ownerId: user.id,
fileCreatedAt: new Date('1970-02-12'),
localDateTime: new Date('1970-02-12'),
isFavorite: true,
});
await ctx.newExif({ assetId: result.asset.id, make: 'Canon' });
return result;
}),
ctx.newUser().then(async ({ user }) => {
const result = await ctx.newAsset({
ownerId: user.id,
fileCreatedAt: new Date('1970-02-13'),
localDateTime: new Date('1970-02-13'),
isFavorite: true,
});
await ctx.newExif({ assetId: result.asset.id, make: 'Canon' });
return result;
}),
]);
await Promise.all([
ctx.newPartner({ sharedById: asset1.ownerId, sharedWithId: asset2.ownerId }),
ctx.newPartner({ sharedById: asset2.ownerId, sharedWithId: asset1.ownerId }),
]);
const auth1 = factory.auth({ user: { id: asset1.ownerId } });
const rawResponse1 = await sut.getTimeBucket(auth1, {
timeBucket: '1970-02-01',
withPartners: true,
visibility: AssetVisibility.Timeline,
});
const response1 = JSON.parse(rawResponse1);
expect(response1).toEqual(expect.objectContaining({ id: [asset2.id, asset1.id], isFavorite: [false, true] }));
const auth2 = factory.auth({ user: { id: asset2.ownerId } });
const rawResponse2 = await sut.getTimeBucket(auth2, {
timeBucket: '1970-02-01',
withPartners: true,
visibility: AssetVisibility.Timeline,
});
const response2 = JSON.parse(rawResponse2);
expect(response2).toEqual(expect.objectContaining({ id: [asset2.id, asset1.id], isFavorite: [true, false] }));
});
});
});