Skip to content

Commit

Permalink
fix(code-coverage): bumping code coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Yavorss committed Feb 20, 2024
1 parent 6fc6b03 commit c3a1077
Show file tree
Hide file tree
Showing 23 changed files with 445 additions and 94 deletions.
1 change: 1 addition & 0 deletions express-pg-auth0/src/api/auth/interfaces/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export type Auth0User = {
updated_at: string;
user_id: string;
user_metadata: Record<string, any>;
blocked: boolean;
};
25 changes: 25 additions & 0 deletions express-pg-auth0/src/api/auth/routes/register.route.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { registerRoute as route } from './register.route';

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

describe('handler', () => {
const authService = { register: jest.fn(() => ({ user: 'user' })) };
const req = {
auth: { payload: { sub: '1' } },

body: { name: 'Name' },
services: { authService },
};
const send = jest.fn();
const status = jest.fn(() => ({ send }));
const res = { send, status };

it('should call AuthService#register', () => {
route.handler(req as never, res as never, jest.fn());
expect(authService.register).toHaveBeenCalledWith({ name: 'Name' });
});
});
});
86 changes: 86 additions & 0 deletions express-pg-auth0/src/api/auth/services/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { User } from '@api/users';
import { AuthService } from './auth.service';
import { Auth0User, Credentials } from '../interfaces';

const userCreds: Credentials = {
email: '[email protected]',
password: 'very-secret',
};

const registeredUser: User = {
id: '1',
createdAt: Date.now().toString(),
updatedAt: Date.now().toString(),
email: userCreds.email,
password: 'very-secret',
userId: '1',
};

const auth0User: Auth0User = {
blocked: false,
created_at: Date.now().toString(),
email: userCreds.email,
email_verified: true,
identities: [],
name: 'userName',
nickname: 'userNickname',
picture: '',
updated_at: Date.now().toString(),
user_id: '1',
user_metadata: {},
};

describe('AuthService', () => {
const logger = {
warn: jest.fn(),
error: jest.fn(),
} as any;

const auth0Service = {
createUser: jest.fn(),
deleteUser: jest.fn(),
updateUserMetadata: jest.fn(),
} as any;

const usersRepository = {
insertOne: jest.fn(),
} as any;

const authService = new AuthService(logger, auth0Service, usersRepository);

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

describe('register', () => {
it('when the email is not registered should register the user', async () => {
const createdUser = { ...registeredUser, ...userCreds };
auth0Service.createUser.mockResolvedValueOnce(auth0User);
usersRepository.insertOne.mockResolvedValueOnce(createdUser);
auth0Service.updateUserMetadata.mockResolvedValueOnce(auth0User as any);

const user = await authService.register(userCreds);

expect(auth0Service.updateUserMetadata).toHaveBeenCalledWith(auth0User.user_id, {
id: createdUser.id
});

expect(user).toEqual({
email: userCreds.email,
userId: auth0User.user_id,
});
});

it('throws error when creating a user in the database fails', async () => {
auth0Service.createUser.mockResolvedValueOnce(auth0User);
usersRepository.insertOne.mockRejectedValueOnce({ error: 'error' });
auth0Service.deleteUser.mockResolvedValueOnce(auth0User as any);

await expect(authService.register(userCreds)).rejects.toThrow();

expect(logger.warn).toHaveBeenCalledWith('Creating a user in the database failed. Proceeding with deleting it in Auth0.');
expect(auth0Service.deleteUser).toHaveBeenCalledWith(auth0User.user_id);

});
});
});
213 changes: 213 additions & 0 deletions express-pg-auth0/src/api/auth/services/auth0.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import { AxiosStatic } from 'axios';
import { Auth0User, Credentials } from '../interfaces';
import { Auth0Service } from './auth0.service';
import { Logger } from 'pino';
import { Environment } from '@utils/environment';

const userCreds: Credentials = {
email: '[email protected]',
password: 'very-secret',
};

const auth0User: Auth0User = {
blocked: false,
created_at: Date.now().toString(),
email: userCreds.email,
email_verified: true,
identities: [],
name: 'userName',
nickname: 'userNickname',
picture: '',
updated_at: Date.now().toString(),
user_id: '1',
user_metadata: {},
};

describe('Auth0Service', () => {
let auth0Service: Auth0Service;
let axios: AxiosStatic;
let logger: Logger;
let env: Environment;

beforeAll(() => {
logger = { error: jest.fn() } as any;
axios = {
post: jest.fn(),
patch: jest.fn(),
get: jest.fn(),
delete: jest.fn(),
} as any;
env = {} as any;
});

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

describe('createUser', () => {
beforeEach(() => {
auth0Service = new Auth0Service(logger, axios, env);
jest
.spyOn(auth0Service, 'getAuth0AccessToken')
.mockResolvedValue('token');
});

it('when the email is not registered should register the user', async () => {
jest
.spyOn(auth0Service, 'searchUsersByEmail')
.mockResolvedValueOnce([] as unknown as Auth0User);
jest
.spyOn(axios, 'post')
.mockResolvedValueOnce(Promise.resolve({ data: auth0User }));

const user = await auth0Service.createUser(
userCreds.email,
userCreds.password
);

expect(user).toEqual(auth0User);
});

it('throws error when user is already registered', async () => {
jest
.spyOn(auth0Service, 'searchUsersByEmail')
.mockResolvedValueOnce([auth0User] as unknown as Auth0User);

await expect(
auth0Service.createUser(userCreds.email, userCreds.password)
).rejects.toThrow(new Error('A user with this email already exists.'));
});

it('throws error when auth0 request fails', async () => {
jest
.spyOn(auth0Service, 'searchUsersByEmail')
.mockResolvedValueOnce([] as unknown as Auth0User);
jest
.spyOn(axios, 'post')
.mockRejectedValueOnce({ response: { data: {} } });

await expect(
auth0Service.createUser(userCreds.email, userCreds.password)
).rejects.toThrow();
});
});

describe('updateUserMetadata', () => {
beforeEach(() => {
auth0Service = new Auth0Service(logger, axios, env);
jest
.spyOn(auth0Service, 'getAuth0AccessToken')
.mockResolvedValue('token');
});

it('should updateUserMetadata updates metadata', async () => {
const newMetadata = { data: 'new' };
jest
.spyOn(axios, 'patch')
.mockResolvedValueOnce({ ...auth0User, user_metadata: newMetadata });

const user = await auth0Service.updateUserMetadata('1', newMetadata);

expect(user).toEqual({ ...auth0User, user_metadata: newMetadata });
});
});

describe('searchUsersByEmail', () => {
beforeEach(() => {
auth0Service = new Auth0Service(logger, axios, env);
jest
.spyOn(auth0Service, 'getAuth0AccessToken')
.mockResolvedValue('token');
});

it('when the user is found', async () => {
jest.spyOn(axios, 'get').mockResolvedValueOnce({ data: auth0User });

const user = await auth0Service.searchUsersByEmail(auth0User.email);

expect(user).toEqual(auth0User);
});

it('throws error when user is not found', async () => {
jest
.spyOn(axios, 'get')
.mockRejectedValueOnce({ response: { data: {} } });

await expect(
auth0Service.searchUsersByEmail(auth0User.email)
).rejects.toThrow();
});
});

describe('deleteUser', () => {
beforeEach(() => {
auth0Service = new Auth0Service(logger, axios, env);
jest
.spyOn(auth0Service, 'getAuth0AccessToken')
.mockResolvedValue('token');
});

it('when user is deleted', async () => {
jest.spyOn(axios, 'delete').mockResolvedValueOnce({});

const response = await auth0Service.deleteUser(auth0User.user_id);

expect(response).toEqual({});
});

it('throws error when auth0 request fails', async () => {
jest
.spyOn(axios, 'delete')
.mockRejectedValueOnce({ response: { data: {} } });

await expect(
auth0Service.deleteUser(auth0User.user_id)
).rejects.toThrow();
});
});

describe('getAuth0AccessToken', () => {
beforeEach(() => {
auth0Service = new Auth0Service(logger, axios, env);
});

it('when accessToken is set', async () => {
const tokenResponse = { data: { access_token: 'token' } };
jest.spyOn(axios, 'post').mockResolvedValueOnce(tokenResponse);

auth0Service.getAuth0AccessToken();

// expect(onModuleInit).toHaveBeenCalled();
});

it('throws error accessToken is missing', async () => {
const tokenResponse = { data: {} };
jest.spyOn(axios, 'post').mockResolvedValueOnce(tokenResponse);

await expect(auth0Service.getAuth0AccessToken()).rejects.toThrow(
new Error('Access token is missing!')
);
expect(logger.error).toHaveBeenCalledWith(
'Access token is missing in the response data'
);
});

it('throws error when axios response is falsy(undefined)', async () => {
jest.spyOn(axios, 'post').mockResolvedValueOnce(undefined);

await expect(auth0Service.getAuth0AccessToken()).rejects.toThrow(
new Error('Access token is missing!')
);
});

it('throws error when auth0 token request fails', async () => {
jest
.spyOn(axios, 'post')
.mockRejectedValueOnce({ response: { data: {} } });

await expect(auth0Service.getAuth0AccessToken()).rejects.toThrow(
new Error('Something went wrong!')
);
});
});
});
Loading

0 comments on commit c3a1077

Please sign in to comment.