Skip to content

Commit

Permalink
fix test
Browse files Browse the repository at this point in the history
  • Loading branch information
mertalev committed Apr 21, 2024
1 parent 6b25652 commit ae60e19
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 137 deletions.
6 changes: 6 additions & 0 deletions server/src/services/asset.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,20 @@ describe(AssetService.name, () => {
it('should update the asset', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
assetMock.getById.mockResolvedValue(assetStub.image);
assetMock.update.mockResolvedValue(assetStub.image);

await sut.update(authStub.admin, 'asset-1', { isFavorite: true });

expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-1', isFavorite: true });
});

it('should update the exif description', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
assetMock.getById.mockResolvedValue(assetStub.image);
assetMock.update.mockResolvedValue(assetStub.image);

await sut.update(authStub.admin, 'asset-1', { description: 'Test description' });

expect(assetMock.upsertExif).toHaveBeenCalledWith({ assetId: 'asset-1', description: 'Test description' });
});
});
Expand Down
115 changes: 0 additions & 115 deletions server/src/services/search.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,119 +97,4 @@ describe(SearchService.name, () => {
expect(result).toEqual(expectedResponse);
});
});

describe('search', () => {
it('should throw an error if query is missing', async () => {
await expect(sut.search(authStub.user1, { q: '' })).rejects.toThrow('Missing query');
});

it('should search by metadata if `clip` option is false', async () => {
const dto: SearchDto = { q: 'test query', clip: false };
assetMock.searchMetadata.mockResolvedValueOnce([assetStub.image]);
partnerMock.getAll.mockResolvedValueOnce([]);
const expectedResponse = {
albums: {
total: 0,
count: 0,
items: [],
facets: [],
},
assets: {
total: 1,
count: 1,
items: [mapAsset(assetStub.image)],
facets: [],
nextPage: null,
},
};

const result = await sut.search(authStub.user1, dto);

expect(result).toEqual(expectedResponse);
expect(assetMock.searchMetadata).toHaveBeenCalledWith(dto.q, [authStub.user1.user.id], { numResults: 250 });
expect(searchMock.searchSmart).not.toHaveBeenCalled();
});

it('should search archived photos if `withArchived` option is true', async () => {
const dto: SearchDto = { q: 'test query', clip: true, withArchived: true };
const embedding = [1, 2, 3];
searchMock.searchSmart.mockResolvedValueOnce({ items: [assetStub.image], hasNextPage: false });
machineMock.encodeText.mockResolvedValueOnce(embedding);
partnerMock.getAll.mockResolvedValueOnce([]);
const expectedResponse = {
albums: {
total: 0,
count: 0,
items: [],
facets: [],
},
assets: {
total: 1,
count: 1,
items: [mapAsset(assetStub.image)],
facets: [],
nextPage: null,
},
};

const result = await sut.search(authStub.user1, dto);

expect(result).toEqual(expectedResponse);
expect(searchMock.searchSmart).toHaveBeenCalledWith(
{ page: 1, size: 100 },
{
userIds: [authStub.user1.user.id],
embedding,
withArchived: true,
},
);
expect(assetMock.searchMetadata).not.toHaveBeenCalled();
});

it('should search by CLIP if `clip` option is true', async () => {
const dto: SearchDto = { q: 'test query', clip: true };
const embedding = [1, 2, 3];
searchMock.searchSmart.mockResolvedValueOnce({ items: [assetStub.image], hasNextPage: false });
machineMock.encodeText.mockResolvedValueOnce(embedding);
partnerMock.getAll.mockResolvedValueOnce([]);
const expectedResponse = {
albums: {
total: 0,
count: 0,
items: [],
facets: [],
},
assets: {
total: 1,
count: 1,
items: [mapAsset(assetStub.image)],
facets: [],
nextPage: null,
},
};

const result = await sut.search(authStub.user1, dto);

expect(result).toEqual(expectedResponse);
expect(searchMock.searchSmart).toHaveBeenCalledWith(
{ page: 1, size: 100 },
{
userIds: [authStub.user1.user.id],
embedding,
withArchived: false,
},
);
expect(assetMock.searchMetadata).not.toHaveBeenCalled();
});

it.each([
{ key: SystemConfigKey.MACHINE_LEARNING_ENABLED },
{ key: SystemConfigKey.MACHINE_LEARNING_CLIP_ENABLED },
])('should throw an error if clip is requested but disabled', async ({ key }) => {
const dto: SearchDto = { q: 'test query', clip: true };
configMock.load.mockResolvedValue([{ key, value: false }]);

await expect(sut.search(authStub.user1, dto)).rejects.toThrow('Smart search is not enabled');
});
});
});
30 changes: 19 additions & 11 deletions server/src/services/timeline.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IPartnerRepository } from 'src/interfaces/partner.interface';
import { TimelineService } from 'src/services/timeline.service';
import { assetStub } from 'test/fixtures/asset.stub';
import { authStub } from 'test/fixtures/auth.stub';
import { partnerStub } from 'test/fixtures/partner.stub';
import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock';
import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock';
Expand Down Expand Up @@ -52,6 +53,7 @@ describe(TimelineService.name, () => {
size: TimeBucketSize.DAY,
timeBucket: 'bucket',
albumId: 'album-id',
userIds: [authStub.admin.user.id],
});
});

Expand All @@ -66,12 +68,15 @@ describe(TimelineService.name, () => {
userId: authStub.admin.user.id,
}),
).resolves.toEqual(expect.arrayContaining([expect.objectContaining({ id: 'asset-id' })]));
expect(assetMock.getTimeBucket).toHaveBeenCalledWith('bucket', {
size: TimeBucketSize.DAY,
timeBucket: 'bucket',
isArchived: true,
userIds: [authStub.admin.user.id],
});
expect(assetMock.getTimeBucket).toHaveBeenCalledWith(
'bucket',
expect.objectContaining({
size: TimeBucketSize.DAY,
timeBucket: 'bucket',
isArchived: true,
userIds: [authStub.admin.user.id],
}),
);
});

it('should return the assets for a library time bucket if user has library.read', async () => {
Expand All @@ -84,11 +89,14 @@ describe(TimelineService.name, () => {
userId: authStub.admin.user.id,
}),
).resolves.toEqual(expect.arrayContaining([expect.objectContaining({ id: 'asset-id' })]));
expect(assetMock.getTimeBucket).toHaveBeenCalledWith('bucket', {
size: TimeBucketSize.DAY,
timeBucket: 'bucket',
userIds: [authStub.admin.user.id],
});
expect(assetMock.getTimeBucket).toHaveBeenCalledWith(
'bucket',
expect.objectContaining({
size: TimeBucketSize.DAY,
timeBucket: 'bucket',
userIds: [authStub.admin.user.id],
}),
);
});

it('should throw an error if withParners is true and isArchived true or undefined', async () => {
Expand Down
26 changes: 15 additions & 11 deletions server/src/services/timeline.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ export class TimelineService {
}

async getTimeBuckets(auth: AuthDto, dto: TimeBucketDto): Promise<TimeBucketResponseDto[]> {
await this.validateDto(auth, dto);
const userIds = await this.getUserIds(auth, dto);
await this.timeBucketChecks(auth, dto, userIds);
await this.checkPermission(auth, dto, userIds);

return this.repository.getTimeBuckets({ ...dto, userIds });
}
Expand All @@ -29,27 +30,20 @@ export class TimelineService {
auth: AuthDto,
dto: TimeBucketAssetDto,
): Promise<AssetResponseDto[] | SanitizedAssetResponseDto[]> {
await this.validateDto(auth, dto);
const userIds = await this.getUserIds(auth, dto);
await this.timeBucketChecks(auth, dto, userIds);
await this.checkPermission(auth, dto, userIds);
const assets = await this.repository.getTimeBucket(dto.timeBucket, { ...dto, userIds });
return !auth.sharedLink || auth.sharedLink?.showExif
? assets.map((asset) => mapAsset(asset, { withStack: true, auth }))
: assets.map((asset) => mapAsset(asset, { stripMetadata: true, auth }));
}

private async timeBucketChecks(auth: AuthDto, dto: TimeBucketDto, userIds: string[]) {
private async validateDto(auth: AuthDto, dto: TimeBucketDto) {
if (dto.albumId) {
await this.accessCore.requirePermission(auth, Permission.ALBUM_READ, [dto.albumId]);
}

const sharedUsers = userIds.filter((id) => id !== auth.user.id);
if (sharedUsers.length > 0) {
await this.accessCore.requirePermission(auth, Permission.TIMELINE_READ, sharedUsers);
if (dto.isArchived !== false) {
await this.accessCore.requirePermission(auth, Permission.ARCHIVE_READ, sharedUsers);
}
}

if (dto.withPartners) {
const requestedArchived = dto.isArchived === true || dto.isArchived === undefined;
const requestedFavorite = dto.isFavorite === true || dto.isFavorite === false;
Expand Down Expand Up @@ -77,4 +71,14 @@ export class TimelineService {

return userIds;
}

private async checkPermission(auth: AuthDto, dto: TimeBucketDto, userIds: string[]) {
const sharedUsers = userIds.filter((id) => id !== auth.user.id);
if (sharedUsers.length > 0) {
await this.accessCore.requirePermission(auth, Permission.TIMELINE_READ, sharedUsers);
if (dto.isArchived !== false) {
await this.accessCore.requirePermission(auth, Permission.ARCHIVE_READ, sharedUsers);
}
}
}
}

0 comments on commit ae60e19

Please sign in to comment.