Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 201 additions & 48 deletions src/auth/auth.service.spec.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talvez por mudança de atributos os testes deste arquivo apresetaram erro, vejam se consegue resolver sozinho e me contatem por favor

Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { JwtService } from '@nestjs/jwt';
import { SignUpDto } from '../auth/dtos/signUp.dto';
import * as bcrypt from 'bcryptjs';
import { repositoryMockFactory } from '../../test/database/utils';
import { UnauthorizedException } from '@nestjs/common';
import { UnauthorizedException, BadRequestException } from '@nestjs/common';
import * as nodemailer from 'nodemailer';
import { SignInDto } from './dtos/signIn.dto';


describe('AuthService', () => {
let service: AuthService;
Expand Down Expand Up @@ -38,91 +40,88 @@ describe('AuthService', () => {
},
],
}).compile();

service = module.get<AuthService>(AuthService);
userRepository = module.get<Repository<User>>(getRepositoryToken(User));
jwtService = module.get<JwtService>(JwtService);

jest.spyOn(bcrypt, 'hash').mockResolvedValueOnce('hashed-password');
jest.spyOn(bcrypt, 'genSalt').mockResolvedValueOnce(10);


jest.spyOn(bcrypt, 'hash').mockResolvedValue('hashed-password');
jest.spyOn(bcrypt, 'genSalt').mockResolvedValue(10);
jest.spyOn(bcrypt, 'compare').mockResolvedValue(true);

sendMailMock = jest.fn();
jest.spyOn(nodemailer, 'createTransport').mockReturnValue({
sendMail: sendMailMock,
} as any);
});

//signUp
describe('signUp', () => {
it('should create a new user and return a signed token', async () => {
const signUpDto: SignUpDto = {
firstName: 'Test',
lastName: 'User',
email: '[email protected]',
phone: '123456789',
password: 'password',
password: 'ValidPassword123!', // Ensure the password meets the criteria
};

const user = new User();
user.id = '18ea976e-367b-4138-b68e-7aff3f7ae4de';
user.firstName = signUpDto.firstName;
user.lastName = signUpDto.lastName;
user.email = signUpDto.email;
user.phone = signUpDto.phone;
user.role = UserRoles.User;

jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(null);

jest.spyOn(userRepository, 'create').mockReturnValue(user);
jest.spyOn(userRepository, 'save').mockResolvedValue(user);
jest.spyOn(service, 'signIn').mockResolvedValue({
accessToken: 'access-token',
refreshToken: 'refresh-token',
});

const response = await service.signUp(signUpDto);

expect(userRepository.findOneBy).toHaveBeenCalledWith({
email: '[email protected]',
});

expect(userRepository.create).toHaveBeenCalledWith({
...signUpDto,
role: UserRoles.User,
password: expect.any(String),
});
expect(bcrypt.hash).toHaveBeenCalledWith('password', 10);
expect(bcrypt.hash).toHaveBeenCalledWith('ValidPassword123!', 10);
expect(userRepository.save).toHaveBeenCalled();
expect(response).toEqual({
accessToken: 'access-token',
refreshToken: 'refresh-token',
});
});

it('should throw an error if user already exists', async () => {
const signUpDto: SignUpDto = {
firstName: 'Test',
lastName: 'User',
email: '[email protected]',
phone: '123456789',
password: 'password',
password: 'ValidPassword123!', // Ensure the password meets the criteria
};

const existingUser = new User();
existingUser.email = 'existing@email.com';

existingUser.email = 'test@email.com';
jest
.spyOn(userRepository, 'findOneBy')
.mockResolvedValueOnce(existingUser);

try {
await service.signUp(signUpDto);
fail('An error should be thrown');
} catch (error) {
expect(error).toBeInstanceOf(UnauthorizedException);
expect((error as Error).message).toBe('Usuário já cadastrado.');
expect(userRepository.create).not.toHaveBeenCalled();
expect(userRepository.save).not.toHaveBeenCalled();
}

await expect(service.signUp(signUpDto)).rejects.toThrow(
UnauthorizedException,
);
expect((await service.signUp(signUpDto).catch(e => e)).message).toBe('Usuário já cadastrado.');
expect(userRepository.create).not.toHaveBeenCalled();
expect(userRepository.save).not.toHaveBeenCalled();
});
});

Expand All @@ -139,7 +138,7 @@ describe('AuthService', () => {
jest.spyOn(bcrypt, 'compare').mockResolvedValueOnce(false);

await expect(service.signIn({ email, password, role })).rejects.toThrow(
UnauthorizedException,
BadRequestException,
);

expect(userRepository.findOneBy).toHaveBeenCalledWith({ email, role });
Expand Down Expand Up @@ -208,41 +207,195 @@ describe('AuthService', () => {
});

describe('recoverPassword', () => {
it('should throw an UnauthorizedException if the user is not found', async () => {
const email = 'notfound@example.com';

it('should throw UnauthorizedException if the user is not found', async () => {
const email = 'nonexistent@example.com';
jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(null);
const signSpy = jest.spyOn(jwtService, 'signAsync');


await expect(service.recoverPassword(email)).rejects.toThrow(
UnauthorizedException,
);

expect(userRepository.findOneBy).toHaveBeenCalledWith({ email });
expect(signSpy).not.toHaveBeenCalled();
});

it('should handle errors during email sending', async () => {
const email = '[email protected]';
const user = new User();
user.id = '123';
user.email = email;

jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(user);
jest.spyOn(jwtService, 'signAsync').mockResolvedValueOnce('mocked-token');

sendMailMock.mockRejectedValueOnce(new Error('Email service error'));

await expect(service.recoverPassword(email)).rejects.toThrow(
'Email service error',
);
});
});

describe('signIn with keepLoggedIn', () => {
it('should return a token with 30m expiration when keepLoggedIn is false', async () => {
const signInDto: SignInDto = {
email: '[email protected]',
password: 'password',
role: UserRoles.User,
keepLoggedIn: false,
};
const user = new User();
user.id = 'user-id';
user.email = signInDto.email;
user.password = 'hashed-password';
user.role = UserRoles.User;

jest.spyOn(userRepository, 'findOneBy').mockResolvedValue(user);
jest.spyOn(bcrypt, 'compare').mockResolvedValue(true);
const signAsyncSpy = jest.spyOn(jwtService, 'signAsync');

const result = await service.signIn(signInDto);

expect(userRepository.findOneBy).toHaveBeenCalledWith({ email });
expect(jwtService.signAsync).toHaveBeenCalledWith(
{ sub: user.id },
expect(result.accessToken).toBeDefined();

expect(signAsyncSpy).toHaveBeenNthCalledWith(
1,
{ sub: user.id, email: user.email, role: user.role },
{ expiresIn: '30m' },
);
expect(sendMailMock).toHaveBeenCalled();
});

it('should return a token with 7d expiration when keepLoggedIn is true', async () => {
const signInDto: SignInDto = {
email: '[email protected]',
password: 'password',
role: UserRoles.User,
keepLoggedIn: true,
};
const user = new User();
user.id = 'user-id';
user.email = signInDto.email;
user.password = 'hashed-password';
user.role = UserRoles.User;

jest.spyOn(userRepository, 'findOneBy').mockResolvedValue(user);
jest.spyOn(bcrypt, 'compare').mockResolvedValue(true);
const signAsyncSpy = jest.spyOn(jwtService, 'signAsync');

const result = await service.signIn(signInDto);

expect(result.accessToken).toBeDefined();

expect(signAsyncSpy).toHaveBeenNthCalledWith(
1,
{ sub: user.id, email: user.email, role: user.role },
{ expiresIn: '7d' },
);
});
});

describe('generateAccessToken', () => {
it('should generate an access token with the given payload and expiration', async () => {
const payload = { sub: '123', email: '[email protected]', role: UserRoles.User };
const expiresIn = '30m';

jest.spyOn(jwtService, 'signAsync').mockResolvedValueOnce('access-token');

const result = await service.generateAccessToken(payload, expiresIn);

expect(result).toBe('access-token');
expect(jwtService.signAsync).toHaveBeenCalledWith(payload, { expiresIn });
});
});

describe('generateRefreshToken', () => {
it('should generate a refresh token with the given payload', async () => {
const payload = { sub: '123', email: '[email protected]', role: UserRoles.User };

jest.spyOn(jwtService, 'signAsync').mockResolvedValueOnce('refresh-token');

const result = await service.generateRefreshToken(payload);

expect(result).toBe('refresh-token');
expect(jwtService.signAsync).toHaveBeenCalledWith(payload);
});
});

describe('changePassword', () => {
it('should update the password if the user exists', async () => {
const userId = '123';
const newPassword = 'NewPassword123!';
const user = new User();
user.id = userId;
user.password = 'oldPassword';

jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(user);
jest.spyOn(bcrypt, 'hash').mockResolvedValueOnce('hashedNewPassword');
jest.spyOn(userRepository, 'save').mockResolvedValueOnce(user);

const result = await service.changePassword(userId, newPassword);

expect(result).toEqual({ success: true });
expect(bcrypt.hash).toHaveBeenCalledWith(newPassword, 10);
expect(userRepository.save).toHaveBeenCalledWith(user);
});

it('should throw UnauthorizedException if the user does not exist', async () => {
const userId = 'nonexistent';
const newPassword = 'NewPassword123!';

jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(null);

await expect(service.changePassword(userId, newPassword)).rejects.toThrow(
UnauthorizedException,
);
});
});

describe('validatePassword', () => {
it('should throw BadRequestException if password is less than 8 characters', async () => {
const shortPassword = 'Pass1!'; // 6 characters, missing length
await expect(() =>
(service as any).validatePassword(shortPassword),
).toThrowError(BadRequestException);
await expect(() =>
(service as any).validatePassword(shortPassword),
).toThrowError('A senha deve ter pelo menos 8 caracteres.');
});

it('should throw BadRequestException if password has no uppercase letter', async () => {
const noUppercasePassword = 'password1!'; // Missing uppercase
await expect(() =>
(service as any).validatePassword(noUppercasePassword),
).toThrowError(BadRequestException);
await expect(() =>
(service as any).validatePassword(noUppercasePassword),
).toThrowError('A senha deve conter pelo menos uma letra maiúscula.');
});

it('should throw BadRequestException if password has no number', async () => {
const noNumberPassword = 'Password!'; // Missing number
await expect(() =>
(service as any).validatePassword(noNumberPassword),
).toThrowError(BadRequestException);
await expect(() =>
(service as any).validatePassword(noNumberPassword),
).toThrowError('A senha deve conter pelo menos um número.');
});

it('should throw BadRequestException if password has no special character', async () => {
const noSpecialCharPassword = 'Password1'; // Missing special character
await expect(() =>
(service as any).validatePassword(noSpecialCharPassword),
).toThrowError(BadRequestException);
await expect(() =>
(service as any).validatePassword(noSpecialCharPassword),
).toThrowError('A senha deve conter pelo menos um caractere especial.');
});

it('should not throw an exception if password meets all criteria', async () => {
const validPassword = 'ValidPassword123!'; // Meets all criteria
expect(() =>
(service as any).validatePassword(validPassword),
).not.toThrow();
});
});
});

});
Loading
Loading