mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-12-08 20:29:05 +00:00
feat(server,web): libraries (#3124)
* feat: libraries Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
committed by
GitHub
parent
816db700e1
commit
acdc66413c
@@ -106,16 +106,16 @@ describe(`${AlbumController.name} (e2e)`, () => {
|
||||
const { status, body } = await request(server)
|
||||
.get('/album?shared=invalid')
|
||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(status).toEqual(400);
|
||||
expect(body).toEqual(errorStub.badRequest(['shared must be a boolean value']));
|
||||
});
|
||||
|
||||
it('should reject an invalid assetId param', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.get('/album?assetId=invalid')
|
||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(status).toEqual(400);
|
||||
expect(body).toEqual(errorStub.badRequest(['assetId must be a UUID']));
|
||||
});
|
||||
|
||||
it('should not return shared albums with a deleted owner', async () => {
|
||||
@@ -413,7 +413,7 @@ describe(`${AlbumController.name} (e2e)`, () => {
|
||||
.send({ sharedUserIds: [user1.userId] });
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual({ ...errorStub.badRequest, message: 'Cannot be shared with owner' });
|
||||
expect(body).toEqual(errorStub.badRequest('Cannot be shared with owner'));
|
||||
});
|
||||
|
||||
it('should not be able to add existing user to shared album', async () => {
|
||||
@@ -428,7 +428,7 @@ describe(`${AlbumController.name} (e2e)`, () => {
|
||||
.send({ sharedUserIds: [user2.userId] });
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual({ ...errorStub.badRequest, message: 'User already added' });
|
||||
expect(body).toEqual(errorStub.badRequest('User already added'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,6 +45,7 @@ let assetCount = 0;
|
||||
const createAsset = (
|
||||
repository: IAssetRepository,
|
||||
loginResponse: LoginResponseDto,
|
||||
libraryId: string,
|
||||
createdAt: Date,
|
||||
): Promise<AssetEntity> => {
|
||||
const id = assetCount++;
|
||||
@@ -54,6 +55,7 @@ const createAsset = (
|
||||
originalPath: `/tests/test_${id}`,
|
||||
deviceAssetId: `test_${id}`,
|
||||
deviceId: 'e2e-test',
|
||||
libraryId,
|
||||
fileCreatedAt: createdAt,
|
||||
fileModifiedAt: new Date(),
|
||||
type: AssetType.IMAGE,
|
||||
@@ -87,15 +89,19 @@ describe(`${AssetController.name} (e2e)`, () => {
|
||||
await api.authApi.adminSignUp(server);
|
||||
const admin = await api.authApi.adminLogin(server);
|
||||
|
||||
const libraries = await api.libraryApi.getAll(server, admin.accessToken);
|
||||
const defaultLibrary = libraries[0];
|
||||
|
||||
await api.userApi.create(server, admin.accessToken, user1Dto);
|
||||
user1 = await api.authApi.login(server, { email: user1Dto.email, password: user1Dto.password });
|
||||
asset1 = await createAsset(assetRepository, user1, new Date('1970-01-01'));
|
||||
asset2 = await createAsset(assetRepository, user1, new Date('1970-01-02'));
|
||||
asset3 = await createAsset(assetRepository, user1, new Date('1970-02-01'));
|
||||
|
||||
asset1 = await createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-01-01'));
|
||||
asset2 = await createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-01-02'));
|
||||
asset3 = await createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-02-01'));
|
||||
|
||||
await api.userApi.create(server, admin.accessToken, user2Dto);
|
||||
user2 = await api.authApi.login(server, { email: user2Dto.email, password: user2Dto.password });
|
||||
asset4 = await createAsset(assetRepository, user2, new Date('1970-01-01'));
|
||||
asset4 = await createAsset(assetRepository, user2, defaultLibrary.id, new Date('1970-01-01'));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -139,7 +145,7 @@ describe(`${AssetController.name} (e2e)`, () => {
|
||||
.attach('assetData', randomBytes(32), 'example.jpg')
|
||||
.field(dto);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -192,7 +198,7 @@ describe(`${AssetController.name} (e2e)`, () => {
|
||||
.put(`/asset/${uuidStub.invalid}`)
|
||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest(['id must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require access', async () => {
|
||||
|
||||
@@ -52,18 +52,33 @@ describe(`${AuthController.name} (e2e)`, () => {
|
||||
});
|
||||
|
||||
const invalid = [
|
||||
{ should: 'require an email address', data: { firstName, lastName, password } },
|
||||
{ should: 'require a password', data: { firstName, lastName, email } },
|
||||
{ should: 'require a first name ', data: { lastName, email, password } },
|
||||
{ should: 'require a last name ', data: { firstName, email, password } },
|
||||
{ should: 'require a valid email', data: { firstName, lastName, email: 'immich', password } },
|
||||
{
|
||||
should: 'require an email address',
|
||||
data: { firstName, lastName, password },
|
||||
},
|
||||
{
|
||||
should: 'require a password',
|
||||
data: { firstName, lastName, email },
|
||||
},
|
||||
{
|
||||
should: 'require a first name ',
|
||||
data: { lastName, email, password },
|
||||
},
|
||||
{
|
||||
should: 'require a last name ',
|
||||
data: { firstName, email, password },
|
||||
},
|
||||
{
|
||||
should: 'require a valid email',
|
||||
data: { firstName, lastName, email: 'immich', password },
|
||||
},
|
||||
];
|
||||
|
||||
for (const { should, data } of invalid) {
|
||||
it(`should ${should}`, async () => {
|
||||
const { status, body } = await request(server).post('/auth/admin-sign-up').send(data);
|
||||
expect(status).toEqual(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -102,7 +117,7 @@ describe(`${AuthController.name} (e2e)`, () => {
|
||||
.post('/auth/admin-sign-up')
|
||||
.send({ ...adminSignupStub, [key]: null });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -120,7 +135,7 @@ describe(`${AuthController.name} (e2e)`, () => {
|
||||
.post('/auth/login')
|
||||
.send({ ...loginStub.admin, [key]: null });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,7 +240,7 @@ describe(`${AuthController.name} (e2e)`, () => {
|
||||
.send({ ...changePasswordStub, [key]: null })
|
||||
.set('Authorization', `Bearer ${accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
494
server/test/e2e/library.e2e-spec.ts
Normal file
494
server/test/e2e/library.e2e-spec.ts
Normal file
@@ -0,0 +1,494 @@
|
||||
import { LoginResponseDto } from '@app/domain';
|
||||
import { AppModule, LibraryController } from '@app/immich';
|
||||
import { LibraryType } from '@app/infra/entities';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import request from 'supertest';
|
||||
import { errorStub, userStub, uuidStub } from '../fixtures';
|
||||
import { api, db } from '../test-utils';
|
||||
|
||||
describe(`${LibraryController.name} (e2e)`, () => {
|
||||
let app: INestApplication;
|
||||
let server: any;
|
||||
let loginResponse: LoginResponseDto;
|
||||
let accessToken: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = await moduleFixture.createNestApplication().init();
|
||||
server = app.getHttpServer();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.reset();
|
||||
await api.adminSignUp(server);
|
||||
loginResponse = await api.adminLogin(server);
|
||||
accessToken = loginResponse.accessToken;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await db.disconnect();
|
||||
await app.close();
|
||||
});
|
||||
|
||||
describe('GET /library', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).get('/library');
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
it('should start with a default upload library', async () => {
|
||||
const { status, body } = await request(server).get('/library').set('Authorization', `Bearer ${accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toHaveLength(1);
|
||||
expect(body).toEqual([
|
||||
{
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.UPLOAD,
|
||||
name: 'Default Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /library', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).post('/library').send({});
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
describe('external library', () => {
|
||||
it('with default settings', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL });
|
||||
expect(status).toBe(201);
|
||||
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New External Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('with name', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL, name: 'My Awesome Library' });
|
||||
expect(status).toBe(201);
|
||||
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'My Awesome Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('with import paths', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL, importPaths: ['/path/to/import'] });
|
||||
expect(status).toBe(201);
|
||||
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New External Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: ['/path/to/import'],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('with exclusion patterns', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL, exclusionPatterns: ['**/Raw/**'] });
|
||||
expect(status).toBe(201);
|
||||
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New External Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: ['**/Raw/**'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('upload library', () => {
|
||||
it('with default settings', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.UPLOAD });
|
||||
expect(status).toBe(201);
|
||||
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.UPLOAD,
|
||||
name: 'New Upload Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('with name', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.UPLOAD, name: 'My Awesome Library' });
|
||||
expect(status).toBe(201);
|
||||
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.UPLOAD,
|
||||
name: 'My Awesome Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('with import paths should fail', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.UPLOAD, importPaths: ['/path/to/import'] });
|
||||
expect(status).toBe(400);
|
||||
|
||||
expect(body).toEqual(errorStub.badRequest('Upload libraries cannot have import paths'));
|
||||
});
|
||||
|
||||
it('with exclusion patterns should fail', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.UPLOAD, exclusionPatterns: ['**/Raw/**'] });
|
||||
expect(status).toBe(400);
|
||||
|
||||
expect(body).toEqual(errorStub.badRequest('Upload libraries cannot have exclusion patterns'));
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow a user to create a library', async () => {
|
||||
await api.userCreate(server, accessToken, userStub.user1);
|
||||
|
||||
const loginResponse = await api.login(server, {
|
||||
email: userStub.user1.email,
|
||||
password: userStub.user1.password ?? '',
|
||||
});
|
||||
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${loginResponse.accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL });
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New External Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT /library/:id', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).put(`/library/${uuidStub.notFound}`).send({});
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
describe('external library', () => {
|
||||
let libraryId: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create an external library with default settings
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL });
|
||||
|
||||
expect(status).toBe(201);
|
||||
|
||||
libraryId = body.id;
|
||||
});
|
||||
|
||||
it('should change the library name', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ name: 'New Library Name' });
|
||||
expect(status).toBe(200);
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New Library Name',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should not set an empty name', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ name: '' });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest(['name should not be empty']));
|
||||
});
|
||||
|
||||
it('should change the import paths', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ importPaths: ['/path/to/import'] });
|
||||
expect(status).toBe(200);
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New External Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: ['/path/to/import'],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should not allow an empty import path', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ importPaths: [''] });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest(['each value in importPaths should not be empty']));
|
||||
});
|
||||
|
||||
it('should change the exclusion pattern', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ exclusionPatterns: [''] });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest(['each value in exclusionPatterns should not be empty']));
|
||||
});
|
||||
|
||||
it('should not allow an empty exclusion pattern', async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ importPaths: [''] });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest(['each value in importPaths should not be empty']));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /library/:id', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).get(`/library/${uuidStub.notFound}`);
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
it('should get library by id', async () => {
|
||||
let libraryId: string;
|
||||
{
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL });
|
||||
expect(status).toBe(201);
|
||||
libraryId = body.id;
|
||||
}
|
||||
const { status, body } = await request(server)
|
||||
.get(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`);
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
ownerId: loginResponse.userId,
|
||||
type: LibraryType.EXTERNAL,
|
||||
name: 'New External Library',
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
refreshedAt: null,
|
||||
assetCount: 0,
|
||||
importPaths: [],
|
||||
exclusionPatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("should not allow getting another user's library", async () => {
|
||||
await api.userCreate(server, accessToken, userStub.user1);
|
||||
|
||||
const loginResponse = await api.login(server, {
|
||||
email: userStub.user1.email,
|
||||
password: userStub.user1.password ?? '',
|
||||
});
|
||||
|
||||
let libraryId: string;
|
||||
{
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL });
|
||||
expect(status).toBe(201);
|
||||
libraryId = body.id;
|
||||
}
|
||||
|
||||
const { status, body } = await request(server)
|
||||
.get(`/library/${libraryId}`)
|
||||
.set('Authorization', `Bearer ${loginResponse.accessToken}`);
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest('Not found or no library.read access'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('DELETE /library/:id', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).delete(`/library/${uuidStub.notFound}`);
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
it('should not delete the last upload library', async () => {
|
||||
const [defaultLibrary] = await api.libraryApi.getAll(server, accessToken);
|
||||
expect(defaultLibrary).toBeDefined();
|
||||
|
||||
const { status, body } = await request(server)
|
||||
.delete(`/library/${defaultLibrary.id}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.noDeleteUploadLibrary);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /library/:id/statistics', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).get(`/library/${uuidStub.notFound}/statistics`);
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /library/:id/scan', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).post(`/library/${uuidStub.notFound}/scan`).send({});
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
it('should scan external library', async () => {
|
||||
let libraryId: string;
|
||||
{
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.EXTERNAL });
|
||||
expect(status).toBe(201);
|
||||
libraryId = body.id;
|
||||
}
|
||||
|
||||
const { status, body } = await request(server)
|
||||
.post(`/library/${libraryId}/scan`)
|
||||
.set('Authorization', `Bearer ${accessToken}`);
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body).toEqual({});
|
||||
});
|
||||
|
||||
it('should not scan an upload library', async () => {
|
||||
let libraryId: string;
|
||||
{
|
||||
const { status, body } = await request(server)
|
||||
.post('/library')
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ type: LibraryType.UPLOAD });
|
||||
expect(status).toBe(201);
|
||||
libraryId = body.id;
|
||||
}
|
||||
|
||||
const { status, body } = await request(server)
|
||||
.post(`/library/${libraryId}/scan`)
|
||||
.set('Authorization', `Bearer ${accessToken}`);
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest('Can only refresh external libraries'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /library/:id/removeOffline', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(server).post(`/library/${uuidStub.notFound}/removeOffline`).send({});
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -37,7 +37,7 @@ describe(`${OAuthController.name} (e2e)`, () => {
|
||||
it(`should throw an error if a redirect uri is not provided`, async () => {
|
||||
const { status, body } = await request(server).post('/oauth/authorize').send({});
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest(['redirectUri must be a string', 'redirectUri should not be empty']));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -110,7 +110,7 @@ describe(`${PersonController.name}`, () => {
|
||||
.set('Authorization', `Bearer ${accessToken}`);
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
|
||||
it('should return person information', async () => {
|
||||
@@ -130,25 +130,34 @@ describe(`${PersonController.name}`, () => {
|
||||
expect(body).toEqual(errorStub.unauthorized);
|
||||
});
|
||||
|
||||
for (const key of ['name', 'featureFaceAssetId', 'isHidden']) {
|
||||
for (const { key, type } of [
|
||||
{ key: 'name', type: 'string' },
|
||||
{ key: 'featureFaceAssetId', type: 'string' },
|
||||
{ key: 'isHidden', type: 'boolean value' },
|
||||
]) {
|
||||
it(`should not allow null ${key}`, async () => {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/person/${visiblePerson.id}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ [key]: null });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest([`${key} must be a ${type}`]));
|
||||
});
|
||||
}
|
||||
|
||||
it('should not accept invalid birth dates', async () => {
|
||||
for (const birthDate of [false, 'false', '123567', 123456]) {
|
||||
for (const { birthDate, response } of [
|
||||
{ birthDate: false, response: ['id must be a UUID'] },
|
||||
{ birthDate: 'false', response: ['birthDate must be a Date instance'] },
|
||||
{ birthDate: '123567', response: ['id must be a UUID'] },
|
||||
{ birthDate: 123456, response: ['id must be a UUID'] },
|
||||
]) {
|
||||
const { status, body } = await request(server)
|
||||
.put(`/person/${uuidStub.notFound}`)
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ birthDate });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest(response));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ describe(`${PartnerController.name} (e2e)`, () => {
|
||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
|
||||
it('should require an asset/album id', async () => {
|
||||
@@ -211,7 +211,7 @@ describe(`${PartnerController.name} (e2e)`, () => {
|
||||
.send({ description: 'foo' });
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
|
||||
it('should update shared link', async () => {
|
||||
@@ -241,7 +241,7 @@ describe(`${PartnerController.name} (e2e)`, () => {
|
||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
|
||||
it('should update shared link', async () => {
|
||||
|
||||
@@ -138,7 +138,7 @@ describe(`${UserController.name}`, () => {
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ ...userSignupStub, [key]: null });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ describe(`${UserController.name}`, () => {
|
||||
.set('Authorization', `Bearer ${accessToken}`)
|
||||
.send({ ...userStub.admin, [key]: null });
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorStub.badRequest);
|
||||
expect(body).toEqual(errorStub.badRequest());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user