Skip to content

Commit 899c10c

Browse files
committed
resolve updateSetting tests with current logic
1 parent fd98175 commit 899c10c

File tree

1 file changed

+151
-27
lines changed

1 file changed

+151
-27
lines changed

server/controllers/user.controller/__tests__/authManagement/updateSettings.test.ts

Lines changed: 151 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ import { saveUser, generateToken, userResponse } from '../../helpers';
77
import { createMockUser } from '../../__testUtils__';
88

99
import { mailerService } from '../../../../utils/mail';
10-
import { UserDocument } from '../../../../types';
10+
import { UpdateSettingsRequestBody, UserDocument } from '../../../../types';
1111

1212
jest.mock('../../../../models/user');
1313
jest.mock('../../../../utils/mail');
1414
jest.mock('../../helpers', () => ({
15-
...jest.requireActual('../../helpers'),
15+
...jest.requireActual('../../helpers'), // use actual userResponse
1616
saveUser: jest.fn(),
1717
generateToken: jest.fn()
1818
}));
1919

20-
describe('user.controller > auth management', () => {
20+
describe('user.controller > auth management > updateSettings (email, username, password)', () => {
2121
let request: any;
22+
let requestBody: UpdateSettingsRequestBody;
2223
let response: any;
2324
let next: MockNext;
2425
const fixedTime = 100000000;
@@ -69,13 +70,31 @@ describe('user.controller > auth management', () => {
6970

7071
// the below tests match the current logic, but logic can be improved
7172
describe('if the user is found', () => {
73+
const OLD_USERNAME = 'oldusername';
74+
const NEW_USERNAME = 'newusername';
75+
76+
const OLD_EMAIL = '[email protected]';
77+
const NEW_EMAIL = '[email protected]';
78+
79+
const OLD_PASSWORD = 'oldpassword';
80+
const NEW_PASSWORD = 'newpassword';
81+
7282
const startingUser = createMockUser({
73-
username: 'oldusername',
74-
75-
id: 'valid-id',
83+
username: OLD_USERNAME,
84+
email: OLD_EMAIL,
85+
password: OLD_PASSWORD,
86+
id: '123459',
7687
comparePassword: jest.fn().mockResolvedValue(true)
7788
});
7889

90+
// minimum valid request body to manipulate per test
91+
// from manual testing on the account form:
92+
// both username and email are required & there is client-side validation for valid email & username-taken prior to submit
93+
const minimumValidRequest: UpdateSettingsRequestBody = {
94+
username: OLD_USERNAME,
95+
email: OLD_EMAIL
96+
};
97+
7998
beforeEach(() => {
8099
User.findById = jest.fn().mockResolvedValue(startingUser);
81100

@@ -85,40 +104,145 @@ describe('user.controller > auth management', () => {
85104
(generateToken as jest.Mock).mockResolvedValue('token12343');
86105
});
87106

88-
describe('and when there is a username in the request', () => {
89-
beforeEach(async () => {
90-
request.setBody({
91-
username: 'newusername'
92-
});
93-
await updateSettings(request, response, next);
107+
// Q: should we add check & logic that if no username or email are on the request,
108+
// we fallback to the username and/or email on the found user for safety?
109+
// not sure if anyone is hitting this api directly, so the client-side checks may not be enough
110+
111+
// duplicate username check happens client-side before this request is made
112+
it('saves the user with any username in the request', async () => {
113+
// saves with old username
114+
requestBody = { ...minimumValidRequest, username: OLD_USERNAME };
115+
request.setBody(requestBody);
116+
117+
await updateSettings(request, response, next);
118+
119+
expect(saveUser).toHaveBeenCalledWith(response, {
120+
...startingUser
94121
});
95-
it('calls saveUser', () => {
96-
expect(saveUser).toHaveBeenCalledWith(response, {
97-
...startingUser,
98-
username: 'newusername'
99-
});
122+
123+
// saves with new username
124+
requestBody = { ...minimumValidRequest, username: NEW_USERNAME };
125+
request.setBody(requestBody);
126+
127+
await updateSettings(request, response, next);
128+
129+
expect(saveUser).toHaveBeenCalledWith(response, {
130+
...startingUser,
131+
username: NEW_USERNAME
100132
});
101133
});
102134

103-
// currently frontend doesn't seem to call the below
104-
describe('and when there is a newPassword in the request', () => {
105-
beforeEach(async () => {});
135+
// currently frontend doesn't seem to call password-change related things the below
136+
// not sure if we should update the logic to be cleaner?
137+
describe('and when there is a new password in the request', () => {
138+
beforeEach(() => {
139+
requestBody = { ...minimumValidRequest, newPassword: NEW_PASSWORD };
140+
});
106141
describe('and the current password is not provided', () => {
107-
it('returns 401 with a "current password not provided" message', () => {});
108-
it('does not save the user with the new password', () => {});
142+
beforeEach(async () => {
143+
request.setBody(requestBody);
144+
await updateSettings(request, response, next);
145+
});
146+
it('returns 401 with a "current password not provided" message', () => {
147+
expect(response.status).toHaveBeenCalledWith(401);
148+
expect(response.json).toHaveBeenCalledWith({
149+
error: 'Current password is not provided.'
150+
});
151+
});
152+
it('does not save the user with the new password', () => {
153+
expect(saveUser).not.toHaveBeenCalled();
154+
});
109155
});
110156
});
157+
158+
// this should be nested in the previous block but currently here to match existing logic as-is
159+
// NOTE: will make a PR into this branch to propose the change
111160
describe('and when there is a currentPassword in the request', () => {
112161
describe('and the current password does not match', () => {
113-
beforeEach(async () => {});
114-
it('returns 401 with a "current password invalid" message', () => {});
115-
it('does not save the user with the new password', () => {});
162+
beforeEach(async () => {
163+
requestBody = {
164+
...minimumValidRequest,
165+
newPassword: NEW_PASSWORD,
166+
currentPassword: 'SOMETHING ELSE'
167+
};
168+
169+
// simulate check for password match failing
170+
startingUser.comparePassword = jest.fn().mockResolvedValue(false);
171+
172+
request.setBody(requestBody);
173+
await updateSettings(request, response, next);
174+
});
175+
176+
it('returns 401 with a "current password invalid" message', () => {
177+
expect(response.status).toHaveBeenCalledWith(401);
178+
expect(response.json).toHaveBeenCalledWith({
179+
error: 'Current password is invalid.'
180+
});
181+
});
182+
it('does not save the user with the new password', () => {
183+
expect(saveUser).not.toHaveBeenCalled();
184+
});
116185
});
117186
describe('and when the current password does match', () => {
118-
beforeEach(async () => {});
119-
it('calls saveUser with the new password', () => {});
187+
beforeEach(async () => {
188+
requestBody = {
189+
...minimumValidRequest,
190+
newPassword: NEW_PASSWORD,
191+
currentPassword: OLD_PASSWORD
192+
};
193+
194+
// simulate check for password match passing
195+
startingUser.comparePassword = jest.fn().mockResolvedValue(true);
196+
197+
request.setBody(requestBody);
198+
await updateSettings(request, response, next);
199+
});
200+
it('calls saveUser with the new password', () => {
201+
expect(saveUser).toHaveBeenCalledWith(response, {
202+
...startingUser,
203+
password: NEW_PASSWORD
204+
});
205+
});
206+
});
207+
208+
// NOTE: This should not pass, but it currently does!!
209+
describe('and when there is no new password on the request', () => {
210+
beforeEach(async () => {
211+
requestBody = {
212+
...minimumValidRequest,
213+
newPassword: undefined,
214+
currentPassword: OLD_PASSWORD
215+
};
216+
217+
// simulate check for password match passing
218+
startingUser.comparePassword = jest.fn().mockResolvedValue(true);
219+
220+
request.setBody(requestBody);
221+
await updateSettings(request, response, next);
222+
});
223+
it('calls saveUser with the new empty password', () => {
224+
expect(saveUser).toHaveBeenCalledWith(response, {
225+
...startingUser,
226+
password: undefined
227+
});
228+
});
120229
});
121230
});
231+
232+
describe('and when there is an email in the request', () => {
233+
describe('and the email is the same as the old email', () => {
234+
it('saves the user with the old email', () => {});
235+
it('does not send a verification email', () => {});
236+
});
237+
describe('and the email is not the same as the old email', () => {
238+
it('saves the user with the new email', () => {});
239+
it('sends a verification email', () => {});
240+
});
241+
});
242+
243+
describe('and when there is any other error', () => {
244+
it('returns a 500 error', () => {});
245+
});
122246
});
123247
});
124248
});

0 commit comments

Comments
 (0)