diff --git a/server/controllers/changeLocalName/details.test.ts b/server/controllers/changeLocalName/details.test.ts index 304ae525..14d71373 100644 --- a/server/controllers/changeLocalName/details.test.ts +++ b/server/controllers/changeLocalName/details.test.ts @@ -74,6 +74,7 @@ describe('Change Local Name', () => { authService.getSystemClientToken = jest.fn().mockResolvedValue('token') locationsService.getLocation = jest.fn().mockResolvedValue(true) locationsService.updateLocalName = jest.fn().mockResolvedValue(true) + locationsService.getLocationByLocalName = jest.fn() analyticsService.sendEvent = jest.fn() }) @@ -119,8 +120,21 @@ describe('Change Local Name', () => { }) }) + it('sets the correct backLink and cancelLink in locals', () => { + const result = controller.locals(req, res) + expect(result.backLink).toBe('/view-and-update-locations/TST/e07effb3-905a-4f6b-acdc-fafbb43a1ee2') + expect(result.cancelLink).toBe('/view-and-update-locations/TST/e07effb3-905a-4f6b-acdc-fafbb43a1ee2') + }) + + it('sets the localName value from res if not in req', () => { + delete req.form.values.localName + res.locals.location.localName = 'Local Name from response' + const result = controller.locals(req, res) + expect(result.fields.localName.value).toBe('Local Name from response') + }) + describe('validateFields', () => { - it('if local name already exists, callback with error', async () => { + it('calls back with error if local name already exists', async () => { req.form.values.localName = 'existing local name' locationsService.getLocationByLocalName = jest.fn().mockResolvedValue(true) @@ -133,12 +147,74 @@ describe('Change Local Name', () => { expect(callback).toHaveBeenCalledWith(expect.objectContaining({ localName: expectedError })) }) + + it('calls back with validation error if localName is null, ', async () => { + req.form.values.localName = '' + locationsService.getLocationByLocalName = jest.fn().mockResolvedValue(false) + + const expectedError = controller.formError('localName', 'required') + + const callback = jest.fn() + await controller.validateFields(req, res, callback) + + await controller.saveValues(req, res, next) + + expect(callback).toHaveBeenCalledWith(expect.objectContaining({ localName: expectedError })) + }) + }) + + describe('errorCases', () => { + it('if errorCode is 101, callback', async () => { + req.form.values.localName = 'Local Name' + const errorsWith101 = new Error('Location not found') + locationsService.getLocationByLocalName = jest.fn().mockRejectedValue(errorsWith101) + const callback = jest.fn() + + await controller.validateFields(req, res, callback) + expect(locationsService.getLocationByLocalName).toHaveBeenCalled() + }) + + it('if errorCode is not 101, callback', async () => { + req.form.values.localName = 'Local Name' + const genericError = new Error('Some other error') + locationsService.getLocationByLocalName = jest.fn().mockRejectedValue(genericError) + const callback = jest.fn() + await controller.validateFields(req, res, callback) + expect(locationsService.getLocationByLocalName).toHaveBeenCalled() + }) }) describe('saveValues', () => { - it('changes a local name via the locations API', async () => { + it('does not call locations API if localName is null ', async () => { + req.form.values.localName = '' + res.locals.location.localName = 'Wing A' + const callback = jest.fn() + await controller.validateFields(req, res, callback) + expect(locationsService.getLocationByLocalName).not.toHaveBeenCalled() + expect(locationsService.updateLocalName).not.toHaveBeenCalled() + }) + + it('does not call locations API if localName has not changed', async () => { + req.form.values.localName = 'Wing A' + res.locals.location.localName = 'Wing A' + const callback = jest.fn() + await controller.validateFields(req, res, callback) + expect(locationsService.getLocationByLocalName).not.toHaveBeenCalled() + expect(locationsService.updateLocalName).not.toHaveBeenCalled() + }) + + it('calls locations API if localName has been changed', async () => { + res.locals.location.localName = 'old Local Name' req.form.values.localName = 'changed local name' + const callback = jest.fn() + await controller.validateFields(req, res, callback) await controller.saveValues(req, res, next) + expect(locationsService.getLocationByLocalName).toHaveBeenCalledWith( + 'token', + 'TST', + 'changed local name', + '57718979-573c-433a-9e51-2d83f887c11c', + ) expect(locationsService.updateLocalName).toHaveBeenCalledWith( 'token', 'e07effb3-905a-4f6b-acdc-fafbb43a1ee2', @@ -147,6 +223,27 @@ describe('Change Local Name', () => { ) }) + it('sanitizes localName before calling locations API', async () => { + req.form.values.localName = '
Sanitized Wing Name
' + const callback = jest.fn() + await controller.validateFields(req, res, callback) + await controller.saveValues(req, res, next) + expect(locationsService.getLocationByLocalName).toHaveBeenCalledWith( + 'token', + 'TST', + 'Sanitized Wing Name', + '57718979-573c-433a-9e51-2d83f887c11c', + ) + expect(locationsService.updateLocalName).toHaveBeenCalledWith( + 'token', + res.locals.location.id, + 'Sanitized Wing Name', + res.locals.user.username, + ) + + expect(next).toHaveBeenCalled() + }) + it('sends an analytics event', async () => { await controller.saveValues(req, res, next) diff --git a/server/controllers/changeLocalName/details.ts b/server/controllers/changeLocalName/details.ts index b6086db0..1febf00e 100644 --- a/server/controllers/changeLocalName/details.ts +++ b/server/controllers/changeLocalName/details.ts @@ -40,6 +40,9 @@ export default class Details extends FormInitialStep { const validationErrors: any = {} + if (!sanitizedLocalName) { + return callback({ ...errors, ...validationErrors }) + } if (sanitizeString(String(values.localName)) === sanitizeString(res.locals.location.localName)) { return res.redirect(`/view-and-update-locations/${prisonId}/${locationId}`) }