Skip to content

Commit 1aeca52

Browse files
committed
add login integration test
1 parent 826035e commit 1aeca52

File tree

3 files changed

+185
-2
lines changed

3 files changed

+185
-2
lines changed

tests/.env.test.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ DB_PORT=27017
2121
DB_USER=afteracademy-blog-test-db-user
2222

2323
#YOUR_TEST_MONGO_DB_USER_PWD
24-
DB_PWD=changeit
24+
DB_USER_PWD=changeit
2525

2626
#Log
2727
#Example '/Users/janisharali/logs'
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
jest.resetAllMocks(); // make sure we do not have any mocks set from unit tests
2+
3+
import supertest from 'supertest';
4+
import app from '../../../../src/app';
5+
import UserRepo from '../../../../src/database/repository/UserRepo';
6+
import KeystoreRepo from '../../../../src/database/repository/KeystoreRepo';
7+
import User, { IUser } from '../../../../src/database/model/User';
8+
import bcrypt from 'bcrypt';
9+
import * as authUtils from '../../../../src/auth/authUtils';
10+
import { IRole, RoleCode } from '../../../../src/database/model/Role';
11+
import { Types } from 'mongoose';
12+
import ApiKey, { IApiKey } from '../../../../src/database/model/ApiKey';
13+
14+
export const createTokensSpy = jest.spyOn(authUtils, 'createTokens');
15+
export const bcryptCompareSpy = jest.spyOn(bcrypt, 'compare');
16+
export const userFindByEmailSpy = jest.spyOn(UserRepo, 'findByEmail');
17+
export const keystoreCreateSpy = jest.spyOn(KeystoreRepo, 'create');
18+
19+
describe('Integration Test: Login basic route', () => {
20+
21+
const endpoint = '/v1/login/basic';
22+
const request = supertest(app);
23+
const password = '123456';
24+
25+
let user: IUser;
26+
let apikey: IApiKey;
27+
28+
beforeAll(async () => {
29+
await User.remove({}); // delete all data from user table
30+
user = await User.create(<IUser>{
31+
name: 'abc',
32+
33+
password: bcrypt.hashSync(password, 10),
34+
status: true,
35+
updatedAt: new Date(),
36+
createdAt: new Date(),
37+
profilePicUrl: 'https:/abc.com/xyz',
38+
roles: [<IRole>{ _id: new Types.ObjectId(), code: RoleCode.LEARNER }]
39+
});
40+
apikey = await ApiKey.findOne({ status: true });
41+
});
42+
43+
afterAll(async () => {
44+
await User.remove({}); // delete all data from user table
45+
});
46+
47+
beforeEach(() => {
48+
userFindByEmailSpy.mockClear();
49+
keystoreCreateSpy.mockClear();
50+
bcryptCompareSpy.mockClear();
51+
createTokensSpy.mockClear();
52+
});
53+
54+
it('Should send error when empty body is sent', async () => {
55+
const response = await addHeaders(request.post(endpoint), apikey);
56+
expect(response.status).toBe(400);
57+
expect(userFindByEmailSpy).not.toBeCalled();
58+
expect(bcryptCompareSpy).not.toBeCalled();
59+
expect(keystoreCreateSpy).not.toBeCalled();
60+
expect(createTokensSpy).not.toBeCalled();
61+
});
62+
63+
it('Should send error when email is only sent', async () => {
64+
const response = await addHeaders(request.post(endpoint)
65+
.send({ email: user.email }),
66+
apikey
67+
);
68+
expect(response.status).toBe(400);
69+
expect(response.body.message).toMatch(/password/);
70+
expect(userFindByEmailSpy).not.toBeCalled();
71+
expect(bcryptCompareSpy).not.toBeCalled();
72+
expect(keystoreCreateSpy).not.toBeCalled();
73+
expect(createTokensSpy).not.toBeCalled();
74+
});
75+
76+
it('Should send error when password is only sent', async () => {
77+
const response = await addHeaders(request.post(endpoint)
78+
.send({ password: password }),
79+
apikey
80+
);
81+
expect(response.status).toBe(400);
82+
expect(response.body.message).toMatch(/email/);
83+
expect(userFindByEmailSpy).not.toBeCalled();
84+
expect(bcryptCompareSpy).not.toBeCalled();
85+
expect(keystoreCreateSpy).not.toBeCalled();
86+
expect(createTokensSpy).not.toBeCalled();
87+
});
88+
89+
it('Should send error when email is not valid format', async () => {
90+
const response = await addHeaders(request.post(endpoint)
91+
.send({ email: '123' }),
92+
apikey
93+
);
94+
expect(response.status).toBe(400);
95+
expect(response.body.message).toMatch(/valid email/);
96+
expect(userFindByEmailSpy).not.toBeCalled();
97+
expect(bcryptCompareSpy).not.toBeCalled();
98+
expect(keystoreCreateSpy).not.toBeCalled();
99+
expect(createTokensSpy).not.toBeCalled();
100+
});
101+
102+
it('Should send error when password is not valid format', async () => {
103+
const response = await addHeaders(request.post(endpoint)
104+
.send({
105+
email: user.email,
106+
password: '123'
107+
}),
108+
apikey
109+
);
110+
expect(response.status).toBe(400);
111+
expect(response.body.message).toMatch(/password length/);
112+
expect(response.body.message).toMatch(/6 char/);
113+
expect(userFindByEmailSpy).not.toBeCalled();
114+
expect(bcryptCompareSpy).not.toBeCalled();
115+
expect(keystoreCreateSpy).not.toBeCalled();
116+
expect(createTokensSpy).not.toBeCalled();
117+
});
118+
119+
it('Should send error when user not registered for email', async () => {
120+
const response = await addHeaders(request.post(endpoint)
121+
.send({
122+
123+
password: password,
124+
}),
125+
apikey
126+
);
127+
expect(response.status).toBe(400);
128+
expect(response.body.message).toMatch(/not registered/);
129+
expect(userFindByEmailSpy).toBeCalledTimes(1);
130+
expect(bcryptCompareSpy).not.toBeCalled();
131+
expect(keystoreCreateSpy).not.toBeCalled();
132+
expect(createTokensSpy).not.toBeCalled();
133+
});
134+
135+
it('Should send error for wrong password', async () => {
136+
const response = await addHeaders(request.post(endpoint)
137+
.send({
138+
email: user.email,
139+
password: 'abc123',
140+
}),
141+
apikey
142+
);
143+
expect(response.status).toBe(401);
144+
expect(response.body.message).toMatch(/authentication failure/i);
145+
expect(userFindByEmailSpy).toBeCalledTimes(1);
146+
expect(bcryptCompareSpy).toBeCalledTimes(1);
147+
expect(keystoreCreateSpy).not.toBeCalled();
148+
expect(createTokensSpy).not.toBeCalled();
149+
});
150+
151+
it('Should send success response for correct credentials', async () => {
152+
const response = await addHeaders(request.post(endpoint)
153+
.send({
154+
email: user.email,
155+
password: password,
156+
}),
157+
apikey
158+
);
159+
expect(response.status).toBe(200);
160+
expect(response.body.message).toMatch(/Success/i);
161+
expect(response.body.data).toBeDefined();
162+
163+
expect(response.body.data.user).toHaveProperty('_id');
164+
expect(response.body.data.user).toHaveProperty('name');
165+
expect(response.body.data.user).toHaveProperty('roles');
166+
expect(response.body.data.user).toHaveProperty('profilePicUrl');
167+
168+
expect(response.body.data.tokens).toBeDefined();
169+
expect(response.body.data.tokens).toHaveProperty('accessToken');
170+
expect(response.body.data.tokens).toHaveProperty('refreshToken');
171+
172+
expect(userFindByEmailSpy).toBeCalledTimes(1);
173+
expect(keystoreCreateSpy).toBeCalledTimes(1);
174+
expect(bcryptCompareSpy).toBeCalledTimes(1);
175+
expect(createTokensSpy).toBeCalledTimes(1);
176+
177+
expect(bcryptCompareSpy).toBeCalledWith(password, user.password);
178+
});
179+
});
180+
181+
export const addHeaders = (request: any, apikey: IApiKey) => request
182+
.set('Content-Type', 'application/json')
183+
.set('x-api-key', apikey.key);

tests/routes/v1/login/index.test.ts renamed to tests/routes/v1/login/unit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import supertest from 'supertest';
1010
import app from '../../../../src/app';
1111

12-
describe('Login basic route', () => {
12+
describe('Unit Test: Login basic route', () => {
1313

1414
const endpoint = '/v1/login/basic';
1515
const request = supertest(app);

0 commit comments

Comments
 (0)