mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
feat(server): improve and refactor get all albums (#2048)
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import { AlbumEntity, AssetEntity, dataSource, UserEntity } from '@app/infra';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository, Not, IsNull, FindManyOptions } from 'typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { AddAssetsDto } from './dto/add-assets.dto';
|
||||
import { AddUsersDto } from './dto/add-users.dto';
|
||||
import { CreateAlbumDto } from './dto/create-album.dto';
|
||||
import { GetAlbumsDto } from './dto/get-albums.dto';
|
||||
import { RemoveAssetsDto } from './dto/remove-assets.dto';
|
||||
import { UpdateAlbumDto } from './dto/update-album.dto';
|
||||
import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
|
||||
@@ -13,8 +12,6 @@ import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto';
|
||||
|
||||
export interface IAlbumRepository {
|
||||
create(ownerId: string, createAlbumDto: CreateAlbumDto): Promise<AlbumEntity>;
|
||||
getList(ownerId: string, getAlbumsDto: GetAlbumsDto): Promise<AlbumEntity[]>;
|
||||
getPublicSharingList(ownerId: string): Promise<AlbumEntity[]>;
|
||||
get(albumId: string): Promise<AlbumEntity | null>;
|
||||
delete(album: AlbumEntity): Promise<void>;
|
||||
addSharedUsers(album: AlbumEntity, addUsersDto: AddUsersDto): Promise<AlbumEntity>;
|
||||
@@ -23,7 +20,6 @@ export interface IAlbumRepository {
|
||||
addAssets(album: AlbumEntity, addAssetsDto: AddAssetsDto): Promise<AddAssetsResponseDto>;
|
||||
updateAlbum(album: AlbumEntity, updateAlbumDto: UpdateAlbumDto): Promise<AlbumEntity>;
|
||||
updateThumbnails(): Promise<number | undefined>;
|
||||
getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]>;
|
||||
getCountByUserId(userId: string): Promise<AlbumCountResponseDto>;
|
||||
getSharedWithUserAlbumCount(userId: string, assetId: string): Promise<number>;
|
||||
}
|
||||
@@ -40,22 +36,6 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
private assetRepository: Repository<AssetEntity>,
|
||||
) {}
|
||||
|
||||
async getPublicSharingList(ownerId: string): Promise<AlbumEntity[]> {
|
||||
return this.albumRepository.find({
|
||||
relations: {
|
||||
sharedLinks: true,
|
||||
assets: true,
|
||||
owner: true,
|
||||
},
|
||||
where: {
|
||||
ownerId,
|
||||
sharedLinks: {
|
||||
id: Not(IsNull()),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getCountByUserId(userId: string): Promise<AlbumCountResponseDto> {
|
||||
const ownedAlbums = await this.albumRepository.find({ where: { ownerId: userId }, relations: ['sharedUsers'] });
|
||||
const sharedAlbums = await this.albumRepository.count({ where: { sharedUsers: { id: userId } } });
|
||||
@@ -77,59 +57,6 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
return this.get(album.id) as Promise<AlbumEntity>;
|
||||
}
|
||||
|
||||
async getList(ownerId: string, getAlbumsDto: GetAlbumsDto): Promise<AlbumEntity[]> {
|
||||
const filteringByShared = typeof getAlbumsDto.shared == 'boolean';
|
||||
const userId = ownerId;
|
||||
|
||||
const queryProperties: FindManyOptions<AlbumEntity> = {
|
||||
relations: { sharedUsers: true, assets: true, sharedLinks: true, owner: true },
|
||||
select: { assets: { id: true } },
|
||||
order: { createdAt: 'DESC' },
|
||||
};
|
||||
|
||||
let albumsQuery: Promise<AlbumEntity[]>;
|
||||
|
||||
/**
|
||||
* `shared` boolean usage
|
||||
* true = shared with me, and my albums that are shared
|
||||
* false = my albums that are not shared
|
||||
* undefined = all my albums
|
||||
*/
|
||||
if (filteringByShared) {
|
||||
if (getAlbumsDto.shared) {
|
||||
// shared albums
|
||||
albumsQuery = this.albumRepository.find({
|
||||
where: [{ sharedUsers: { id: userId } }, { ownerId: userId, sharedUsers: { id: Not(IsNull()) } }],
|
||||
...queryProperties,
|
||||
});
|
||||
} else {
|
||||
// owned, not shared albums
|
||||
albumsQuery = this.albumRepository.find({
|
||||
where: { ownerId: userId, sharedUsers: { id: IsNull() } },
|
||||
...queryProperties,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// owned
|
||||
albumsQuery = this.albumRepository.find({
|
||||
where: { ownerId: userId },
|
||||
...queryProperties,
|
||||
});
|
||||
}
|
||||
|
||||
return albumsQuery;
|
||||
}
|
||||
|
||||
async getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]> {
|
||||
const albums = await this.albumRepository.find({
|
||||
where: { ownerId: userId },
|
||||
relations: { owner: true, assets: true, sharedUsers: true },
|
||||
order: { assets: { fileCreatedAt: 'ASC' } },
|
||||
});
|
||||
|
||||
return albums.filter((album) => album.assets.some((asset) => asset.id === assetId));
|
||||
}
|
||||
|
||||
async get(albumId: string): Promise<AlbumEntity | null> {
|
||||
return this.albumRepository.findOne({
|
||||
where: { id: albumId },
|
||||
|
||||
@@ -21,7 +21,6 @@ import { AddAssetsDto } from './dto/add-assets.dto';
|
||||
import { AddUsersDto } from './dto/add-users.dto';
|
||||
import { RemoveAssetsDto } from './dto/remove-assets.dto';
|
||||
import { UpdateAlbumDto } from './dto/update-album.dto';
|
||||
import { GetAlbumsDto } from './dto/get-albums.dto';
|
||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { AlbumResponseDto } from '@app/domain';
|
||||
import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
|
||||
@@ -74,15 +73,6 @@ export class AlbumController {
|
||||
return this.albumService.addAssetsToAlbum(authUser, addAssetsDto, albumId);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get()
|
||||
async getAllAlbums(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Query(new ValidationPipe({ transform: true })) query: GetAlbumsDto,
|
||||
) {
|
||||
return this.albumService.getAllAlbums(authUser, query);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@Get('/:albumId')
|
||||
async getAlbumInfo(
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { AlbumService } from './album.service';
|
||||
import { AuthUserDto } from '../../decorators/auth-user.decorator';
|
||||
import { BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common';
|
||||
import { AlbumEntity, AssetEntity, UserEntity } from '@app/infra';
|
||||
import { AlbumEntity, UserEntity } from '@app/infra';
|
||||
import { AlbumResponseDto, ICryptoRepository, IJobRepository, JobName, mapUser } from '@app/domain';
|
||||
import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto';
|
||||
import { IAlbumRepository } from './album-repository';
|
||||
import { DownloadService } from '../../modules/download/download.service';
|
||||
import { ISharedLinkRepository } from '@app/domain';
|
||||
import {
|
||||
assetEntityStub,
|
||||
newCryptoRepositoryMock,
|
||||
newJobRepositoryMock,
|
||||
newSharedLinkRepositoryMock,
|
||||
@@ -119,18 +118,15 @@ describe('Album service', () => {
|
||||
|
||||
beforeAll(() => {
|
||||
albumRepositoryMock = {
|
||||
getPublicSharingList: jest.fn(),
|
||||
addAssets: jest.fn(),
|
||||
addSharedUsers: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
get: jest.fn(),
|
||||
getList: jest.fn(),
|
||||
removeAssets: jest.fn(),
|
||||
removeUser: jest.fn(),
|
||||
updateAlbum: jest.fn(),
|
||||
updateThumbnails: jest.fn(),
|
||||
getListByAssetId: jest.fn(),
|
||||
getCountByUserId: jest.fn(),
|
||||
getSharedWithUserAlbumCount: jest.fn(),
|
||||
};
|
||||
@@ -166,19 +162,6 @@ describe('Album service', () => {
|
||||
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.SEARCH_INDEX_ALBUM, data: { ids: [albumEntity.id] } });
|
||||
});
|
||||
|
||||
it('gets list of albums for auth user', async () => {
|
||||
const ownedAlbum = _getOwnedAlbum();
|
||||
const ownedSharedAlbum = _getOwnedSharedAlbum();
|
||||
const sharedWithMeAlbum = _getSharedWithAuthUserAlbum();
|
||||
const albums: AlbumEntity[] = [ownedAlbum, ownedSharedAlbum, sharedWithMeAlbum];
|
||||
|
||||
albumRepositoryMock.getList.mockImplementation(() => Promise.resolve(albums));
|
||||
|
||||
const result = await sut.getAllAlbums(authUser, {});
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].id).toEqual(ownedAlbum.id);
|
||||
});
|
||||
|
||||
it('gets an owned album', async () => {
|
||||
const albumId = 'f19ab956-4761-41ea-a5d6-bae948308d58';
|
||||
|
||||
@@ -474,76 +457,4 @@ describe('Album service', () => {
|
||||
),
|
||||
).rejects.toBeInstanceOf(ForbiddenException);
|
||||
});
|
||||
|
||||
it('counts assets correctly', async () => {
|
||||
const albumEntity = new AlbumEntity();
|
||||
|
||||
albumEntity.ownerId = authUser.id;
|
||||
albumEntity.owner = albumOwner;
|
||||
albumEntity.id = albumId;
|
||||
albumEntity.albumName = 'name';
|
||||
albumEntity.createdAt = 'date';
|
||||
albumEntity.sharedUsers = [];
|
||||
albumEntity.assets = [
|
||||
{
|
||||
...assetEntityStub.image,
|
||||
id: '3',
|
||||
},
|
||||
];
|
||||
albumEntity.albumThumbnailAssetId = null;
|
||||
|
||||
albumRepositoryMock.getList.mockImplementation(() => Promise.resolve([albumEntity]));
|
||||
|
||||
const result = await sut.getAllAlbums(authUser, {});
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].assetCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('updates the album thumbnail by listing all albums', async () => {
|
||||
const albumEntity = _getOwnedAlbum();
|
||||
const assetEntity = new AssetEntity();
|
||||
const newThumbnailAsset = new AssetEntity();
|
||||
newThumbnailAsset.id = 'e5e65c02-b889-4f3c-afe1-a39a96d578ed';
|
||||
|
||||
albumEntity.albumThumbnailAssetId = 'nonexistent';
|
||||
assetEntity.id = newThumbnailAsset.id;
|
||||
albumEntity.assets = [assetEntity];
|
||||
albumRepositoryMock.getList.mockImplementation(async () => [albumEntity]);
|
||||
albumRepositoryMock.updateThumbnails.mockImplementation(async () => {
|
||||
albumEntity.albumThumbnailAsset = newThumbnailAsset;
|
||||
albumEntity.albumThumbnailAssetId = newThumbnailAsset.id;
|
||||
|
||||
return 1;
|
||||
});
|
||||
|
||||
const result = await sut.getAllAlbums(authUser, {});
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].albumThumbnailAssetId).toEqual(newThumbnailAsset.id);
|
||||
expect(albumRepositoryMock.getList).toHaveBeenCalledTimes(1);
|
||||
expect(albumRepositoryMock.updateThumbnails).toHaveBeenCalledTimes(1);
|
||||
expect(albumRepositoryMock.getList).toHaveBeenCalledWith(albumEntity.ownerId, {});
|
||||
});
|
||||
|
||||
it('removes the thumbnail for an empty album', async () => {
|
||||
const albumEntity = _getOwnedAlbum();
|
||||
|
||||
albumEntity.albumThumbnailAssetId = 'e5e65c02-b889-4f3c-afe1-a39a96d578ed';
|
||||
albumRepositoryMock.getList.mockImplementation(async () => [albumEntity]);
|
||||
albumRepositoryMock.updateThumbnails.mockImplementation(async () => {
|
||||
albumEntity.albumThumbnailAsset = null;
|
||||
albumEntity.albumThumbnailAssetId = null;
|
||||
|
||||
return 1;
|
||||
});
|
||||
|
||||
const result = await sut.getAllAlbums(authUser, {});
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].albumThumbnailAssetId).toBeNull();
|
||||
expect(albumRepositoryMock.getList).toHaveBeenCalledTimes(1);
|
||||
expect(albumRepositoryMock.updateThumbnails).toHaveBeenCalledTimes(1);
|
||||
expect(albumRepositoryMock.getList).toHaveBeenCalledWith(albumEntity.ownerId, {});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,8 +5,7 @@ import { AlbumEntity, SharedLinkType } from '@app/infra';
|
||||
import { AddUsersDto } from './dto/add-users.dto';
|
||||
import { RemoveAssetsDto } from './dto/remove-assets.dto';
|
||||
import { UpdateAlbumDto } from './dto/update-album.dto';
|
||||
import { GetAlbumsDto } from './dto/get-albums.dto';
|
||||
import { AlbumResponseDto, IJobRepository, JobName, mapAlbum, mapAlbumExcludeAssetInfo } from '@app/domain';
|
||||
import { AlbumResponseDto, IJobRepository, JobName, mapAlbum } from '@app/domain';
|
||||
import { IAlbumRepository } from './album-repository';
|
||||
import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
|
||||
import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto';
|
||||
@@ -15,7 +14,6 @@ import { DownloadService } from '../../modules/download/download.service';
|
||||
import { DownloadDto } from '../asset/dto/download-library.dto';
|
||||
import { ShareCore, ISharedLinkRepository, mapSharedLink, SharedLinkResponseDto, ICryptoRepository } from '@app/domain';
|
||||
import { CreateAlbumShareLinkDto } from './dto/create-album-shared-link.dto';
|
||||
import _ from 'lodash';
|
||||
|
||||
@Injectable()
|
||||
export class AlbumService {
|
||||
@@ -63,31 +61,6 @@ export class AlbumService {
|
||||
return mapAlbum(albumEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all shared album, including owned and shared one.
|
||||
* @param authUser AuthUserDto
|
||||
* @returns All Shared Album And Its Members
|
||||
*/
|
||||
async getAllAlbums(authUser: AuthUserDto, getAlbumsDto: GetAlbumsDto): Promise<AlbumResponseDto[]> {
|
||||
await this.albumRepository.updateThumbnails();
|
||||
|
||||
let albums: AlbumEntity[];
|
||||
if (typeof getAlbumsDto.assetId === 'string') {
|
||||
albums = await this.albumRepository.getListByAssetId(authUser.id, getAlbumsDto.assetId);
|
||||
} else {
|
||||
albums = await this.albumRepository.getList(authUser.id, getAlbumsDto);
|
||||
|
||||
if (getAlbumsDto.shared) {
|
||||
const publicSharingAlbums = await this.albumRepository.getPublicSharingList(authUser.id);
|
||||
albums = [...albums, ...publicSharingAlbums];
|
||||
}
|
||||
}
|
||||
|
||||
albums = _.uniqBy(albums, (album) => album.id);
|
||||
|
||||
return albums.map((album) => mapAlbumExcludeAssetInfo(album));
|
||||
}
|
||||
|
||||
async getAlbumInfo(authUser: AuthUserDto, albumId: string): Promise<AlbumResponseDto> {
|
||||
const album = await this._getAlbum({ authUser, albumId, validateIsOwner: false });
|
||||
return mapAlbum(album);
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsOptional } from 'class-validator';
|
||||
import { toBoolean } from '../../../utils/transform.util';
|
||||
|
||||
export class GetAlbumsDto {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@Transform(toBoolean)
|
||||
/**
|
||||
* true: only shared albums
|
||||
* false: only non-shared own albums
|
||||
* undefined: shared and owned albums
|
||||
*/
|
||||
shared?: boolean;
|
||||
|
||||
/**
|
||||
* Only returns albums that contain the asset
|
||||
* Ignores the shared parameter
|
||||
* undefined: get all albums
|
||||
*/
|
||||
assetId?: string;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { TagModule } from './api-v1/tag/tag.module';
|
||||
import { DomainModule, SearchService } from '@app/domain';
|
||||
import { InfraModule } from '@app/infra';
|
||||
import {
|
||||
AlbumController,
|
||||
APIKeyController,
|
||||
AuthController,
|
||||
DeviceInfoController,
|
||||
@@ -35,6 +36,7 @@ import { AppCronJobs } from './app.cron-jobs';
|
||||
],
|
||||
controllers: [
|
||||
AppController,
|
||||
AlbumController,
|
||||
APIKeyController,
|
||||
AuthController,
|
||||
DeviceInfoController,
|
||||
|
||||
21
server/apps/immich/src/controllers/album.controller.ts
Normal file
21
server/apps/immich/src/controllers/album.controller.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { AlbumService, AuthUserDto } from '@app/domain';
|
||||
import { GetAlbumsDto } from '@app/domain/album/dto/get-albums.dto';
|
||||
import { Controller, Get, Query, ValidationPipe } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
|
||||
@ApiTags('Album')
|
||||
@Controller('album')
|
||||
@Authenticated()
|
||||
export class AlbumController {
|
||||
constructor(private service: AlbumService) {}
|
||||
|
||||
@Get()
|
||||
async getAllAlbums(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Query(new ValidationPipe({ transform: true })) query: GetAlbumsDto,
|
||||
) {
|
||||
return this.service.getAllAlbums(authUser, query);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './album.controller';
|
||||
export * from './api-key.controller';
|
||||
export * from './auth.controller';
|
||||
export * from './device-info.controller';
|
||||
|
||||
@@ -3,13 +3,22 @@ import { INestApplication } from '@nestjs/common';
|
||||
import request from 'supertest';
|
||||
import { clearDb, getAuthUser, authCustom } from './test-utils';
|
||||
import { CreateAlbumDto } from '../src/api-v1/album/dto/create-album.dto';
|
||||
import { CreateAlbumShareLinkDto } from '../src/api-v1/album/dto/create-album-shared-link.dto';
|
||||
import { AuthUserDto } from '../src/decorators/auth-user.decorator';
|
||||
import { AuthService, UserService } from '@app/domain';
|
||||
import { AlbumResponseDto, AuthService, SharedLinkResponseDto, UserService } from '@app/domain';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
function _createAlbum(app: INestApplication, data: CreateAlbumDto) {
|
||||
return request(app.getHttpServer()).post('/album').send(data);
|
||||
async function _createAlbum(app: INestApplication, data: CreateAlbumDto) {
|
||||
const res = await request(app.getHttpServer()).post('/album').send(data);
|
||||
expect(res.status).toEqual(201);
|
||||
return res.body as AlbumResponseDto;
|
||||
}
|
||||
|
||||
async function _createAlbumSharedLink(app: INestApplication, data: CreateAlbumShareLinkDto) {
|
||||
const res = await request(app.getHttpServer()).post('/album/create-shared-link').send(data);
|
||||
expect(res.status).toEqual(201);
|
||||
return res.body as SharedLinkResponseDto;
|
||||
}
|
||||
|
||||
describe('Album', () => {
|
||||
@@ -57,30 +66,38 @@ describe('Album', () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
// TODO - Until someone figure out how to passed in a logged in user to the request.
|
||||
// describe('with empty DB', () => {
|
||||
// it('creates an album', async () => {
|
||||
// const data: CreateAlbumDto = {
|
||||
// albumName: 'first albbum',
|
||||
// };
|
||||
describe('with empty DB', () => {
|
||||
it('rejects invalid shared param', async () => {
|
||||
const { status } = await request(app.getHttpServer()).get('/album?shared=invalid');
|
||||
expect(status).toEqual(400);
|
||||
});
|
||||
|
||||
// const { status, body } = await _createAlbum(app, data);
|
||||
it('rejects invalid assetId param', async () => {
|
||||
const { status } = await request(app.getHttpServer()).get('/album?assetId=invalid');
|
||||
expect(status).toEqual(400);
|
||||
});
|
||||
|
||||
// expect(status).toEqual(201);
|
||||
|
||||
// expect(body).toEqual(
|
||||
// expect.objectContaining({
|
||||
// ownerId: authUser.id,
|
||||
// albumName: data.albumName,
|
||||
// }),
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
// TODO - Until someone figure out how to passed in a logged in user to the request.
|
||||
// it('creates an album', async () => {
|
||||
// const data: CreateAlbumDto = {
|
||||
// albumName: 'first albbum',
|
||||
// };
|
||||
// const body = await _createAlbum(app, data);
|
||||
// expect(body).toEqual(
|
||||
// expect.objectContaining({
|
||||
// ownerId: authUser.id,
|
||||
// albumName: data.albumName,
|
||||
// }),
|
||||
// );
|
||||
// });
|
||||
});
|
||||
|
||||
describe('with albums in DB', () => {
|
||||
const userOneShared = 'userOneShared';
|
||||
const userOneSharedUser = 'userOneSharedUser';
|
||||
const userOneSharedLink = 'userOneSharedLink';
|
||||
const userOneNotShared = 'userOneNotShared';
|
||||
const userTwoShared = 'userTwoShared';
|
||||
const userTwoSharedUser = 'userTwoSharedUser';
|
||||
const userTwoSharedLink = 'userTwoSharedLink';
|
||||
const userTwoNotShared = 'userTwoNotShared';
|
||||
let userOne: AuthUserDto;
|
||||
let userTwo: AuthUserDto;
|
||||
@@ -104,16 +121,26 @@ describe('Album', () => {
|
||||
|
||||
// add user one albums
|
||||
authUser = userOne;
|
||||
await Promise.all([
|
||||
_createAlbum(app, { albumName: userOneShared, sharedWithUserIds: [userTwo.id] }),
|
||||
const userOneAlbums = await Promise.all([
|
||||
_createAlbum(app, { albumName: userOneSharedUser, sharedWithUserIds: [userTwo.id] }),
|
||||
_createAlbum(app, { albumName: userOneSharedLink }),
|
||||
_createAlbum(app, { albumName: userOneNotShared }),
|
||||
]);
|
||||
|
||||
// add shared link to userOneSharedLink album
|
||||
await _createAlbumSharedLink(app, { albumId: userOneAlbums[1].id });
|
||||
|
||||
// add user two albums
|
||||
authUser = userTwo;
|
||||
await Promise.all([
|
||||
_createAlbum(app, { albumName: userTwoShared, sharedWithUserIds: [userOne.id] }),
|
||||
const userTwoAlbums = await Promise.all([
|
||||
_createAlbum(app, { albumName: userTwoSharedUser, sharedWithUserIds: [userOne.id] }),
|
||||
_createAlbum(app, { albumName: userTwoSharedLink }),
|
||||
_createAlbum(app, { albumName: userTwoNotShared }),
|
||||
]);
|
||||
|
||||
// add shared link to userTwoSharedLink album
|
||||
await _createAlbumSharedLink(app, { albumId: userTwoAlbums[1].id });
|
||||
|
||||
// set user one as authed for next requests
|
||||
authUser = userOne;
|
||||
});
|
||||
@@ -125,10 +152,11 @@ describe('Album', () => {
|
||||
it('returns the album collection including owned and shared', async () => {
|
||||
const { status, body } = await request(app.getHttpServer()).get('/album');
|
||||
expect(status).toEqual(200);
|
||||
expect(body).toHaveLength(2);
|
||||
expect(body).toHaveLength(3);
|
||||
expect(body).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneShared, shared: true }),
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneSharedUser, shared: true }),
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneSharedLink, shared: true }),
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneNotShared, shared: false }),
|
||||
]),
|
||||
);
|
||||
@@ -137,11 +165,12 @@ describe('Album', () => {
|
||||
it('returns the album collection filtered by shared', async () => {
|
||||
const { status, body } = await request(app.getHttpServer()).get('/album?shared=true');
|
||||
expect(status).toEqual(200);
|
||||
expect(body).toHaveLength(2);
|
||||
expect(body).toHaveLength(3);
|
||||
expect(body).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneShared, shared: true }),
|
||||
expect.objectContaining({ ownerId: userTwo.id, albumName: userTwoShared, shared: true }),
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneSharedUser, shared: true }),
|
||||
expect.objectContaining({ ownerId: userOne.id, albumName: userOneSharedLink, shared: true }),
|
||||
expect.objectContaining({ ownerId: userTwo.id, albumName: userTwoSharedUser, shared: true }),
|
||||
]),
|
||||
);
|
||||
});
|
||||
@@ -156,6 +185,33 @@ describe('Album', () => {
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
// TODO: Add asset to album and test if it returns correctly.
|
||||
it('returns the album collection filtered by assetId', async () => {
|
||||
const { status, body } = await request(app.getHttpServer()).get(
|
||||
'/album?assetId=ecb120db-45a2-4a65-9293-51476f0d8790',
|
||||
);
|
||||
expect(status).toEqual(200);
|
||||
expect(body).toHaveLength(0);
|
||||
});
|
||||
|
||||
// TODO: Add asset to album and test if it returns correctly.
|
||||
it('returns the album collection filtered by assetId and ignores shared=true', async () => {
|
||||
const { status, body } = await request(app.getHttpServer()).get(
|
||||
'/album?shared=true&assetId=ecb120db-45a2-4a65-9293-51476f0d8790',
|
||||
);
|
||||
expect(status).toEqual(200);
|
||||
expect(body).toHaveLength(0);
|
||||
});
|
||||
|
||||
// TODO: Add asset to album and test if it returns correctly.
|
||||
it('returns the album collection filtered by assetId and ignores shared=false', async () => {
|
||||
const { status, body } = await request(app.getHttpServer()).get(
|
||||
'/album?shared=false&assetId=ecb120db-45a2-4a65-9293-51476f0d8790',
|
||||
);
|
||||
expect(status).toEqual(200);
|
||||
expect(body).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user