2023-10-29 09:35:38 +08:00
|
|
|
import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common';
|
2023-06-20 21:08:43 -04:00
|
|
|
import _ from 'lodash';
|
2024-03-20 23:53:07 +01:00
|
|
|
import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto';
|
2024-08-15 06:57:01 -04:00
|
|
|
import { SharedLinkType } from 'src/enum';
|
2024-03-21 00:07:30 +01:00
|
|
|
import { SharedLinkService } from 'src/services/shared-link.service';
|
2024-03-20 19:32:04 +01:00
|
|
|
import { albumStub } from 'test/fixtures/album.stub';
|
|
|
|
|
import { assetStub } from 'test/fixtures/asset.stub';
|
|
|
|
|
import { authStub } from 'test/fixtures/auth.stub';
|
|
|
|
|
import { sharedLinkResponseStub, sharedLinkStub } from 'test/fixtures/shared-link.stub';
|
2025-04-11 11:53:37 -04:00
|
|
|
import { factory } from 'test/small.factory';
|
2025-02-10 18:47:42 -05:00
|
|
|
import { newTestService, ServiceMocks } from 'test/utils';
|
2023-06-01 22:09:57 -04:00
|
|
|
|
|
|
|
|
describe(SharedLinkService.name, () => {
|
|
|
|
|
let sut: SharedLinkService;
|
2025-02-10 18:47:42 -05:00
|
|
|
let mocks: ServiceMocks;
|
2023-06-01 22:09:57 -04:00
|
|
|
|
2024-03-05 23:23:06 +01:00
|
|
|
beforeEach(() => {
|
2025-02-10 18:47:42 -05:00
|
|
|
({ sut, mocks } = newTestService(SharedLinkService));
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work', () => {
|
|
|
|
|
expect(sut).toBeDefined();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('getAll', () => {
|
|
|
|
|
it('should return all shared links for a user', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]);
|
2025-02-07 16:38:20 -05:00
|
|
|
await expect(sut.getAll(authStub.user1, {})).resolves.toEqual([
|
2023-06-01 22:09:57 -04:00
|
|
|
sharedLinkResponseStub.expired,
|
|
|
|
|
sharedLinkResponseStub.valid,
|
|
|
|
|
]);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.getAll).toHaveBeenCalledWith({ userId: authStub.user1.user.id });
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('getMine', () => {
|
|
|
|
|
it('should only work for a public user', async () => {
|
2023-10-29 09:35:38 +08:00
|
|
|
await expect(sut.getMine(authStub.admin, {})).rejects.toBeInstanceOf(ForbiddenException);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).not.toHaveBeenCalled();
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return the shared link for the public user', async () => {
|
|
|
|
|
const authDto = authStub.adminSharedLink;
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.valid);
|
2023-10-29 09:35:38 +08:00
|
|
|
await expect(sut.getMine(authDto, {})).resolves.toEqual(sharedLinkResponseStub.valid);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authDto.user.id, authDto.sharedLink?.id);
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
2023-10-14 03:46:30 +02:00
|
|
|
it('should not return metadata', async () => {
|
2025-04-11 11:53:37 -04:00
|
|
|
const authDto = factory.auth({
|
|
|
|
|
sharedLink: {
|
|
|
|
|
showExif: false,
|
|
|
|
|
allowDownload: true,
|
|
|
|
|
allowUpload: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.readonlyNoExif);
|
2023-10-29 09:35:38 +08:00
|
|
|
await expect(sut.getMine(authDto, {})).resolves.toEqual(sharedLinkResponseStub.readonlyNoMetadata);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authDto.user.id, authDto.sharedLink?.id);
|
2023-10-29 09:35:38 +08:00
|
|
|
});
|
|
|
|
|
|
2024-10-08 23:08:49 +02:00
|
|
|
it('should throw an error for an invalid password protected shared link', async () => {
|
2023-10-29 09:35:38 +08:00
|
|
|
const authDto = authStub.adminSharedLink;
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.passwordRequired);
|
2023-10-29 09:35:38 +08:00
|
|
|
await expect(sut.getMine(authDto, {})).rejects.toBeInstanceOf(UnauthorizedException);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authDto.user.id, authDto.sharedLink?.id);
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
2024-10-08 23:08:49 +02:00
|
|
|
|
|
|
|
|
it('should allow a correct password on a password protected shared link', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue({ ...sharedLinkStub.individual, password: '123' });
|
2024-10-08 23:08:49 +02:00
|
|
|
await expect(sut.getMine(authStub.adminSharedLink, { password: '123' })).resolves.toBeDefined();
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(
|
2024-10-08 23:08:49 +02:00
|
|
|
authStub.adminSharedLink.user.id,
|
|
|
|
|
authStub.adminSharedLink.sharedLink?.id,
|
|
|
|
|
);
|
|
|
|
|
});
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('get', () => {
|
|
|
|
|
it('should throw an error for an invalid shared link', async () => {
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(void 0);
|
|
|
|
|
|
2023-06-01 22:09:57 -04:00
|
|
|
await expect(sut.get(authStub.user1, 'missing-id')).rejects.toBeInstanceOf(BadRequestException);
|
2025-03-10 16:52:44 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authStub.user1.user.id, 'missing-id');
|
|
|
|
|
expect(mocks.sharedLink.update).not.toHaveBeenCalled();
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should get a shared link by id', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.valid);
|
2023-06-01 22:09:57 -04:00
|
|
|
await expect(sut.get(authStub.user1, sharedLinkStub.valid.id)).resolves.toEqual(sharedLinkResponseStub.valid);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authStub.user1.user.id, sharedLinkStub.valid.id);
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2023-06-20 21:08:43 -04:00
|
|
|
describe('create', () => {
|
|
|
|
|
it('should not allow an album shared link without an albumId', async () => {
|
2025-07-15 14:50:13 -04:00
|
|
|
await expect(sut.create(authStub.admin, { type: SharedLinkType.Album, assetIds: [] })).rejects.toBeInstanceOf(
|
2023-06-20 21:08:43 -04:00
|
|
|
BadRequestException,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should not allow non-owners to create album shared links', async () => {
|
|
|
|
|
await expect(
|
2025-07-15 14:50:13 -04:00
|
|
|
sut.create(authStub.admin, { type: SharedLinkType.Album, assetIds: [], albumId: 'album-1' }),
|
2023-06-20 21:08:43 -04:00
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should not allow individual shared links with no assets', async () => {
|
|
|
|
|
await expect(
|
2025-07-15 14:50:13 -04:00
|
|
|
sut.create(authStub.admin, { type: SharedLinkType.Individual, assetIds: [] }),
|
2023-06-20 21:08:43 -04:00
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should require asset ownership to make an individual shared link', async () => {
|
|
|
|
|
await expect(
|
2025-07-15 14:50:13 -04:00
|
|
|
sut.create(authStub.admin, { type: SharedLinkType.Individual, assetIds: ['asset-1'] }),
|
2023-06-20 21:08:43 -04:00
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should create an album shared link', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([albumStub.oneAsset.id]));
|
|
|
|
|
mocks.sharedLink.create.mockResolvedValue(sharedLinkStub.valid);
|
2023-06-20 21:08:43 -04:00
|
|
|
|
2025-07-15 14:50:13 -04:00
|
|
|
await sut.create(authStub.admin, { type: SharedLinkType.Album, albumId: albumStub.oneAsset.id });
|
2023-06-20 21:08:43 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.access.album.checkOwnerAccess).toHaveBeenCalledWith(
|
2023-12-09 23:34:12 -05:00
|
|
|
authStub.admin.user.id,
|
2023-11-25 17:56:23 -05:00
|
|
|
new Set([albumStub.oneAsset.id]),
|
|
|
|
|
);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.create).toHaveBeenCalledWith({
|
2025-07-15 14:50:13 -04:00
|
|
|
type: SharedLinkType.Album,
|
2023-12-09 23:34:12 -05:00
|
|
|
userId: authStub.admin.user.id,
|
2023-06-20 21:08:43 -04:00
|
|
|
albumId: albumStub.oneAsset.id,
|
|
|
|
|
allowDownload: true,
|
|
|
|
|
allowUpload: true,
|
|
|
|
|
description: null,
|
|
|
|
|
expiresAt: null,
|
2025-07-28 14:16:55 -04:00
|
|
|
slug: null,
|
2023-06-20 21:08:43 -04:00
|
|
|
showExif: true,
|
|
|
|
|
key: Buffer.from('random-bytes', 'utf8'),
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should create an individual shared link', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));
|
|
|
|
|
mocks.sharedLink.create.mockResolvedValue(sharedLinkStub.individual);
|
2023-06-20 21:08:43 -04:00
|
|
|
|
|
|
|
|
await sut.create(authStub.admin, {
|
2025-07-15 14:50:13 -04:00
|
|
|
type: SharedLinkType.Individual,
|
2023-07-31 21:28:07 -04:00
|
|
|
assetIds: [assetStub.image.id],
|
2023-10-14 03:46:30 +02:00
|
|
|
showMetadata: true,
|
2023-06-20 21:08:43 -04:00
|
|
|
allowDownload: true,
|
|
|
|
|
allowUpload: true,
|
|
|
|
|
});
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledWith(
|
2023-12-09 23:34:12 -05:00
|
|
|
authStub.admin.user.id,
|
|
|
|
|
new Set([assetStub.image.id]),
|
2025-05-15 09:35:21 -06:00
|
|
|
false,
|
2023-12-09 23:34:12 -05:00
|
|
|
);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.create).toHaveBeenCalledWith({
|
2025-07-15 14:50:13 -04:00
|
|
|
type: SharedLinkType.Individual,
|
2023-12-09 23:34:12 -05:00
|
|
|
userId: authStub.admin.user.id,
|
2023-06-20 21:08:43 -04:00
|
|
|
albumId: null,
|
|
|
|
|
allowDownload: true,
|
2025-07-28 14:16:55 -04:00
|
|
|
slug: null,
|
2023-06-20 21:08:43 -04:00
|
|
|
allowUpload: true,
|
2025-01-18 20:25:15 +01:00
|
|
|
assetIds: [assetStub.image.id],
|
2023-06-20 21:08:43 -04:00
|
|
|
description: null,
|
|
|
|
|
expiresAt: null,
|
|
|
|
|
showExif: true,
|
|
|
|
|
key: Buffer.from('random-bytes', 'utf8'),
|
|
|
|
|
});
|
|
|
|
|
});
|
2024-06-13 09:21:47 -05:00
|
|
|
|
|
|
|
|
it('should create a shared link with allowDownload set to false when showMetadata is false', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));
|
|
|
|
|
mocks.sharedLink.create.mockResolvedValue(sharedLinkStub.individual);
|
2024-06-13 09:21:47 -05:00
|
|
|
|
|
|
|
|
await sut.create(authStub.admin, {
|
2025-07-15 14:50:13 -04:00
|
|
|
type: SharedLinkType.Individual,
|
2024-06-13 09:21:47 -05:00
|
|
|
assetIds: [assetStub.image.id],
|
|
|
|
|
showMetadata: false,
|
|
|
|
|
allowDownload: true,
|
|
|
|
|
allowUpload: true,
|
|
|
|
|
});
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledWith(
|
2024-06-13 09:21:47 -05:00
|
|
|
authStub.admin.user.id,
|
|
|
|
|
new Set([assetStub.image.id]),
|
2025-05-15 09:35:21 -06:00
|
|
|
false,
|
2024-06-13 09:21:47 -05:00
|
|
|
);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.create).toHaveBeenCalledWith({
|
2025-07-15 14:50:13 -04:00
|
|
|
type: SharedLinkType.Individual,
|
2024-06-13 09:21:47 -05:00
|
|
|
userId: authStub.admin.user.id,
|
|
|
|
|
albumId: null,
|
|
|
|
|
allowDownload: false,
|
|
|
|
|
allowUpload: true,
|
2025-01-18 20:25:15 +01:00
|
|
|
assetIds: [assetStub.image.id],
|
2024-06-13 09:21:47 -05:00
|
|
|
description: null,
|
|
|
|
|
expiresAt: null,
|
|
|
|
|
showExif: false,
|
2025-07-28 14:16:55 -04:00
|
|
|
slug: null,
|
2024-06-13 09:21:47 -05:00
|
|
|
key: Buffer.from('random-bytes', 'utf8'),
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-06-20 21:08:43 -04:00
|
|
|
});
|
|
|
|
|
|
2023-06-01 22:09:57 -04:00
|
|
|
describe('update', () => {
|
|
|
|
|
it('should throw an error for an invalid shared link', async () => {
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(void 0);
|
|
|
|
|
|
2023-06-01 22:09:57 -04:00
|
|
|
await expect(sut.update(authStub.user1, 'missing-id', {})).rejects.toBeInstanceOf(BadRequestException);
|
2025-03-10 16:52:44 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authStub.user1.user.id, 'missing-id');
|
|
|
|
|
expect(mocks.sharedLink.update).not.toHaveBeenCalled();
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update a shared link', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
|
mocks.sharedLink.update.mockResolvedValue(sharedLinkStub.valid);
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2023-06-01 22:09:57 -04:00
|
|
|
await sut.update(authStub.user1, sharedLinkStub.valid.id, { allowDownload: false });
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authStub.user1.user.id, sharedLinkStub.valid.id);
|
|
|
|
|
expect(mocks.sharedLink.update).toHaveBeenCalledWith({
|
2023-06-01 22:09:57 -04:00
|
|
|
id: sharedLinkStub.valid.id,
|
2025-07-28 14:16:55 -04:00
|
|
|
slug: null,
|
2023-12-09 23:34:12 -05:00
|
|
|
userId: authStub.user1.user.id,
|
2023-06-01 22:09:57 -04:00
|
|
|
allowDownload: false,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('remove', () => {
|
|
|
|
|
it('should throw an error for an invalid shared link', async () => {
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(void 0);
|
|
|
|
|
|
2023-06-01 22:09:57 -04:00
|
|
|
await expect(sut.remove(authStub.user1, 'missing-id')).rejects.toBeInstanceOf(BadRequestException);
|
2025-03-10 16:52:44 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authStub.user1.user.id, 'missing-id');
|
|
|
|
|
expect(mocks.sharedLink.update).not.toHaveBeenCalled();
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should remove a key', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.valid);
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.sharedLink.remove.mockResolvedValue();
|
|
|
|
|
|
2023-06-01 22:09:57 -04:00
|
|
|
await sut.remove(authStub.user1, sharedLinkStub.valid.id);
|
2025-03-10 16:52:44 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalledWith(authStub.user1.user.id, sharedLinkStub.valid.id);
|
2025-04-18 23:10:34 +02:00
|
|
|
expect(mocks.sharedLink.remove).toHaveBeenCalledWith(sharedLinkStub.valid.id);
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|
|
|
|
|
});
|
2023-06-20 21:08:43 -04:00
|
|
|
|
|
|
|
|
describe('addAssets', () => {
|
|
|
|
|
it('should not work on album shared links', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.valid);
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2023-06-20 21:08:43 -04:00
|
|
|
await expect(sut.addAssets(authStub.admin, 'link-1', { assetIds: ['asset-1'] })).rejects.toBeInstanceOf(
|
|
|
|
|
BadRequestException,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should add assets to a shared link', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(_.cloneDeep(sharedLinkStub.individual));
|
|
|
|
|
mocks.sharedLink.create.mockResolvedValue(sharedLinkStub.individual);
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.sharedLink.update.mockResolvedValue(sharedLinkStub.individual);
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-3']));
|
2023-06-20 21:08:43 -04:00
|
|
|
|
|
|
|
|
await expect(
|
2023-07-31 21:28:07 -04:00
|
|
|
sut.addAssets(authStub.admin, 'link-1', { assetIds: [assetStub.image.id, 'asset-2', 'asset-3'] }),
|
2023-06-20 21:08:43 -04:00
|
|
|
).resolves.toEqual([
|
2023-07-31 21:28:07 -04:00
|
|
|
{ assetId: assetStub.image.id, success: false, error: AssetIdErrorReason.DUPLICATE },
|
2023-06-20 21:08:43 -04:00
|
|
|
{ assetId: 'asset-2', success: false, error: AssetIdErrorReason.NO_PERMISSION },
|
|
|
|
|
{ assetId: 'asset-3', success: true },
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledTimes(1);
|
|
|
|
|
expect(mocks.sharedLink.update).toHaveBeenCalled();
|
|
|
|
|
expect(mocks.sharedLink.update).toHaveBeenCalledWith({
|
2023-06-20 21:08:43 -04:00
|
|
|
...sharedLinkStub.individual,
|
2025-07-28 14:16:55 -04:00
|
|
|
slug: null,
|
2025-01-18 20:25:15 +01:00
|
|
|
assetIds: ['asset-3'],
|
2023-06-20 21:08:43 -04:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('removeAssets', () => {
|
|
|
|
|
it('should not work on album shared links', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.valid);
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2023-06-20 21:08:43 -04:00
|
|
|
await expect(sut.removeAssets(authStub.admin, 'link-1', { assetIds: ['asset-1'] })).rejects.toBeInstanceOf(
|
|
|
|
|
BadRequestException,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should remove assets from a shared link', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(_.cloneDeep(sharedLinkStub.individual));
|
|
|
|
|
mocks.sharedLink.create.mockResolvedValue(sharedLinkStub.individual);
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.sharedLink.update.mockResolvedValue(sharedLinkStub.individual);
|
2025-10-16 21:03:41 +02:00
|
|
|
mocks.sharedLinkAsset.remove.mockResolvedValue([assetStub.image.id]);
|
2023-06-20 21:08:43 -04:00
|
|
|
|
|
|
|
|
await expect(
|
2023-07-31 21:28:07 -04:00
|
|
|
sut.removeAssets(authStub.admin, 'link-1', { assetIds: [assetStub.image.id, 'asset-2'] }),
|
2023-06-20 21:08:43 -04:00
|
|
|
).resolves.toEqual([
|
2023-07-31 21:28:07 -04:00
|
|
|
{ assetId: assetStub.image.id, success: true },
|
2023-06-20 21:08:43 -04:00
|
|
|
{ assetId: 'asset-2', success: false, error: AssetIdErrorReason.NOT_FOUND },
|
|
|
|
|
]);
|
|
|
|
|
|
2025-10-16 21:03:41 +02:00
|
|
|
expect(mocks.sharedLinkAsset.remove).toHaveBeenCalledWith('link-1', [assetStub.image.id, 'asset-2']);
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.update).toHaveBeenCalledWith({ ...sharedLinkStub.individual, assets: [] });
|
2023-06-20 21:08:43 -04:00
|
|
|
});
|
|
|
|
|
});
|
2023-12-11 14:37:47 -05:00
|
|
|
|
|
|
|
|
describe('getMetadataTags', () => {
|
|
|
|
|
it('should return null when auth is not a shared link', async () => {
|
|
|
|
|
await expect(sut.getMetadataTags(authStub.admin)).resolves.toBe(null);
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).not.toHaveBeenCalled();
|
2023-12-11 14:37:47 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return null when shared link has a password', async () => {
|
2025-04-11 11:53:37 -04:00
|
|
|
const auth = factory.auth({ user: {}, sharedLink: { password: 'password' } });
|
|
|
|
|
|
|
|
|
|
await expect(sut.getMetadataTags(auth)).resolves.toBe(null);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).not.toHaveBeenCalled();
|
2023-12-11 14:37:47 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return metadata tags', async () => {
|
2025-02-10 18:47:42 -05:00
|
|
|
mocks.sharedLink.get.mockResolvedValue(sharedLinkStub.individual);
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2023-12-11 14:37:47 -05:00
|
|
|
await expect(sut.getMetadataTags(authStub.adminSharedLink)).resolves.toEqual({
|
|
|
|
|
description: '1 shared photos & videos',
|
2025-03-31 13:08:41 +02:00
|
|
|
imageUrl: `https://my.immich.app/api/assets/asset-id/thumbnail?key=LCtkaJX4R1O_9D-2lq0STzsPryoL1UdAbyb6Sna1xxmQCSuqU2J1ZUsqt6GR-yGm1s0`,
|
2023-12-11 14:37:47 -05:00
|
|
|
title: 'Public Share',
|
|
|
|
|
});
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalled();
|
2023-12-11 14:37:47 -05:00
|
|
|
});
|
2024-10-08 23:08:49 +02:00
|
|
|
|
|
|
|
|
it('should return metadata tags with a default image path if the asset id is not set', async () => {
|
2025-04-18 23:10:34 +02:00
|
|
|
mocks.sharedLink.get.mockResolvedValue({ ...sharedLinkStub.individual, album: null, assets: [] });
|
2024-10-08 23:08:49 +02:00
|
|
|
await expect(sut.getMetadataTags(authStub.adminSharedLink)).resolves.toEqual({
|
|
|
|
|
description: '0 shared photos & videos',
|
2025-03-31 13:08:41 +02:00
|
|
|
imageUrl: `https://my.immich.app/feature-panel.png`,
|
2024-10-08 23:08:49 +02:00
|
|
|
title: 'Public Share',
|
|
|
|
|
});
|
2025-04-11 11:53:37 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.sharedLink.get).toHaveBeenCalled();
|
2024-10-08 23:08:49 +02:00
|
|
|
});
|
2023-12-11 14:37:47 -05:00
|
|
|
});
|
2023-06-01 22:09:57 -04:00
|
|
|
});
|