Skip to content

Commit

Permalink
Merge pull request #3 from fga-eps-mds/unitytest
Browse files Browse the repository at this point in the history
Unitytest
  • Loading branch information
Matheusafonsouza authored Jan 10, 2025
2 parents fca369f + d80a3ec commit 04ccca2
Show file tree
Hide file tree
Showing 4 changed files with 364 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/dist
/node_modules
/build
package-lock.json


# Logs
logs
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sonar.projectName=2024.2-LIVRO-LIVRE-USERS
sonar.host.url=https://sonarcloud.io
sonar.language=ts
sonar.sources=src
sonar.exclusions=src/__tests__/**, **/metrics/*.py, vite.config.ts, .vitest.config.js, dist/
sonar.exclusions=**/metrics/*.py, dist/, src/database/migrations/*.ts, **/*.spec.ts
sonar.tests=src
sonar.test.inclusions=**/*.test.tsx,**/*.test.ts
sonar.javascript.lcov.reportPaths=coverage/lcov.info
Expand Down
233 changes: 222 additions & 11 deletions src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,246 @@
import { Repository } from 'typeorm';
import { Test, TestingModule } from '@nestjs/testing';
import { AuthService } from './auth.service';
import { getRepositoryToken } from '@nestjs/typeorm';
import { User } from '../database/entities/user.entity';
import { User, UserRoles } from '../database/entities/user.entity';
import { JwtService } from '@nestjs/jwt';
import { SignUpDto } from '../auth/dtos/signUp.dto';
import * as bcrypt from 'bcryptjs';
import { repositoryMockFactory } from '../../test/database/utils';
import { JwtModule } from '@nestjs/jwt';
import { jwtContants } from './auth.constants';
import { UnauthorizedException } from '@nestjs/common';
import * as nodemailer from 'nodemailer';

describe('AuthService', () => {
let service: AuthService;
let userRepository: Repository<User>;
let jwtService: JwtService;
let sendMailMock: jest.Mock;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
JwtModule.register({
global: true,
secret: jwtContants.secret,
}),
],
providers: [
AuthService,
{
provide: getRepositoryToken(User),
useFactory: repositoryMockFactory,
},
{
provide: JwtService,
useValue: {
signAsync: jest.fn(async (payload) => {
if (payload) {
return 'access-token';
}
throw new Error('Payload não fornecido');
}),
verifyAsync: jest.fn(async () => 'refresh-token'),
},
},
],
}).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);

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

it('should be defined', () => {
expect(service).toBeDefined();
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',
};

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(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',
};

const existingUser = new User();
existingUser.email = '[email protected]';

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();
}
});
});

describe('signIn', () => {
it('should throw an UnauthorizedException for invalid credentials', async () => {
const email = '[email protected]';
const password = 'wrongPassword';
const user = new User();
user.email = email;
user.password = 'hashedPassword';

jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(user);
jest.spyOn(bcrypt, 'compare').mockResolvedValueOnce(false);

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

expect(userRepository.findOneBy).toHaveBeenCalledWith({ email });
expect(bcrypt.compare).toHaveBeenCalledWith(password, user.password);
});

it('should return a signed token on successful login', async () => {
const email = '[email protected]';
const password = 'validPassword';
const user = new User();
user.id = '18ea976e-367b-4138-b68e-7aff3f7ae4de';
user.email = email;
user.password = await bcrypt.hash(password, 10);
user.role = UserRoles.User;

const payload = { sub: user.id, email, role: user.role };

jest.spyOn(userRepository, 'findOneBy').mockResolvedValueOnce(user);
jest.spyOn(bcrypt, 'compare').mockResolvedValueOnce(true);

const response = await service.signIn({ email, password });

expect(response).toEqual({
accessToken: 'access-token',
refreshToken: 'access-token',
});

expect(userRepository.findOneBy).toHaveBeenCalledWith({ email });
expect(bcrypt.compare).toHaveBeenCalledWith(password, user.password);
expect(jwtService.signAsync).toHaveBeenCalledTimes(2);
expect(jwtService.signAsync).toHaveBeenCalledWith(payload);
});
});

describe('getProfile', () => {
it('should return the user profile when user exists', async () => {
const userId = '123';
const user = new User();
user.id = userId;

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

const result = await service.getProfile({
sub: userId,
email: '[email protected]',
});

expect(result).toBe(user);
expect(userRepository.findOneBy).toHaveBeenCalledWith({ id: userId });
});

it('should return null when user does not exist', async () => {
const userId = '123';

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

const result = await service.getProfile({
sub: userId,
email: '[email protected]',
});

expect(result).toBeNull();
expect(userRepository.findOneBy).toHaveBeenCalledWith({ id: userId });
});
});

describe('recoverPassword', () => {
it('should throw an UnauthorizedException if the user is not found', async () => {
const email = '[email protected]';

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',
);

expect(userRepository.findOneBy).toHaveBeenCalledWith({ email });
expect(jwtService.signAsync).toHaveBeenCalledWith(
{ sub: user.id },
{ expiresIn: '30m' },
);
expect(sendMailMock).toHaveBeenCalled();
});
});
});
Loading

0 comments on commit 04ccca2

Please sign in to comment.