diff --git a/jest.config.js b/jest.config.js index 4298710..064b6fd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -26,6 +26,7 @@ module.exports = { '!src/index.ts', '!src/app.ts', '!src/database/index.ts', + '!src/database/seeders', '!src/modules/app/**', '!src/config/**', ], diff --git a/src/modules/authentication/__test__/authentication.spec.ts b/src/modules/authentication/__test__/authentication.spec.ts index 7f650c4..7d7fbfe 100644 --- a/src/modules/authentication/__test__/authentication.spec.ts +++ b/src/modules/authentication/__test__/authentication.spec.ts @@ -7,15 +7,15 @@ import logger from '../../../config/logger'; import { signUpMock, - // loginMock, - // invalidLoginMock, + loginMock, + invalidLoginMock, emptySignupNameField, invalidSignupEmailInput, invalidSignupPasswordInput, allSignupFieldsEmpty, - // invalidLoginEmailInput, - // invalidLoginPasswordInput, - // allLoginFieldsEmpty, + invalidLoginEmailInput, + invalidLoginPasswordInput, + allLoginFieldsEmpty, } from '../../user/__test__/__mocks__/mockUsers'; import User from '../../../database/models/User'; @@ -112,65 +112,63 @@ describe('TEST SUITE FOR USER ONBOARDING AND AUTHENTICATION', () => { done(); }); - // it('should successfully sign in a user', async (done) => { - // const response = await request.post(`${baseUrl}/auth`).send(loginMock); - - // expect(response.status).toEqual(200); - // expect(response.body.success).toEqual(true); - // expect(response.body.message).toEqual('You have successfully logged in'); - // expect(response.body.user.email).toEqual(loginMock.email); - // done(); - // }); - - // it('should not sign in a non-existing user', async (done) => { - // const response = await request.post(`${baseUrl}/auth`).send(invalidLoginMock); - - // expect(response.status).toEqual(404); - // expect(response.body.success).toEqual(false); - // expect(response.body.message).toEqual('The email or password is not correct'); - // done(); - // }); - - // it('should validate login email field', async (done) => { - // const response = await request - // .post(`${baseUrl}/auth`) - // .send(invalidLoginEmailInput); - - // expect(response.status).toEqual(422); - // expect(response.body.success).toEqual(false); - // expect(response.body.message).toEqual('Validation Errors'); - // expect(response.body.errors).toEqual({ - // email: ['email is not allowed to be empty'], - // }); - // done(); - // }); - - // it('should validate login password field', async (done) => { - // const response = await request - // .post(`${baseUrl}/auth`) - // .send(invalidLoginPasswordInput); - - // expect(response.status).toEqual(422); - // expect(response.body.success).toEqual(false); - // expect(response.body.message).toEqual('Validation Errors'); - // expect(response.body.errors).toEqual({ - // password: ['password is not allowed to be empty'], - // }); - // done(); - // }); - - // it('should validate signup all fields concurrently', async (done) => { - // const response = await request.post(`${baseUrl}/auth`).send(allLoginFieldsEmpty); - - // expect(response.status).toEqual(422); - // expect(response.body.success).toEqual(false); - // expect(response.body.message).toEqual('Validation Errors'); - // expect(response.body.errors).toEqual({ - // email: ['email is not allowed to be empty'], - // password: ['password is not allowed to be empty'], - // }); - // done(); - // }); + it('should successfully sign in a user', async (done) => { + const response = await request.post(`${baseUrl}/auth`).send(loginMock); + + expect(response.status).toEqual(200); + expect(response.body.success).toEqual(true); + done(); + }); + + it('should not sign in a non-existing user', async (done) => { + const response = await request.post(`${baseUrl}/auth`).send(invalidLoginMock); + + expect(response.status).toEqual(400); + expect(response.body.success).toEqual(false); + expect(response.body.error).toEqual('Invalid login details'); + done(); + }); + + it('should validate login email field', async (done) => { + const response = await request + .post(`${baseUrl}/auth`) + .send(invalidLoginEmailInput); + + expect(response.status).toEqual(422); + expect(response.body.success).toEqual(false); + expect(response.body.message).toEqual('Validation Errors'); + expect(response.body.errors).toEqual({ + email: ['email is not allowed to be empty'], + }); + done(); + }); + + it('should validate login password field', async (done) => { + const response = await request + .post(`${baseUrl}/auth`) + .send(invalidLoginPasswordInput); + + expect(response.status).toEqual(422); + expect(response.body.success).toEqual(false); + expect(response.body.message).toEqual('Validation Errors'); + expect(response.body.errors).toEqual({ + password: ['password is not allowed to be empty'], + }); + done(); + }); + + it('should validate signup all fields concurrently', async (done) => { + const response = await request.post(`${baseUrl}/auth`).send(allLoginFieldsEmpty); + + expect(response.status).toEqual(422); + expect(response.body.success).toEqual(false); + expect(response.body.message).toEqual('Validation Errors'); + expect(response.body.errors).toEqual({ + email: ['email is not allowed to be empty'], + password: ['password is not allowed to be empty'], + }); + done(); + }); }); describe('AUTHENTICATION CONTROLLER UNIT TESTS', () => { @@ -209,10 +207,10 @@ describe('AUTHENTICATION CONTROLLER UNIT TESTS', () => { done(); }); - // it("calls status and json methods to generate response when login in", async (done) => { - // await UnmockedAuthController.loginUser(req, res); - // expect(status).toHaveBeenCalledTimes(1); - // expect(json).toHaveBeenCalledTimes(1); - // done(); - // }); + it("calls status and json methods to generate response when login in", async (done) => { + await UnmockedAuthController.loginUser(req, res); + expect(status).toHaveBeenCalledTimes(1); + expect(json).toHaveBeenCalledTimes(1); + done(); + }); }); diff --git a/src/modules/authentication/authentication.controller.ts b/src/modules/authentication/authentication.controller.ts index c48bfa6..f6fc2b1 100644 --- a/src/modules/authentication/authentication.controller.ts +++ b/src/modules/authentication/authentication.controller.ts @@ -1,9 +1,10 @@ import { Request, Response } from 'express'; -// import _ from 'underscore'; +import _ from 'underscore'; import Utils from '../../utils/utils'; import Error from '../../utils/Error'; import UserRepository from '../user/user.repository'; +import { User } from '../../@types/express'; // import { UserType } from '../user/interfaces/User'; const { @@ -37,12 +38,11 @@ export default class AuthController { request: Request, response: Response, ): Promise>> { - const { email, password } = request.body; try { + const { email, password } = request.body; const isUserExists = await UserRepository.findByEmail(email); - if (isUserExists) { - return Error.handleError("Email already in use", 403, response); + return Error.handleError('Email already in use', 403, response); } const hashedPassword = await hashPassword(password); @@ -52,63 +52,47 @@ export default class AuthController { password: hashedPassword, }); - return response.status(201).json({ - message: "User added successfully", - token: Utils.generateAuthToken({ sub: user.email }), - success: true, - }); + return response.status(201).json({ + message: 'User added successfully', + token: Utils.generateAuthToken({ sub: user.email, admin: user.admin }), + success: true, + }); } catch (error) { return Error.handleError('Server error', 500, response, error); } } - // /** - // * Returns success:true and token if verification was successful and error if not - // * @name /auth POST - // * @param request {Object} The request. - // * @param response {Object} The response. - // * @param req.body {Object} The JSON payload. - // * @remarks - // * - This function accepts two parameters, request, and response - // * You can follow the file trail to have a better understanding of how the function works. - // * - // * @function - // * @returns {Boolean} success - // * - // */ - // static async loginUser(request: Request, response: Response): Promise { - // const { email, password } = request.body; - // const user: any = await UserRepository.findByEmail(email); - - // try { - // if (!user || !comparePassword(user.password, password)) { - // return response.status(404).json({ - // success: false, - // message: 'The email or password is not correct', - // }); - // } - - // const token: string = generateToken({ - // sub: user.email, - // admin: user.admin, - // }); + /** + * Returns success:true and token if verification was successful and error if not + * @name /auth POST + * @param request {Object} The request. + * @param response {Object} The response. + * @param req.body {Object} The JSON payload. + * @remarks + * - This function accepts two parameters, request, and response + * You can follow the file trail to have a better understanding of how the function works. + * + * @function + * @returns {Boolean} success + * + */ + static async loginUser(request: Request, response: Response): Promise { + try { + const { email, password } = request.body; + const user: User | null = await UserRepository.findByEmail(email); - // const authenticatedUser = _.omit( - // user.toJSON(), - // 'password', - // '__v', - // 'admin', - // 'date', - // ); + if (!user || !Utils.passwordsMatch(password, user.password)) { + return Error.handleError("Invalid login details", 400, response); + } - // response.status(200).json({ - // success: true, - // message: 'You have successfully logged in', - // user: authenticatedUser, - // token, - // }); - // } catch (error) { - // return errorHandler(error, 500, response); - // } - // } + const token: string = Utils.generateAuthToken({ + sub: user.email, + admin: user.admin, + }); + + return response.status(200).json({ success: true, token }); + } catch (error) { + return Error.handleError('Server error', 500, response, error); + } + } } diff --git a/src/modules/authentication/index.ts b/src/modules/authentication/index.ts index efb7839..10be631 100644 --- a/src/modules/authentication/index.ts +++ b/src/modules/authentication/index.ts @@ -6,15 +6,9 @@ import Middlewares from '../../middleware'; const authRouter: Router = Router(); +const { createUser, loginUser } = AuthController; const { - createUser, - // loginUser -} = AuthController; -const { - UserSchema: { - signupSchema, - // loginSchema - }, + UserSchema: { signupSchema, loginSchema }, } = Schemas; const { Validator: { validateRequest }, @@ -26,6 +20,6 @@ authRouter.post( createUser, ); -// authRouter.post('/auth', validateRequest(loginSchema(), 'body'), loginUser); +authRouter.post('/auth', validateRequest(loginSchema(), 'body'), loginUser); export default authRouter; diff --git a/src/utils/schema/index.ts b/src/utils/schema/index.ts index 789c526..70aa715 100644 --- a/src/utils/schema/index.ts +++ b/src/utils/schema/index.ts @@ -1,4 +1,4 @@ -import UserSchema from './user'; +import UserSchema from './user.schema'; import SupportRequestSchema from './support-request.schema'; import CommentSchema from './comment.schema'; diff --git a/src/utils/schema/user.ts b/src/utils/schema/user.schema.ts similarity index 64% rename from src/utils/schema/user.ts rename to src/utils/schema/user.schema.ts index 8df5a0c..88e5ba2 100644 --- a/src/utils/schema/user.ts +++ b/src/utils/schema/user.schema.ts @@ -11,10 +11,10 @@ export default class UserSchema { }); } - // static loginSchema() { - // return Joi.object({ - // email: BaseSchema.email().required(), - // password: Joi.string().required(), - // }); - // } + static loginSchema() { + return Joi.object({ + email: BaseSchema.email().required(), + password: Joi.string().required(), + }); + } }