mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	chore(web,server): run code coverage reports (#1313)
* chore(web,server): run code coverage reports * chore(tests): fail test check if coverage drops * chore: disable e2e until they are fixed * chore(web): coverage threshold
This commit is contained in:
		@@ -6,64 +6,77 @@ import { when } from 'jest-when';
 | 
			
		||||
import { UserService } from './user.service';
 | 
			
		||||
import { UpdateUserDto } from './dto/update-user.dto';
 | 
			
		||||
 | 
			
		||||
const adminUserAuth: AuthUserDto = Object.freeze({
 | 
			
		||||
  id: 'admin_id',
 | 
			
		||||
  email: 'admin@test.com',
 | 
			
		||||
  isAdmin: true,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const immichUserAuth: AuthUserDto = Object.freeze({
 | 
			
		||||
  id: 'immich_id',
 | 
			
		||||
  email: 'immich@test.com',
 | 
			
		||||
  isAdmin: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const adminUser: UserEntity = Object.freeze({
 | 
			
		||||
  id: adminUserAuth.id,
 | 
			
		||||
  email: 'admin@test.com',
 | 
			
		||||
  password: 'admin_password',
 | 
			
		||||
  firstName: 'admin_first_name',
 | 
			
		||||
  lastName: 'admin_last_name',
 | 
			
		||||
  isAdmin: true,
 | 
			
		||||
  oauthId: '',
 | 
			
		||||
  shouldChangePassword: false,
 | 
			
		||||
  profileImagePath: '',
 | 
			
		||||
  createdAt: '2021-01-01',
 | 
			
		||||
  tags: [],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const immichUser: UserEntity = Object.freeze({
 | 
			
		||||
  id: immichUserAuth.id,
 | 
			
		||||
  email: 'immich@test.com',
 | 
			
		||||
  password: 'immich_password',
 | 
			
		||||
  firstName: 'immich_first_name',
 | 
			
		||||
  lastName: 'immich_last_name',
 | 
			
		||||
  isAdmin: false,
 | 
			
		||||
  oauthId: '',
 | 
			
		||||
  shouldChangePassword: false,
 | 
			
		||||
  profileImagePath: '',
 | 
			
		||||
  createdAt: '2021-01-01',
 | 
			
		||||
  tags: [],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const updatedImmichUser: UserEntity = Object.freeze({
 | 
			
		||||
  id: immichUserAuth.id,
 | 
			
		||||
  email: 'immich@test.com',
 | 
			
		||||
  password: 'immich_password',
 | 
			
		||||
  firstName: 'updated_immich_first_name',
 | 
			
		||||
  lastName: 'updated_immich_last_name',
 | 
			
		||||
  isAdmin: false,
 | 
			
		||||
  oauthId: '',
 | 
			
		||||
  shouldChangePassword: true,
 | 
			
		||||
  profileImagePath: '',
 | 
			
		||||
  createdAt: '2021-01-01',
 | 
			
		||||
  tags: [],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const adminUserResponse = Object.freeze({
 | 
			
		||||
  id: adminUserAuth.id,
 | 
			
		||||
  email: 'admin@test.com',
 | 
			
		||||
  deletedAt: undefined,
 | 
			
		||||
  firstName: 'admin_first_name',
 | 
			
		||||
  lastName: 'admin_last_name',
 | 
			
		||||
  isAdmin: true,
 | 
			
		||||
  oauthId: '',
 | 
			
		||||
  shouldChangePassword: false,
 | 
			
		||||
  profileImagePath: '',
 | 
			
		||||
  createdAt: '2021-01-01',
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
describe('UserService', () => {
 | 
			
		||||
  let sut: UserService;
 | 
			
		||||
  let userRepositoryMock: jest.Mocked<IUserRepository>;
 | 
			
		||||
 | 
			
		||||
  const adminUserAuth: AuthUserDto = Object.freeze({
 | 
			
		||||
    id: 'admin_id',
 | 
			
		||||
    email: 'admin@test.com',
 | 
			
		||||
    isAdmin: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const immichUserAuth: AuthUserDto = Object.freeze({
 | 
			
		||||
    id: 'immich_id',
 | 
			
		||||
    email: 'immich@test.com',
 | 
			
		||||
    isAdmin: false,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const adminUser: UserEntity = Object.freeze({
 | 
			
		||||
    id: adminUserAuth.id,
 | 
			
		||||
    email: 'admin@test.com',
 | 
			
		||||
    password: 'admin_password',
 | 
			
		||||
    firstName: 'admin_first_name',
 | 
			
		||||
    lastName: 'admin_last_name',
 | 
			
		||||
    isAdmin: true,
 | 
			
		||||
    oauthId: '',
 | 
			
		||||
    shouldChangePassword: false,
 | 
			
		||||
    profileImagePath: '',
 | 
			
		||||
    createdAt: '2021-01-01',
 | 
			
		||||
    tags: [],
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const immichUser: UserEntity = Object.freeze({
 | 
			
		||||
    id: immichUserAuth.id,
 | 
			
		||||
    email: 'immich@test.com',
 | 
			
		||||
    password: 'immich_password',
 | 
			
		||||
    firstName: 'immich_first_name',
 | 
			
		||||
    lastName: 'immich_last_name',
 | 
			
		||||
    isAdmin: false,
 | 
			
		||||
    oauthId: '',
 | 
			
		||||
    shouldChangePassword: false,
 | 
			
		||||
    profileImagePath: '',
 | 
			
		||||
    createdAt: '2021-01-01',
 | 
			
		||||
    tags: [],
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const updatedImmichUser: UserEntity = Object.freeze({
 | 
			
		||||
    id: immichUserAuth.id,
 | 
			
		||||
    email: 'immich@test.com',
 | 
			
		||||
    password: 'immich_password',
 | 
			
		||||
    firstName: 'updated_immich_first_name',
 | 
			
		||||
    lastName: 'updated_immich_last_name',
 | 
			
		||||
    isAdmin: false,
 | 
			
		||||
    oauthId: '',
 | 
			
		||||
    shouldChangePassword: true,
 | 
			
		||||
    profileImagePath: '',
 | 
			
		||||
    createdAt: '2021-01-01',
 | 
			
		||||
    tags: [],
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    userRepositoryMock = {
 | 
			
		||||
      get: jest.fn(),
 | 
			
		||||
@@ -78,12 +91,86 @@ describe('UserService', () => {
 | 
			
		||||
    };
 | 
			
		||||
    when(userRepositoryMock.get).calledWith(adminUser.id).mockResolvedValue(adminUser);
 | 
			
		||||
    when(userRepositoryMock.get).calledWith(adminUser.id, undefined).mockResolvedValue(adminUser);
 | 
			
		||||
    when(userRepositoryMock.get).calledWith(immichUser.id).mockResolvedValue(immichUser);
 | 
			
		||||
    when(userRepositoryMock.get).calledWith(immichUser.id, undefined).mockResolvedValue(immichUser);
 | 
			
		||||
 | 
			
		||||
    sut = new UserService(userRepositoryMock);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Update user', () => {
 | 
			
		||||
  describe('getAllUsers', () => {
 | 
			
		||||
    it('should get all users', async () => {
 | 
			
		||||
      userRepositoryMock.getList.mockResolvedValue([adminUser]);
 | 
			
		||||
 | 
			
		||||
      const response = await sut.getAllUsers(adminUserAuth, false);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.getList).toHaveBeenCalledWith({ excludeId: adminUser.id });
 | 
			
		||||
      expect(response).toEqual([
 | 
			
		||||
        {
 | 
			
		||||
          id: adminUserAuth.id,
 | 
			
		||||
          email: 'admin@test.com',
 | 
			
		||||
          deletedAt: undefined,
 | 
			
		||||
          firstName: 'admin_first_name',
 | 
			
		||||
          lastName: 'admin_last_name',
 | 
			
		||||
          isAdmin: true,
 | 
			
		||||
          oauthId: '',
 | 
			
		||||
          shouldChangePassword: false,
 | 
			
		||||
          profileImagePath: '',
 | 
			
		||||
          createdAt: '2021-01-01',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getUserById', () => {
 | 
			
		||||
    it('should get a user by id', async () => {
 | 
			
		||||
      userRepositoryMock.get.mockResolvedValue(adminUser);
 | 
			
		||||
 | 
			
		||||
      const response = await sut.getUserById(adminUser.id);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUser.id, false);
 | 
			
		||||
      expect(response).toEqual(adminUserResponse);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should throw an error if a user is not found', async () => {
 | 
			
		||||
      userRepositoryMock.get.mockResolvedValue(null);
 | 
			
		||||
 | 
			
		||||
      await expect(sut.getUserById(adminUser.id)).rejects.toBeInstanceOf(NotFoundException);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUser.id, false);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getUserInfo', () => {
 | 
			
		||||
    it("should get the auth user's info", async () => {
 | 
			
		||||
      userRepositoryMock.get.mockResolvedValue(adminUser);
 | 
			
		||||
 | 
			
		||||
      const response = await sut.getUserInfo(adminUser);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUser.id, undefined);
 | 
			
		||||
      expect(response).toEqual(adminUserResponse);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should throw an error if a user is not found', async () => {
 | 
			
		||||
      userRepositoryMock.get.mockResolvedValue(null);
 | 
			
		||||
 | 
			
		||||
      await expect(sut.getUserInfo(adminUser)).rejects.toBeInstanceOf(BadRequestException);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUser.id, undefined);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getUserCount', () => {
 | 
			
		||||
    it('should get the user count', async () => {
 | 
			
		||||
      userRepositoryMock.getList.mockResolvedValue([adminUser]);
 | 
			
		||||
 | 
			
		||||
      const response = await sut.getUserCount({});
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.getList).toHaveBeenCalled();
 | 
			
		||||
      expect(response).toEqual({ userCount: 1 });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('update', () => {
 | 
			
		||||
    it('should update user', async () => {
 | 
			
		||||
      const update: UpdateUserDto = {
 | 
			
		||||
        id: immichUser.id,
 | 
			
		||||
@@ -161,17 +248,7 @@ describe('UserService', () => {
 | 
			
		||||
 | 
			
		||||
      await expect(result).rejects.toBeInstanceOf(NotFoundException);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Delete user', () => {
 | 
			
		||||
    it('cannot delete admin user', async () => {
 | 
			
		||||
      const result = sut.deleteUser(adminUserAuth, adminUserAuth.id);
 | 
			
		||||
 | 
			
		||||
      await expect(result).rejects.toBeInstanceOf(ForbiddenException);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Create user', () => {
 | 
			
		||||
    it('should let the admin update himself', async () => {
 | 
			
		||||
      const dto = { id: adminUser.id, shouldChangePassword: true, isAdmin: true };
 | 
			
		||||
 | 
			
		||||
@@ -190,7 +267,37 @@ describe('UserService', () => {
 | 
			
		||||
 | 
			
		||||
      await expect(sut.updateUser(adminUser, dto)).rejects.toBeInstanceOf(BadRequestException);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('restoreUser', () => {
 | 
			
		||||
    it('should require an admin', async () => {
 | 
			
		||||
      when(userRepositoryMock.get).calledWith(adminUser.id, true).mockResolvedValue(adminUser);
 | 
			
		||||
      await expect(sut.restoreUser(immichUserAuth, adminUser.id)).rejects.toBeInstanceOf(ForbiddenException);
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUser.id, true);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should require the auth user be an admin', async () => {
 | 
			
		||||
      await expect(sut.deleteUser(immichUserAuth, adminUserAuth.id)).rejects.toBeInstanceOf(ForbiddenException);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.delete).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('deleteUser', () => {
 | 
			
		||||
    it('cannot delete admin user', async () => {
 | 
			
		||||
      const result = sut.deleteUser(adminUserAuth, adminUserAuth.id);
 | 
			
		||||
 | 
			
		||||
      await expect(result).rejects.toBeInstanceOf(ForbiddenException);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should require the auth user be an admin', async () => {
 | 
			
		||||
      await expect(sut.deleteUser(immichUserAuth, adminUserAuth.id)).rejects.toBeInstanceOf(ForbiddenException);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.delete).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('update', () => {
 | 
			
		||||
    it('should not create a user if there is no local admin account', async () => {
 | 
			
		||||
      when(userRepositoryMock.getAdmin).calledWith().mockResolvedValueOnce(null);
 | 
			
		||||
 | 
			
		||||
@@ -204,4 +311,33 @@ describe('UserService', () => {
 | 
			
		||||
      ).rejects.toBeInstanceOf(BadRequestException);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('createProfileImage', () => {
 | 
			
		||||
    it('should throw an error if the user does not exist', async () => {
 | 
			
		||||
      const file = { path: '/profile/path' } as Express.Multer.File;
 | 
			
		||||
      userRepositoryMock.update.mockResolvedValue({ ...adminUser, profileImagePath: file.path });
 | 
			
		||||
 | 
			
		||||
      await sut.createProfileImage(adminUserAuth, file);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.update).toHaveBeenCalledWith(adminUserAuth.id, { profileImagePath: file.path });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getUserProfileImage', () => {
 | 
			
		||||
    it('should throw an error if the user does not exist', async () => {
 | 
			
		||||
      userRepositoryMock.get.mockResolvedValue(null);
 | 
			
		||||
 | 
			
		||||
      await expect(sut.getUserProfileImage(adminUserAuth.id)).rejects.toBeInstanceOf(NotFoundException);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUserAuth.id, undefined);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should throw an error if the user does not have a picture', async () => {
 | 
			
		||||
      userRepositoryMock.get.mockResolvedValue(adminUser);
 | 
			
		||||
 | 
			
		||||
      await expect(sut.getUserProfileImage(adminUserAuth.id)).rejects.toBeInstanceOf(NotFoundException);
 | 
			
		||||
 | 
			
		||||
      expect(userRepositoryMock.get).toHaveBeenCalledWith(adminUserAuth.id, undefined);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user