forked from immich-app/immich
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(web,server): run code coverage reports (immich-app#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
- Loading branch information
Showing
6 changed files
with
231 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ | |
.idea | ||
|
||
docker/upload | ||
coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,63 +6,76 @@ import { when } from 'jest-when'; | |
import { UserService } from './user.service'; | ||
import { UpdateUserDto } from './dto/update-user.dto'; | ||
|
||
describe('UserService', () => { | ||
let sut: UserService; | ||
let userRepositoryMock: jest.Mocked<IUserRepository>; | ||
const adminUserAuth: AuthUserDto = Object.freeze({ | ||
id: 'admin_id', | ||
email: '[email protected]', | ||
isAdmin: true, | ||
}); | ||
|
||
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 immichUserAuth: AuthUserDto = Object.freeze({ | ||
id: 'immich_id', | ||
email: '[email protected]', | ||
isAdmin: false, | ||
}); | ||
const adminUser: UserEntity = Object.freeze({ | ||
id: adminUserAuth.id, | ||
email: '[email protected]', | ||
password: 'admin_password', | ||
firstName: 'admin_first_name', | ||
lastName: 'admin_last_name', | ||
isAdmin: true, | ||
oauthId: '', | ||
shouldChangePassword: false, | ||
profileImagePath: '', | ||
createdAt: '2021-01-01', | ||
tags: [], | ||
}); | ||
|
||
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 immichUser: UserEntity = Object.freeze({ | ||
id: immichUserAuth.id, | ||
email: '[email protected]', | ||
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: '[email protected]', | ||
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 updatedImmichUser: UserEntity = Object.freeze({ | ||
id: immichUserAuth.id, | ||
email: '[email protected]', | ||
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: '[email protected]', | ||
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>; | ||
|
||
beforeEach(() => { | ||
userRepositoryMock = { | ||
|
@@ -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: '[email protected]', | ||
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); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.