mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -05:00 
			
		
		
		
	* tests for person service * tests for auth service * tests for access core * improve tests for album service * fix missing brackets and remove comments * tests for asset service * tests for face recognition * tests for job service * feedback * tests for search service (broken) * fix: disabled search test * tests for smart-info service * tests for storage template service * tests for user service * fix formatting of untouched files LOL * attempt to fix formatting * streamline api utils, add asset api for uploading files * test upload of assets * fix formatting * move test-utils to correct folder * test add assets to album * use random bytes instead of test image * (e2e) test albums with assets * (e2e) complete tests for album endpoints * (e2e) tests for asset endpoint * fix: asset upload/import dto validation * (e2e) tests for statistics asset endpoint * fix wrong describe text * (e2e) tests for people with faces * (e2e) clean up person tests * (e2e) tests for partner sharing endpoints * (e2e) tests for link sharing * (e2e) tests for the asset time bucket endpoint * fix minor issues * remove access.core.spec.ts * chore: wording * chore: organize test api files * chore: fix test describe * implement feedback * fix race condition in album tests --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
		
			
				
	
	
		
			293 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { LoginResponseDto } from '@app/domain';
 | 
						|
import { AppModule, UserController } from '@app/immich';
 | 
						|
import { INestApplication } from '@nestjs/common';
 | 
						|
import { Test, TestingModule } from '@nestjs/testing';
 | 
						|
import { api } from '@test/api';
 | 
						|
import { db } from '@test/db';
 | 
						|
import { errorStub, userSignupStub, userStub } from '@test/fixtures';
 | 
						|
import request from 'supertest';
 | 
						|
 | 
						|
describe(`${UserController.name}`, () => {
 | 
						|
  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.authApi.adminSignUp(server);
 | 
						|
    loginResponse = await api.authApi.adminLogin(server);
 | 
						|
    accessToken = loginResponse.accessToken;
 | 
						|
  });
 | 
						|
 | 
						|
  afterAll(async () => {
 | 
						|
    await db.disconnect();
 | 
						|
    await app.close();
 | 
						|
  });
 | 
						|
 | 
						|
  describe('GET /user', () => {
 | 
						|
    it('should require authentication', async () => {
 | 
						|
      const { status, body } = await request(server).get('/user');
 | 
						|
      expect(status).toBe(401);
 | 
						|
      expect(body).toEqual(errorStub.unauthorized);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should start with the admin', async () => {
 | 
						|
      const { status, body } = await request(server).get('/user').set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toEqual(200);
 | 
						|
      expect(body).toHaveLength(1);
 | 
						|
      expect(body[0]).toMatchObject({ email: 'admin@immich.app' });
 | 
						|
    });
 | 
						|
 | 
						|
    it('should hide deleted users', async () => {
 | 
						|
      const user1 = await api.userApi.create(server, accessToken, {
 | 
						|
        email: `user1@immich.app`,
 | 
						|
        password: 'Password123',
 | 
						|
        firstName: `User 1`,
 | 
						|
        lastName: 'Test',
 | 
						|
      });
 | 
						|
 | 
						|
      await api.userApi.delete(server, accessToken, user1.id);
 | 
						|
 | 
						|
      const { status, body } = await request(server)
 | 
						|
        .get(`/user`)
 | 
						|
        .query({ isAll: true })
 | 
						|
        .set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toHaveLength(1);
 | 
						|
      expect(body[0]).toMatchObject({ email: 'admin@immich.app' });
 | 
						|
    });
 | 
						|
 | 
						|
    it('should include deleted users', async () => {
 | 
						|
      const user1 = await api.userApi.create(server, accessToken, {
 | 
						|
        email: `user1@immich.app`,
 | 
						|
        password: 'Password123',
 | 
						|
        firstName: `User 1`,
 | 
						|
        lastName: 'Test',
 | 
						|
      });
 | 
						|
 | 
						|
      await api.userApi.delete(server, accessToken, user1.id);
 | 
						|
 | 
						|
      const { status, body } = await request(server)
 | 
						|
        .get(`/user`)
 | 
						|
        .query({ isAll: false })
 | 
						|
        .set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toHaveLength(2);
 | 
						|
      expect(body[0]).toMatchObject({ id: user1.id, email: 'user1@immich.app', deletedAt: expect.any(String) });
 | 
						|
      expect(body[1]).toMatchObject({ id: loginResponse.userId, email: 'admin@immich.app' });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('GET /user/info/:id', () => {
 | 
						|
    it('should require authentication', async () => {
 | 
						|
      const { status } = await request(server).get(`/user/info/${loginResponse.userId}`);
 | 
						|
      expect(status).toEqual(401);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should get the user info', async () => {
 | 
						|
      const { status, body } = await request(server)
 | 
						|
        .get(`/user/info/${loginResponse.userId}`)
 | 
						|
        .set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toMatchObject({ id: loginResponse.userId, email: 'admin@immich.app' });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('GET /user/me', () => {
 | 
						|
    it('should require authentication', async () => {
 | 
						|
      const { status, body } = await request(server).get(`/user/me`);
 | 
						|
      expect(status).toBe(401);
 | 
						|
      expect(body).toEqual(errorStub.unauthorized);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should get my info', async () => {
 | 
						|
      const { status, body } = await request(server).get(`/user/me`).set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toMatchObject({ id: loginResponse.userId, email: 'admin@immich.app' });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('POST /user', () => {
 | 
						|
    it('should require authentication', async () => {
 | 
						|
      const { status, body } = await request(server).post(`/user`).send(userSignupStub);
 | 
						|
      expect(status).toBe(401);
 | 
						|
      expect(body).toEqual(errorStub.unauthorized);
 | 
						|
    });
 | 
						|
 | 
						|
    for (const key of Object.keys(userSignupStub)) {
 | 
						|
      it(`should not allow null ${key}`, async () => {
 | 
						|
        const { status, body } = await request(server)
 | 
						|
          .post(`/user`)
 | 
						|
          .set('Authorization', `Bearer ${accessToken}`)
 | 
						|
          .send({ ...userSignupStub, [key]: null });
 | 
						|
        expect(status).toBe(400);
 | 
						|
        expect(body).toEqual(errorStub.badRequest);
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    it('should ignore `isAdmin`', async () => {
 | 
						|
      const { status, body } = await request(server)
 | 
						|
        .post(`/user`)
 | 
						|
        .send({
 | 
						|
          isAdmin: true,
 | 
						|
          email: 'user1@immich.app',
 | 
						|
          password: 'Password123',
 | 
						|
          firstName: 'Immich',
 | 
						|
          lastName: 'User',
 | 
						|
        })
 | 
						|
        .set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(body).toMatchObject({
 | 
						|
        email: 'user1@immich.app',
 | 
						|
        isAdmin: false,
 | 
						|
        shouldChangePassword: true,
 | 
						|
      });
 | 
						|
      expect(status).toBe(201);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should create a user without memories enabled', async () => {
 | 
						|
      const { status, body } = await request(server)
 | 
						|
        .post(`/user`)
 | 
						|
        .send({
 | 
						|
          email: 'no-memories@immich.app',
 | 
						|
          password: 'Password123',
 | 
						|
          firstName: 'No Memories',
 | 
						|
          lastName: 'User',
 | 
						|
          memoriesEnabled: false,
 | 
						|
        })
 | 
						|
        .set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(body).toMatchObject({
 | 
						|
        email: 'no-memories@immich.app',
 | 
						|
        memoriesEnabled: false,
 | 
						|
      });
 | 
						|
      expect(status).toBe(201);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('PUT /user', () => {
 | 
						|
    it('should require authentication', async () => {
 | 
						|
      const { status, body } = await request(server).put(`/user`);
 | 
						|
      expect(status).toBe(401);
 | 
						|
      expect(body).toEqual(errorStub.unauthorized);
 | 
						|
    });
 | 
						|
 | 
						|
    for (const key of Object.keys(userStub.admin)) {
 | 
						|
      it(`should not allow null ${key}`, async () => {
 | 
						|
        const { status, body } = await request(server)
 | 
						|
          .put(`/user`)
 | 
						|
          .set('Authorization', `Bearer ${accessToken}`)
 | 
						|
          .send({ ...userStub.admin, [key]: null });
 | 
						|
        expect(status).toBe(400);
 | 
						|
        expect(body).toEqual(errorStub.badRequest);
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    it('should not allow a non-admin to become an admin', async () => {
 | 
						|
      const user = await api.userApi.create(server, accessToken, {
 | 
						|
        email: 'user1@immich.app',
 | 
						|
        password: 'Password123',
 | 
						|
        firstName: 'Immich',
 | 
						|
        lastName: 'User',
 | 
						|
      });
 | 
						|
 | 
						|
      const { status, body } = await request(server)
 | 
						|
        .put(`/user`)
 | 
						|
        .send({ isAdmin: true, id: user.id })
 | 
						|
        .set('Authorization', `Bearer ${accessToken}`);
 | 
						|
 | 
						|
      expect(status).toBe(400);
 | 
						|
      expect(body).toEqual(errorStub.alreadyHasAdmin);
 | 
						|
    });
 | 
						|
 | 
						|
    it('ignores updates to profileImagePath', async () => {
 | 
						|
      const user = await api.userApi.update(server, accessToken, {
 | 
						|
        id: loginResponse.userId,
 | 
						|
        profileImagePath: 'invalid.jpg',
 | 
						|
      } as any);
 | 
						|
 | 
						|
      expect(user).toMatchObject({ id: loginResponse.userId, profileImagePath: '' });
 | 
						|
    });
 | 
						|
 | 
						|
    it('should ignore updates to createdAt, updatedAt and deletedAt', async () => {
 | 
						|
      const before = await api.userApi.get(server, accessToken, loginResponse.userId);
 | 
						|
      const after = await api.userApi.update(server, accessToken, {
 | 
						|
        id: loginResponse.userId,
 | 
						|
        createdAt: '2023-01-01T00:00:00.000Z',
 | 
						|
        updatedAt: '2023-01-01T00:00:00.000Z',
 | 
						|
        deletedAt: '2023-01-01T00:00:00.000Z',
 | 
						|
      } as any);
 | 
						|
 | 
						|
      expect(after).toStrictEqual(before);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should update first and last name', async () => {
 | 
						|
      const before = await api.userApi.get(server, accessToken, loginResponse.userId);
 | 
						|
      const after = await api.userApi.update(server, accessToken, {
 | 
						|
        id: before.id,
 | 
						|
        firstName: 'First Name',
 | 
						|
        lastName: 'Last Name',
 | 
						|
      });
 | 
						|
 | 
						|
      expect(after).toMatchObject({
 | 
						|
        ...before,
 | 
						|
        updatedAt: expect.anything(),
 | 
						|
        firstName: 'First Name',
 | 
						|
        lastName: 'Last Name',
 | 
						|
      });
 | 
						|
      expect(before.updatedAt).not.toEqual(after.updatedAt);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should update memories enabled', async () => {
 | 
						|
      const before = await api.userApi.get(server, accessToken, loginResponse.userId);
 | 
						|
      const after = await api.userApi.update(server, accessToken, {
 | 
						|
        id: before.id,
 | 
						|
        memoriesEnabled: false,
 | 
						|
      });
 | 
						|
 | 
						|
      expect(after).toMatchObject({
 | 
						|
        ...before,
 | 
						|
        updatedAt: expect.anything(),
 | 
						|
        memoriesEnabled: false,
 | 
						|
      });
 | 
						|
      expect(before.updatedAt).not.toEqual(after.updatedAt);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('GET /user/count', () => {
 | 
						|
    it('should not require authentication', async () => {
 | 
						|
      const { status, body } = await request(server).get(`/user/count`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toEqual({ userCount: 1 });
 | 
						|
    });
 | 
						|
 | 
						|
    it('should start with just the admin', async () => {
 | 
						|
      const { status, body } = await request(server).get(`/user/count`).set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toEqual({ userCount: 1 });
 | 
						|
    });
 | 
						|
 | 
						|
    it('should return the total user count', async () => {
 | 
						|
      for (let i = 0; i < 5; i++) {
 | 
						|
        await api.userApi.create(server, accessToken, {
 | 
						|
          email: `user${i + 1}@immich.app`,
 | 
						|
          password: 'Password123',
 | 
						|
          firstName: `User ${i + 1}`,
 | 
						|
          lastName: 'Test',
 | 
						|
        });
 | 
						|
      }
 | 
						|
      const { status, body } = await request(server).get(`/user/count`).set('Authorization', `Bearer ${accessToken}`);
 | 
						|
      expect(status).toBe(200);
 | 
						|
      expect(body).toEqual({ userCount: 6 });
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 |