import { Test, TestingModule } from '@nestjs/testing'; import { MailerModule } from '../mailer/mailer.module'; import { User } from './schemas/user.schema'; import { UsersService } from './users.service'; import { getModelToken } from '@nestjs/mongoose'; import { CreateUserDto } from './dto/create-user.dto'; import { HttpException, HttpStatus } from '@nestjs/common'; import { LoginDto } from '../auth/login-dto'; import { EmailChangeDto } from './dto/change-email.dto'; import * as bcrypt from 'bcrypt'; import { ConfigurationModule } from '../configuration/configuration.module'; import { IUser } from './interfaces/user.interface'; function hashPassword() { return bcrypt.hashSync(process.env.USER_PWD, process.env.SALT); } describe('UsersService', () => { let service: UsersService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ imports: [MailerModule, ConfigurationModule], providers: [ UsersService, { provide: getModelToken('User'), useValue: User, }, ], }).compile(); service = module.get<UsersService>(UsersService); }); describe('User Service create', () => { it('UsersService should be defined', () => { expect(service).toBeDefined(); }); it('User should be created', async () => { const result: User = { role: 0, validationToken: 'cf1c74c22cedb6b575945098db42d2f493fb759c9142c6aff7980f252886f36ee086574ee99a06bc99119079257116c959c8ec870949cebdef2b293666dbca42', emailVerified: false, email: 'jacques.dupont@mii.com', password: hashPassword(), newEmail: '', changeEmailToken: '', resetPasswordToken: null, structuresLink: [], structureOutdatedMailSent: [], pendingStructuresLink: [], name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', }; const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!', name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', }; //NOSONAR jest.spyOn(service, 'create').mockImplementation(async (): Promise<User> => result); expect(await service.create(userDto)).toBe(result); }); it('User should not be created, already exist', async () => { const result = new HttpException('User already exists', HttpStatus.BAD_REQUEST); const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!', name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', }; //NOSONAR jest.spyOn(service, 'create').mockImplementation(async (): Promise<any> => result); expect(await service.create(userDto)).toBe(result); }); it('User should not be created, weak password', async () => { const result = new HttpException( 'Weak password, it must contain one lowercase alphabetical character, one uppercase alphabetical character, one numeric character, one special character and be eight characters or longer', HttpStatus.UNPROCESSABLE_ENTITY ); const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test', name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', }; //NOSONAR jest.spyOn(service, 'create').mockImplementation(async (): Promise<any> => result); expect(await service.create(userDto)).toBe(result); }); }); describe('findByLogin', () => { it('should find', async () => { const result = { validationToken: 'cf1c74c22cedb6b575945098db42d2f493fb759c9142c6aff7980f252886f36ee086574ee99a06bc99119079257116c959c8ec870949cebdef2b293666dbca42', emailVerified: false, email: 'jacques.dupont@mii.com', password: hashPassword(), role: 0, newEmail: '', changeEmailToken: '', resetPasswordToken: null, structuresLink: [], pendingStructuresLink: [], structureOutdatedMailSent: [], name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', }; const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR jest.spyOn(service, 'findByLogin').mockImplementation(async (): Promise<User> => result); expect(await service.findByLogin(loginDto)).toBe(result); }); it('user does not exist, should be unauthorized issue', async () => { const result: HttpException = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED); const loginDto: LoginDto = { email: 'jean.dupont@mii.com', password: 'test1A!!' }; //NOSONAR jest.spyOn(service, 'findByLogin').mockImplementation(async (): Promise<any> => result); expect(await service.findByLogin(loginDto)).toBe(result); }); it('wrong password, should be unauthorized issue', async () => { const result: HttpException = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED); const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!!' }; //NOSONAR jest.spyOn(service, 'findByLogin').mockImplementation(async (): Promise<any> => result); expect(await service.findByLogin(loginDto)).toBe(result); }); }); describe('validateUser', () => { it('should not validateUser', async () => { const result = new HttpException('Invalid token', HttpStatus.UNAUTHORIZED); jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<HttpException> => result); expect(await service.validateUser('add3d', 'qdqdqdqd185')).toBe(result); }); }); describe('changeUserPassword', () => { it('should not change password', async () => { const result = new HttpException('Invalid token', HttpStatus.UNAUTHORIZED); jest.spyOn(service, 'changeUserPassword').mockImplementation(async (): Promise<HttpException> => result); expect(await service.changeUserPassword('add3d', 'azertyU1', 'azertyU1!d')).toBe(result); }); it('should not change password', async () => { const result = new HttpException('Invalid token', HttpStatus.UNPROCESSABLE_ENTITY); jest.spyOn(service, 'changeUserPassword').mockImplementation(async (): Promise<HttpException> => result); expect(await service.changeUserPassword('add3d', 'azertyU1!d', 'a')).toBe(result); }); it('should change password', async () => { const result = new HttpException('Invalid token', HttpStatus.CREATED); jest.spyOn(service, 'changeUserPassword').mockImplementation(async (): Promise<HttpException> => result); expect(await service.changeUserPassword('add3d', 'azertyU1!d', 'azertyU1!d')).toBe(result); }); }); describe('changeUserEmail', () => { it('should find and add token', async () => { const result = { validationToken: '', emailVerified: true, email: 'jacques.dupont@mii.com', password: hashPassword(), role: 0, newEmail: 'test.dupont@mail.com', resetPasswordToken: '', structuresLink: [], pendingStructuresLink: [], structureOutdatedMailSent: [], name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', changeEmailToken: '9bb3542bdc5ca8801ad4cee00403c1052bc95dee768dcbb65b1f719870578ed79f71f52fdc3e6bf02fd200a72b8b6f56fc26950df30c8cd7e427a485f80181b9', }; const emailDto: EmailChangeDto = { newEmail: 'test.dupont@mail.com', oldEmail: 'jacques.dupont@mii.com' }; //NOSONAR jest.spyOn(service, 'changeUserEmail').mockImplementation(async (): Promise<User> => result); expect(await service.changeUserEmail(emailDto)).toBe(result); }); it('user does not exist, should be unauthorized issue', async () => { const result: HttpException = new HttpException('Email sent if account exist', HttpStatus.UNAUTHORIZED); const emailDto: EmailChangeDto = { newEmail: 'test.dupont@mail.com', oldEmail: 'jacques.dupont@mii.com' }; //NOSONAR jest.spyOn(service, 'changeUserEmail').mockImplementation(async (): Promise<any> => result); expect(await service.changeUserEmail(emailDto)).toBe(result); }); it('email already used, should be not acceptable issue', async () => { const result: HttpException = new HttpException('Email already used', HttpStatus.NOT_ACCEPTABLE); const emailDto: EmailChangeDto = { newEmail: 'jacques.dupont@mii.com', oldEmail: 'jacques.dupont@mii.com' }; //NOSONAR jest.spyOn(service, 'changeUserEmail').mockImplementation(async (): Promise<any> => result); expect(await service.changeUserEmail(emailDto)).toBe(result); }); it('should change email', async () => { const result = { validationToken: '', emailVerified: true, email: 'test.dupont@mail.com', password: hashPassword(), role: 0, newEmail: '', resetPasswordToken: '', changeEmailToken: '', structuresLink: [], pendingStructuresLink: [], structureOutdatedMailSent: [], name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', }; const token = '9bb3542bdc5ca8801ad4cee00403c1052bc95dee768dcbb65b1f719870578ed79f71f52fdc3e6bf02fd200a72b8b6f56fc26950df30c8cd7e427a485f80181b9'; //NOSONAR jest.spyOn(service, 'verifyAndUpdateUserEmail').mockImplementation(async (): Promise<User> => result); expect(await service.verifyAndUpdateUserEmail(token)).toBe(result); }); it('should not change email', async () => { const result: HttpException = new HttpException('Invalid token', HttpStatus.UNAUTHORIZED); const token = '9bb3542bdc5ca8801aa72b8b6f56fc26950df30c8cd7e427a485f80181b9FAKETOKEN'; //NOSONAR jest.spyOn(service, 'verifyAndUpdateUserEmail').mockImplementation(async (): Promise<any> => result); expect(await service.verifyAndUpdateUserEmail(token)).toBe(result); }); }); describe('sendResetPasswordEmail', () => { it('should not send email', async () => { const result = new HttpException('Email sent if account exist', HttpStatus.OK); jest.spyOn(service, 'sendResetPasswordEmail').mockImplementation(async (): Promise<HttpException> => result); expect(await service.sendResetPasswordEmail('test@mii.com')).toBe(result); }); it('should send email', async () => { const result = new HttpException('Email sent if account exist', HttpStatus.OK); jest.spyOn(service, 'sendResetPasswordEmail').mockImplementation(async (): Promise<HttpException> => result); expect(await service.sendResetPasswordEmail('test@mii.com')).toBe(result); }); }); describe('validatePasswordResetToken', () => { it('should not validate new password: token does`nt exist', async () => { const result = new HttpException('Invalid token', HttpStatus.UNAUTHORIZED); jest.spyOn(service, 'validatePasswordResetToken').mockImplementation(async (): Promise<HttpException> => result); expect( await service.validatePasswordResetToken( 'test@mii.com', '5def4cb41106f89c212679e164911776618bd529e4f78e2883f7dd01776612a1b4a2ad7edabf2a3e3638aa605966c7a4b69d5f07d9617334e58332ba5f9305' ) ).toBe(result); }); it('should not validate new password: weak password', async () => { const result = new HttpException( 'Weak password, it must contain one lowercase alphabetical character, one uppercase alphabetical character, one numeric character, one special character and be eight characters or longer', HttpStatus.UNPROCESSABLE_ENTITY ); jest.spyOn(service, 'validatePasswordResetToken').mockImplementation(async (): Promise<HttpException> => result); expect( await service.validatePasswordResetToken( 'test@mii.com', '5def4cb41106f89c212679e164911776618bd529e4f78e2883f7dd01776612a1b4a2ad7edabf2a3e3638aa605966c7a4b69d5f07d9617334e58332ba5f9305a6' ) ).toBe(result); }); it('should validate new password', async () => { const result = new HttpException('Password Reset', HttpStatus.OK); jest.spyOn(service, 'validatePasswordResetToken').mockImplementation(async (): Promise<HttpException> => result); expect( await service.validatePasswordResetToken( 'test@mii.com', '5def4cb41106f89c212679e164911776618bd529e4f78e2883f7dd01776612a1b4a2ad7edabf2a3e3638aa605966c7a4b69d5f07d9617334e58332ba5f9305a6' ) ).toBe(result); }); it('should return structureLink tab ', async () => { const result = [53]; jest.spyOn(service, 'updateStructureLinked').mockImplementation(async (): Promise<any> => result); expect(await service.updateStructureLinked('test@mii.com', '6001a37716b08100062e4160')).toBe(result); }); it('should return invalid User ', async () => { const result = new HttpException('Invalid user', HttpStatus.NOT_FOUND); jest.spyOn(service, 'updateStructureLinked').mockImplementation(async (): Promise<any> => result); expect(await service.updateStructureLinked('test@mii.com', '6001a37716b08100062e4160')).toBe(result); }); }); it('should find All Unattacheduser', async () => { const result = [ { _id: '123', validationToken: 'cf1c74c22cedb6b575945098db42d2f493fb759c9142c6aff7980f252886f36ee086574ee99a06bc99119079257116c959c8ec870949cebdef2b293666dbca42', emailVerified: false, email: 'jacques.dupont@mii.com', password: hashPassword(), role: 0, newEmail: '', changeEmailToken: '', resetPasswordToken: null, structuresLink: [], pendingStructuresLink: [], structureOutdatedMailSent: [], name: 'Jacques', surname: 'Dupont', phone: '06 06 06 06 06', } as IUser, ]; jest.spyOn(service, 'findAllUnattached').mockImplementation(async (): Promise<IUser[]> => result); expect(await service.findAllUnattached()).toBe(result); }); it('should find attached users', async () => { const result = []; jest.spyOn(service, 'findAllAttached').mockImplementation(async (): Promise<IUser[]> => result); expect((await service.findAllAttached()).length).toBe(0); }); it('should find UnVerified Users', async () => { const result = []; jest.spyOn(service, 'findAllUnVerified').mockImplementation(async (): Promise<IUser[]> => result); expect((await service.findAllUnVerified()).length).toBe(0); }); });