Skip to content

Commit

Permalink
Merge pull request #912 from OneCommunityGlobal/Anirudh_loginmethod_u…
Browse files Browse the repository at this point in the history
…nittest

Anirudh loginmethod unittest
  • Loading branch information
one-community authored Jun 29, 2024
2 parents 75b3b1f + 35f9004 commit 9bd36d1
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 32 deletions.
9 changes: 9 additions & 0 deletions requirements/logincontroller/getUser-usecase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Check mark: ✅
Cross Mark: ❌

# GetUser

> ## Positive case
1. ❌ Receives a POST request in the **/api/userProfile** route
2. ✅ Returns **200**, with the requestor body
21 changes: 21 additions & 0 deletions requirements/logincontroller/login-usecase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Check mark: ✅
Cross Mark: ❌

# login

> ## Positive case
1. ❌ Receives a POST request in the **/api/userProfile** route
2. ✅ Returns 200, if the user is a new user and there is a password match
3. ✅ Returns 200, if the user already exists and the password is a match

## Negative case

1. ✅ Returns error 400 if there is no email or password
2. ✅ Returns error 403 if there is no user
3. ✅ Returns error 403 if the user exists but is not active
4. ✅ Returns error 403 if the password is not a match and if the user already exists - in progress

## Edge case

1. ✅ Returns the error if the try block fails - in progress
66 changes: 34 additions & 32 deletions src/controllers/logincontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ const logincontroller = function () {
if (!user) {
res.status(403).send({ message: 'Username not found.' });
} else if (user.isActive === false) {
res.status(403).send({ message: 'Sorry, this account is no longer active. If you feel this is in error, please contact your Manager and/or Administrator.' });
res.status(403).send({
message:
'Sorry, this account is no longer active. If you feel this is in error, please contact your Manager and/or Administrator.',
});
} else {
let isPasswordMatch = false;
let isNewUser = false;
Expand All @@ -34,42 +37,42 @@ const logincontroller = function () {
isPasswordMatch = await bcrypt.compare(_password, user.password);

if (!isPasswordMatch && user.resetPwd !== '') {
isPasswordMatch = (_password === user.resetPwd);
isPasswordMatch = _password === user.resetPwd;
isNewUser = true;
}

if (isNewUser && isPasswordMatch) {
const result = {
new: true,
userId: user._id,
};
res.status(200).send(result);
} else if (isPasswordMatch && !isNewUser) {
const jwtPayload = {
userid: user._id,
role: user.role,
permissions: user.permissions,
access: {
canAccessBMPortal: false,
},
email: user.email,
expiryTimestamp: moment().add(config.TOKEN.Lifetime, config.TOKEN.Units),
};
if (isNewUser && isPasswordMatch) {
const result = {
new: true,
userId: user._id,
};
res.status(200).send(result);
} else if (isPasswordMatch && !isNewUser) {
const jwtPayload = {
userid: user._id,
role: user.role,
permissions: user.permissions,
access: {
canAccessBMPortal: false,
},
email: user.email,
expiryTimestamp: moment().add(config.TOKEN.Lifetime, config.TOKEN.Units),
};

const token = jwt.sign(jwtPayload, JWT_SECRET);
const token = jwt.sign(jwtPayload, JWT_SECRET);

res.status(200).send({ token });
} else {
res.status(403).send({
message: 'Invalid password.',
});
}
res.status(200).send({ token });
} else {
res.status(403).send({
message: 'Invalid password.',
});
}
}
} catch (err) {
console.log(err);
res.json(err);
}
};
} catch (err) {
console.log(err);
res.json(err);
}
};

const getUser = function (req, res) {
const { requestor } = req.body;
Expand All @@ -78,7 +81,6 @@ const logincontroller = function () {
};

return {

login,
getUser,
};
Expand Down
211 changes: 211 additions & 0 deletions src/controllers/logincontroller.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });
const bcrypt = require('bcryptjs');
const logincontroller = require('./logincontroller');
const { mockReq, mockRes, assertResMock, mockUser } = require('../test');
const userProfile = require('../models/userProfile');

const makeSut = () => {
const { login, getUser } = logincontroller();
return {
login,
getUser,
};
};

describe('logincontroller module', () => {
afterEach(() => {
jest.clearAllMocks();
});

describe('login', () => {
test('Ensure login returns error 400 if there is no email or password', async () => {
const { login } = makeSut();
const mockReqModified = {
...mockReq,
...{
body: {
email: '',
password: '',
},
},
};
const res = await login(mockReqModified, mockRes);
assertResMock(400, { error: 'Invalid request' }, res, mockRes);
});

test('Ensure login returns error 403 if there is no user', async () => {
const { login } = makeSut();
const mockReqModified = {
...mockReq,
...{
body: {
email: '[email protected]',
password: 'exampletest',
},
},
};
const findOneSpy = jest
.spyOn(userProfile, 'findOne')
.mockImplementation(() => Promise.resolve(null));

const res = await login(mockReqModified, mockRes);
expect(findOneSpy).toHaveBeenCalledWith({ email: mockReqModified.body.email });
assertResMock(403, { message: 'Username not found.' }, res, mockRes);
});

test('Ensure login returns error 403 if the user exists but is not active', async () => {
const { login } = makeSut();
const mockReqModified = {
...mockReq,
...{
body: {
email: '[email protected]',
password: 'exampletest',
},
},
};
const mockUserModified = {
...mockUser,
...{
isActive: false,
},
};

const findOneSpy = jest
.spyOn(userProfile, 'findOne')
.mockImplementation(() => Promise.resolve(mockUserModified));

const res = await login(mockReqModified, mockRes);
expect(findOneSpy).toHaveBeenCalledWith({ email: mockReqModified.body.email });
assertResMock(
403,
{
message:
'Sorry, this account is no longer active. If you feel this is in error, please contact your Manager and/or Administrator.',
},
res,
mockRes,
);
});

test('Ensure login returns error 403 if the password is not a match and if the user already exists', async () => {
const { login } = makeSut();
const mockReqModified = {
...mockReq,
...{
body: {
email: '[email protected]',
password: 'SuperSecretPassword@',
},
},
};

const findOneSpy = jest
.spyOn(userProfile, 'findOne')
.mockImplementation(() => Promise.resolve(mockUser));
jest.spyOn(bcrypt, 'compare').mockResolvedValue(false);

const res = await login(mockReqModified, mockRes);
expect(findOneSpy).toHaveBeenCalledWith({ email: mockReqModified.body.email });

assertResMock(
403,
{
message: 'Invalid password.',
},
res,
mockRes,
);
});

test('Ensure login returns the error if the try block fails', async () => {
const { login } = makeSut();
const error = new Error('Try block failed');
const mockReqModified = {
...mockReq,
...{
body: {
email: '[email protected]',
password: 'exampletest',
},
},
};

jest.spyOn(userProfile, 'findOne').mockImplementation(() => Promise.reject(error));

await login(mockReqModified, mockRes);
expect(mockRes.json).toHaveBeenCalledWith(error);
});

test('Ensure login returns 200, if the user is a new user and there is a password match', async () => {
const { login } = makeSut();
const mockReqModified = {
...mockReq,
...{
body: {
email: '[email protected]',
password: '123Welcome!',
},
},
};

const mockUserModified = {
_id: 'user123',
email: '[email protected]',
password: 'hashedPassword',
resetPwd: 'newUserPassword',
isActive: true,
};

jest
.spyOn(userProfile, 'findOne')
.mockImplementation(() => Promise.resolve(mockUserModified));

jest.spyOn(bcrypt, 'compare').mockResolvedValue(true);

const res = await login(mockReqModified, mockRes);
assertResMock(200, { new: true, userId: 'user123' }, res, mockRes);
});

test('Ensure login returns 200, if the user already exists and the password is a match', async () => {
const { login } = makeSut();
const mockReqModified = {
...mockReq,
body: {
email: '[email protected]',
password: 'existingUserPassword',
},
};
const mockUserModified = {
_id: 'user123',
email: '[email protected]',
password: 'hashedPassword',
resetPwd: 'newUserPassword',
isActive: true,
role: 'Volunteer',
permissions: ['read', 'write'],
};

const findOneSpy = jest
.spyOn(userProfile, 'findOne')
.mockImplementation(() => Promise.resolve(mockUserModified));

jest.spyOn(bcrypt, 'compare').mockResolvedValue(true);

const res = await login(mockReqModified, mockRes);
expect(findOneSpy).toHaveBeenCalledWith({ email: mockReqModified.body.email });

assertResMock(200, { token: expect.any(String) }, res, mockRes);
});
});

describe('getUser', () => {
it('Ensure getUser returns 200, with the requestor body', () => {
const { getUser } = makeSut();

const res = getUser(mockReq, mockRes);
assertResMock(200, mockReq.body.requestor, res, mockRes);
});
});
});
1 change: 1 addition & 0 deletions src/test/mock-response.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const mockRes = {
status: jest.fn().mockReturnThis(),
send: jest.fn(),
json: jest.fn(),
};

module.exports = mockRes;

0 comments on commit 9bd36d1

Please sign in to comment.