Skip to content

Commit

Permalink
Merge pull request #7 from olaviolacerda/feature/testing-unit
Browse files Browse the repository at this point in the history
Feature/testing unit
  • Loading branch information
olaviolacerda authored Mar 1, 2024
2 parents 47ea1cb + 374d795 commit b8137ea
Show file tree
Hide file tree
Showing 6 changed files with 317 additions and 42 deletions.
4 changes: 3 additions & 1 deletion src/core/providers/services/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class UsersService {

const createdUser = await this.usersRepository.create(createUserDto);
const savedUser = await this.usersRepository.save(createdUser);

return this.prepareUserResponse(savedUser);
}

Expand Down Expand Up @@ -73,7 +74,8 @@ export class UsersService {
throw new NotFoundException(`User with id ${id} does not exist`);
}

return this.usersRepository.save(user);
const savedUser = await this.usersRepository.save(user);
return this.prepareUserResponse(savedUser);
}

async remove(id: User['id']) {
Expand Down
10 changes: 10 additions & 0 deletions test/unit/mocks/auth.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { JwtService } from '@nestjs/jwt';

export const mockTokens = {
accessToken: 'fakeJwtToken',
refreshToken: 'fakeJwtToken',
};

export const mockJwtService: Partial<JwtService> = {
signAsync: jest.fn().mockResolvedValue('fakeJwtToken'),
};
20 changes: 20 additions & 0 deletions test/unit/mocks/users.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Role } from '../../../src/common/enums/role.enum';
import { User } from '../../../src/core/entities/user.entity';

export const mockUser: User = {
id: 'id',
username: 'fake',
role: Role.User,
refreshToken: 'refreshToken',
password: 'fakePass',
hashPassword: () => Promise.resolve(),
};

export class UsersRepositoryFake {
public async create(): Promise<any> {}
public async save(): Promise<any> {}
public async remove(): Promise<any> {}
public async findOne(): Promise<any> {}
public async find(): Promise<any> {}
public async preload(): Promise<any> {}
}
37 changes: 37 additions & 0 deletions test/unit/providers/helpers/auth.helper.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { AuthHelper } from '../../../../src/core/providers/helpers/auth.helper';

jest.mock('bcrypt', () => ({
async hashSync(): Promise<string> {
return 'hash';
},
}));

jest.mock('crypto', () => ({
createHash: jest.fn().mockReturnValue({
update: jest.fn().mockReturnThis(),
digest: jest.fn(),
}),
}));

describe('AuthHelper', () => {
let helper: AuthHelper;

beforeEach(async () => {
helper = new AuthHelper();
});

afterEach(() => {
jest.clearAllMocks();
});

it('should be defined', () => {
expect(helper).toBeDefined();
});

it('should hash token', async () => {
const refreshToken = 'refreshToken';
const hashedToken = await helper.hashToken(refreshToken);

expect(hashedToken).toBe('hash');
});
});
70 changes: 30 additions & 40 deletions test/unit/providers/services/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ import { ConfigService } from '@nestjs/config';
import { AuthService } from '../../../../src/core/providers/services/auth.service';
import { UsersService } from '../../../../src/core/providers/services/users.service';
import { User } from '../../../../src/core/entities/user.entity';
import { Role } from '../../../../src/common/enums/role.enum';
import { AuthHelper } from '../../../../src/core/providers/helpers/auth.helper';

const mockJwtService: Partial<JwtService> = {
signAsync: jest.fn().mockResolvedValue('fakeJwtToken'),
};
import { mockJwtService, mockTokens } from '../../mocks/auth.mock';
import { UsersRepositoryFake, mockUser } from '../../mocks/users.mock';

let compareResponse = true;

Expand All @@ -24,14 +21,6 @@ jest.mock('bcrypt', () => ({
},
}));

const mockUser: Partial<User> = {
id: 'id',
username: 'fake',
role: Role.User,
refreshToken: 'refreshToken',
password: 'fakePass',
};

describe('AuthService', () => {
let service: AuthService;
let usersService: UsersService;
Expand All @@ -50,13 +39,7 @@ describe('AuthService', () => {
UsersService,
{
provide: getRepositoryToken(User),
useValue: {
preload: jest.fn().mockResolvedValue(mockUser),
find: jest.fn().mockResolvedValue(mockUser),
findOne: jest.fn().mockResolvedValue(mockUser),
findByUsername: jest.fn().mockResolvedValue(mockUser),
save: jest.fn(),
},
useClass: UsersRepositoryFake,
},
ConfigService,
AuthHelper,
Expand All @@ -80,29 +63,28 @@ describe('AuthService', () => {

it('should login a registered user', async () => {
const payload = { id: mockUser.id, role: mockUser.role };
const hashedRefreshToken = 'hashedRefreshToken';
const spyUserUpdate = jest.spyOn(usersService, 'update');
const spyHashToken = jest
.spyOn(authHelper, 'hashToken')
.mockResolvedValue(hashedRefreshToken);
const spyGetTokens = jest
.spyOn(service, 'getTokens')
.mockResolvedValue(mockTokens);
const spyUpdateRefreshToken = jest
.spyOn(service, 'updateRefreshToken')
.mockImplementation(() => Promise.resolve());

const result = await service.login(payload);

expect(spyHashToken).toHaveBeenCalledWith('fakeJwtToken');
expect(spyUserUpdate).toHaveBeenCalled();
expect(spyUserUpdate).toHaveBeenCalledWith(payload.id, {
refreshToken: hashedRefreshToken,
});
expect(mockJwtService.signAsync).toHaveBeenCalled();
expect(result).toEqual({
accessToken: 'fakeJwtToken',
refreshToken: 'fakeJwtToken',
});
expect(spyGetTokens).toHaveBeenCalledWith(payload);
expect(spyUpdateRefreshToken).toHaveBeenCalledWith(
payload.id,
result.refreshToken,
);
expect(result).toEqual(mockTokens);
});

it('should logout a logged user', async () => {
const userId = mockUser.id;
const spyUserServiceUpdate = jest.spyOn(usersService, 'update');
const spyUserServiceUpdate = jest
.spyOn(usersService, 'update')
.mockResolvedValue(mockUser);

await service.logout(userId);

Expand All @@ -117,11 +99,13 @@ describe('AuthService', () => {
userId: mockUser.id,
refreshToken: mockUser.refreshToken,
};
const spyUserServiceUpdate = jest.spyOn(usersService, 'update');
const hashedRefreshToken = 'hashedRefreshToken';
const spyHashToken = jest
.spyOn(authHelper, 'hashToken')
.mockResolvedValue(hashedRefreshToken);
const spyUserServiceUpdate = jest
.spyOn(usersService, 'update')
.mockResolvedValue({ refreshToken: hashedRefreshToken, ...mockUser });

await service.updateRefreshToken(payload.userId, payload.refreshToken);

Expand All @@ -138,7 +122,9 @@ describe('AuthService', () => {
accessToken: fakeToken,
refreshToken: fakeToken,
});
const spyUpdateRefreshToken = jest.spyOn(service, 'updateRefreshToken');
const spyUpdateRefreshToken = jest
.spyOn(service, 'updateRefreshToken')
.mockImplementation(() => Promise.resolve());
const tokens = await service.refreshTokens(payload);

expect(spyGetTokens).toHaveBeenCalledWith(payload);
Expand Down Expand Up @@ -178,7 +164,9 @@ describe('AuthService', () => {

it('should validate user', async () => {
const payload = { username: mockUser.username, pass: mockUser.password };
const spyFindByUsername = jest.spyOn(usersService, 'findByUsername');
const spyFindByUsername = jest
.spyOn(usersService, 'findByUsername')
.mockResolvedValue(mockUser);

const user = await service.validateUser(payload.username, payload.pass);

Expand All @@ -191,7 +179,9 @@ describe('AuthService', () => {

it("should NOT validate user if passwords doesn't matches", async () => {
const payload = { username: mockUser.username, pass: mockUser.password };
const spyFindByUsername = jest.spyOn(usersService, 'findByUsername');
const spyFindByUsername = jest
.spyOn(usersService, 'findByUsername')
.mockResolvedValue(mockUser);
compareResponse = false;

const user = await service.validateUser(payload.username, payload.pass);
Expand Down
Loading

0 comments on commit b8137ea

Please sign in to comment.