Skip to content

Commit f83d2ae

Browse files
committed
add signup route tests
1 parent 87d1af4 commit f83d2ae

File tree

4 files changed

+216
-3
lines changed

4 files changed

+216
-3
lines changed

tests/routes/v1/login/index.test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,29 @@ import { addHeaders } from '../../../auth/authentication/mock';
33
// the mock for this class should be below all other mock imports
44
import {
55
mockKeystoreCreate, mockUserFindByEmail, createTokensSpy,
6-
USER_EMAIL, USER_PASSWORD
6+
bcryptCompareSpy, USER_EMAIL, USER_PASSWORD, USER_PASSWORD_HASH
77
} from './mock';
88

99
import supertest from 'supertest';
1010
import app from '../../../../src/app';
1111

12-
describe('Login Route', () => {
12+
describe('Login basic route', () => {
1313

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

1717
beforeEach(() => {
1818
mockKeystoreCreate.mockClear();
1919
mockUserFindByEmail.mockClear();
20+
bcryptCompareSpy.mockClear();
2021
createTokensSpy.mockClear();
2122
});
2223

2324
it('Should throw error when empty body is sent', async () => {
2425
const response = await addHeaders(request.post(endpoint));
2526
expect(response.status).toBe(400);
2627
expect(mockUserFindByEmail).not.toBeCalled();
28+
expect(bcryptCompareSpy).not.toBeCalled();
2729
expect(mockKeystoreCreate).not.toBeCalled();
2830
expect(createTokensSpy).not.toBeCalled();
2931
});
@@ -35,6 +37,7 @@ describe('Login Route', () => {
3537
expect(response.status).toBe(400);
3638
expect(response.body.message).toMatch(/password/);
3739
expect(mockUserFindByEmail).not.toBeCalled();
40+
expect(bcryptCompareSpy).not.toBeCalled();
3841
expect(mockKeystoreCreate).not.toBeCalled();
3942
expect(createTokensSpy).not.toBeCalled();
4043
});
@@ -46,6 +49,7 @@ describe('Login Route', () => {
4649
expect(response.status).toBe(400);
4750
expect(response.body.message).toMatch(/email/);
4851
expect(mockUserFindByEmail).not.toBeCalled();
52+
expect(bcryptCompareSpy).not.toBeCalled();
4953
expect(mockKeystoreCreate).not.toBeCalled();
5054
expect(createTokensSpy).not.toBeCalled();
5155
});
@@ -57,6 +61,7 @@ describe('Login Route', () => {
5761
expect(response.status).toBe(400);
5862
expect(response.body.message).toMatch(/valid email/);
5963
expect(mockUserFindByEmail).not.toBeCalled();
64+
expect(bcryptCompareSpy).not.toBeCalled();
6065
expect(mockKeystoreCreate).not.toBeCalled();
6166
expect(createTokensSpy).not.toBeCalled();
6267
});
@@ -71,6 +76,7 @@ describe('Login Route', () => {
7176
expect(response.body.message).toMatch(/password length/);
7277
expect(response.body.message).toMatch(/6 char/);
7378
expect(mockUserFindByEmail).not.toBeCalled();
79+
expect(bcryptCompareSpy).not.toBeCalled();
7480
expect(mockKeystoreCreate).not.toBeCalled();
7581
expect(createTokensSpy).not.toBeCalled();
7682
});
@@ -84,6 +90,7 @@ describe('Login Route', () => {
8490
expect(response.status).toBe(400);
8591
expect(response.body.message).toMatch(/not registered/);
8692
expect(mockUserFindByEmail).toBeCalledTimes(1);
93+
expect(bcryptCompareSpy).not.toBeCalled();
8794
expect(mockKeystoreCreate).not.toBeCalled();
8895
expect(createTokensSpy).not.toBeCalled();
8996
});
@@ -97,6 +104,7 @@ describe('Login Route', () => {
97104
expect(response.status).toBe(401);
98105
expect(response.body.message).toMatch(/authentication failure/i);
99106
expect(mockUserFindByEmail).toBeCalledTimes(1);
107+
expect(bcryptCompareSpy).toBeCalledTimes(1);
100108
expect(mockKeystoreCreate).not.toBeCalled();
101109
expect(createTokensSpy).not.toBeCalled();
102110
});
@@ -122,6 +130,9 @@ describe('Login Route', () => {
122130

123131
expect(mockUserFindByEmail).toBeCalledTimes(1);
124132
expect(mockKeystoreCreate).toBeCalledTimes(1);
133+
expect(bcryptCompareSpy).toBeCalledTimes(1);
125134
expect(createTokensSpy).toBeCalledTimes(1);
135+
136+
expect(bcryptCompareSpy).toBeCalledWith(USER_PASSWORD, USER_PASSWORD_HASH);
126137
});
127138
});

tests/routes/v1/login/mock.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export const USER_PASSWORD_HASH = bcrypt.hashSync(USER_PASSWORD, 10);
1111

1212
export const createTokensSpy = jest.spyOn(authUtils, 'createTokens');
1313

14+
export const bcryptCompareSpy = jest.spyOn(bcrypt, 'compare');
15+
1416
export const mockKeystoreCreate =
1517
jest.fn(
1618
async (client: IUser, primaryKey: string, secondaryKey: string): Promise<IKeystore> => {
@@ -44,4 +46,4 @@ jest.mock('../../../../src/database/repository/UserRepo', () => ({
4446
get findByEmail() { return mockUserFindByEmail; }
4547
}));
4648

47-
jest.unmock('../../../../src/auth/authUtils');
49+
jest.unmock('../../../../src/auth/authUtils'); // remove any override made anywhere

tests/routes/v1/signup/index.test.ts

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// importing any mock file let the jest load all the mocks defined in that file
2+
import { addHeaders } from '../../../auth/authentication/mock';
3+
import {
4+
mockUserFindByEmail, createTokensSpy, USER_EMAIL, USER_PASSWORD
5+
} from '../login/mock';
6+
7+
// import the mock for this file below all mock imports
8+
import { mockUserCreate, bcryptHashSpy, USER_NAME, USER_PROFILE_PIC } from './mock';
9+
10+
import supertest from 'supertest';
11+
import app from '../../../../src/app';
12+
13+
describe('Signup basic route', () => {
14+
15+
const endpoint = '/v1/signup/basic';
16+
const request = supertest(app);
17+
18+
const email = '[email protected]';
19+
20+
beforeEach(() => {
21+
mockUserFindByEmail.mockClear();
22+
mockUserCreate.mockClear();
23+
bcryptHashSpy.mockClear();
24+
createTokensSpy.mockClear();
25+
});
26+
27+
it('Should throw error when empty body is sent', async () => {
28+
const response = await addHeaders(request.post(endpoint));
29+
expect(response.status).toBe(400);
30+
expect(mockUserFindByEmail).not.toBeCalled();
31+
expect(bcryptHashSpy).not.toBeCalled();
32+
expect(mockUserCreate).not.toBeCalled();
33+
expect(createTokensSpy).not.toBeCalled();
34+
});
35+
36+
it('Should throw error when email is not sent', async () => {
37+
const response = await addHeaders(request.post(endpoint)
38+
.send({
39+
name: USER_NAME,
40+
password: USER_PASSWORD,
41+
profilePicUrl: USER_PROFILE_PIC
42+
})
43+
);
44+
expect(response.status).toBe(400);
45+
expect(response.body.message).toMatch(/email/);
46+
expect(response.body.message).toMatch(/required/);
47+
expect(mockUserFindByEmail).not.toBeCalled();
48+
expect(bcryptHashSpy).not.toBeCalled();
49+
expect(mockUserCreate).not.toBeCalled();
50+
expect(createTokensSpy).not.toBeCalled();
51+
});
52+
53+
it('Should throw error when password is not sent', async () => {
54+
const response = await addHeaders(request.post(endpoint)
55+
.send({
56+
email: email,
57+
name: USER_NAME,
58+
profilePicUrl: USER_PROFILE_PIC
59+
})
60+
);
61+
expect(response.status).toBe(400);
62+
expect(response.body.message).toMatch(/password/);
63+
expect(response.body.message).toMatch(/required/);
64+
expect(mockUserFindByEmail).not.toBeCalled();
65+
expect(bcryptHashSpy).not.toBeCalled();
66+
expect(mockUserCreate).not.toBeCalled();
67+
expect(createTokensSpy).not.toBeCalled();
68+
});
69+
70+
it('Should throw error when name is not sent', async () => {
71+
const response = await addHeaders(request.post(endpoint)
72+
.send({
73+
email: email,
74+
password: USER_PASSWORD,
75+
profilePicUrl: USER_PROFILE_PIC
76+
})
77+
);
78+
expect(response.status).toBe(400);
79+
expect(response.body.message).toMatch(/name/);
80+
expect(response.body.message).toMatch(/required/);
81+
expect(mockUserFindByEmail).not.toBeCalled();
82+
expect(bcryptHashSpy).not.toBeCalled();
83+
expect(mockUserCreate).not.toBeCalled();
84+
expect(createTokensSpy).not.toBeCalled();
85+
});
86+
87+
it('Should throw error when email is not valid format', async () => {
88+
const response = await addHeaders(request.post(endpoint)
89+
.send({
90+
email: 'abc',
91+
name: USER_NAME,
92+
password: USER_PASSWORD,
93+
profilePicUrl: USER_PROFILE_PIC
94+
})
95+
);
96+
expect(response.status).toBe(400);
97+
expect(response.body.message).toMatch(/valid email/);
98+
expect(mockUserFindByEmail).not.toBeCalled();
99+
expect(bcryptHashSpy).not.toBeCalled();
100+
expect(mockUserCreate).not.toBeCalled();
101+
expect(createTokensSpy).not.toBeCalled();
102+
});
103+
104+
it('Should throw error when password is not valid format', async () => {
105+
const response = await addHeaders(request.post(endpoint)
106+
.send({
107+
email: email,
108+
name: USER_NAME,
109+
password: '123',
110+
profilePicUrl: USER_PROFILE_PIC
111+
})
112+
);
113+
expect(response.status).toBe(400);
114+
expect(response.body.message).toMatch(/password length/);
115+
expect(response.body.message).toMatch(/6 char/);
116+
expect(mockUserFindByEmail).not.toBeCalled();
117+
expect(bcryptHashSpy).not.toBeCalled();
118+
expect(mockUserCreate).not.toBeCalled();
119+
expect(createTokensSpy).not.toBeCalled();
120+
});
121+
122+
it('Should throw error when user is registered for email', async () => {
123+
const response = await addHeaders(request.post(endpoint)
124+
.send({
125+
email: USER_EMAIL,
126+
name: USER_NAME,
127+
password: USER_PASSWORD,
128+
profilePicUrl: USER_PROFILE_PIC
129+
})
130+
);
131+
132+
expect(response.status).toBe(400);
133+
expect(response.body.message).toMatch(/already registered/);
134+
expect(mockUserFindByEmail).toBeCalledTimes(1);
135+
expect(bcryptHashSpy).not.toBeCalled();
136+
expect(mockUserCreate).not.toBeCalled();
137+
expect(createTokensSpy).not.toBeCalled();
138+
});
139+
140+
it('Should send success response for correct data', async () => {
141+
const response = await addHeaders(request.post(endpoint)
142+
.send({
143+
email: email,
144+
name: USER_NAME,
145+
password: USER_PASSWORD,
146+
profilePicUrl: USER_PROFILE_PIC
147+
})
148+
);
149+
expect(response.status).toBe(200);
150+
expect(response.body.message).toMatch(/Success/i);
151+
expect(response.body.data).toBeDefined();
152+
153+
expect(response.body.data.user).toHaveProperty('_id');
154+
expect(response.body.data.user).toHaveProperty('name');
155+
expect(response.body.data.user).toHaveProperty('roles');
156+
expect(response.body.data.user).toHaveProperty('profilePicUrl');
157+
158+
expect(response.body.data.tokens).toBeDefined();
159+
expect(response.body.data.tokens).toHaveProperty('accessToken');
160+
expect(response.body.data.tokens).toHaveProperty('refreshToken');
161+
162+
expect(mockUserFindByEmail).toBeCalledTimes(1);
163+
expect(bcryptHashSpy).toBeCalledTimes(1);
164+
expect(mockUserCreate).toBeCalledTimes(1);
165+
expect(createTokensSpy).toBeCalledTimes(1);
166+
167+
expect(bcryptHashSpy).toBeCalledWith(USER_PASSWORD, 10);
168+
});
169+
});

tests/routes/v1/signup/mock.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { mockUserFindByEmail } from '../login/mock';
2+
import { IUser } from '../../../../src/database/model/User';
3+
import { IKeystore } from '../../../../src/database/model/Keystore';
4+
import { Types } from 'mongoose';
5+
import bcrypt from 'bcrypt';
6+
7+
export const USER_NAME = 'abc';
8+
export const USER_PROFILE_PIC = 'https://abc.com/xyz';
9+
10+
export const bcryptHashSpy = jest.spyOn(bcrypt, 'hash');
11+
12+
13+
export const mockUserCreate = jest.fn(async (user: IUser, accessTokenKey: string, refreshTokenKey: string, roleCode: string)
14+
: Promise<{ user: IUser, keystore: IKeystore }> => {
15+
user._id = new Types.ObjectId();
16+
user.roles = [];
17+
return {
18+
user: user,
19+
keystore: <IKeystore>{
20+
_id: new Types.ObjectId(),
21+
client: user,
22+
primaryKey: 'abc',
23+
secondaryKey: 'xyz'
24+
}
25+
};
26+
});
27+
28+
jest.mock('../../../../src/database/repository/UserRepo', () => ({
29+
get findByEmail() { return mockUserFindByEmail; }, // utilising already defined mock
30+
get create() { return mockUserCreate; }
31+
}));

0 commit comments

Comments
 (0)