From bb02fa20a23eab285c88cfe6ef16d28783d24ec6 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 3 May 2020 18:42:22 +0100 Subject: [PATCH] feat(patient): add input validation (#2032) --- src/__tests__/patients/patient-slice.test.ts | 39 +++++++++++++++++++ .../enUs/translations/patient/index.ts | 4 ++ src/patients/GeneralInformation.tsx | 8 ++++ src/patients/patient-slice.ts | 30 ++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/src/__tests__/patients/patient-slice.test.ts b/src/__tests__/patients/patient-slice.test.ts index 28ed65761c..dba7899dcd 100644 --- a/src/__tests__/patients/patient-slice.test.ts +++ b/src/__tests__/patients/patient-slice.test.ts @@ -295,6 +295,37 @@ describe('patients slice', () => { }), ) }) + + it('should validate fields that should only contian alpha characters', async () => { + const store = mockStore() + const expectedPatientId = 'sliceId10' + const expectedPatient = { + id: expectedPatientId, + givenName: 'some given name', + suffix: 'A123', + familyName: 'B456', + prefix: 'C987', + preferredLanguage: 'D321', + } as Patient + const saveOrUpdateSpy = jest + .spyOn(PatientRepository, 'saveOrUpdate') + .mockResolvedValue(expectedPatient) + const onSuccessSpy = jest.fn() + + await store.dispatch(createPatient(expectedPatient, onSuccessSpy)) + + expect(onSuccessSpy).not.toHaveBeenCalled() + expect(saveOrUpdateSpy).not.toHaveBeenCalled() + expect(store.getActions()[1]).toEqual( + createPatientError({ + message: 'patient.errors.createPatientError', + suffix: 'patient.errors.patientNumInSuffixFeedback', + familyName: 'patient.errors.patientNumInFamilyNameFeedback', + prefix: 'patient.errors.patientNumInPrefixFeedback', + preferredLanguage: 'patient.errors.patientNumInPreferredLanguageFeedback', + }), + ) + }) }) describe('fetch patient', () => { @@ -386,6 +417,10 @@ describe('patients slice', () => { id: expectedPatientId, givenName: undefined, dateOfBirth: addDays(new Date(), 4).toISOString(), + suffix: '061002', + prefix: '061002', + familyName: '061002', + preferredLanguage: '061002', } as Patient const saveOrUpdateSpy = jest .spyOn(PatientRepository, 'saveOrUpdate') @@ -401,6 +436,10 @@ describe('patients slice', () => { message: 'patient.errors.updatePatientError', givenName: 'patient.errors.patientGivenNameFeedback', dateOfBirth: 'patient.errors.patientDateOfBirthFeedback', + suffix: 'patient.errors.patientNumInSuffixFeedback', + familyName: 'patient.errors.patientNumInFamilyNameFeedback', + prefix: 'patient.errors.patientNumInPrefixFeedback', + preferredLanguage: 'patient.errors.patientNumInPreferredLanguageFeedback', }), ) }) diff --git a/src/locales/enUs/translations/patient/index.ts b/src/locales/enUs/translations/patient/index.ts index 32b6b4b331..c404f9e229 100644 --- a/src/locales/enUs/translations/patient/index.ts +++ b/src/locales/enUs/translations/patient/index.ts @@ -94,6 +94,10 @@ export default { updatePatientError: 'Could not update patient.', patientGivenNameFeedback: 'Given Name is required.', patientDateOfBirthFeedback: 'Date of Birth can not be greater than today', + patientNumInSuffixFeedback: 'Cannot contain numbers.', + patientNumInPrefixFeedback: 'Cannot contain numbers.', + patientNumInFamilyNameFeedback: 'Cannot contain numbers.', + patientNumInPreferredLanguageFeedback: 'Cannot contain numbers.', invalidEmail: 'Must be a valid email.', invalidPhoneNumber: 'Must be a valid phone number.', }, diff --git a/src/patients/GeneralInformation.tsx b/src/patients/GeneralInformation.tsx index 6f926a6d2d..ca9a7f1f2c 100644 --- a/src/patients/GeneralInformation.tsx +++ b/src/patients/GeneralInformation.tsx @@ -60,6 +60,8 @@ const GeneralInformation = (props: Props) => { onChange={(event: React.ChangeEvent) => { onInputElementChange(event, 'prefix') }} + isInvalid={error?.prefix} + feedback={t(error?.prefix)} />
@@ -85,6 +87,8 @@ const GeneralInformation = (props: Props) => { onChange={(event: React.ChangeEvent) => { onInputElementChange(event, 'familyName') }} + isInvalid={error?.familyName} + feedback={t(error?.familyName)} />
@@ -96,6 +100,8 @@ const GeneralInformation = (props: Props) => { onChange={(event: React.ChangeEvent) => { onInputElementChange(event, 'suffix') }} + isInvalid={error?.suffix} + feedback={t(error?.suffix)} />
@@ -195,6 +201,8 @@ const GeneralInformation = (props: Props) => { onChange={(event: React.ChangeEvent) => { onInputElementChange(event, 'preferredLanguage') }} + isInvalid={error?.preferredLanguage} + feedback={t(error?.preferredLanguage)} /> diff --git a/src/patients/patient-slice.ts b/src/patients/patient-slice.ts index 4488ef5eef..ba79c89dc9 100644 --- a/src/patients/patient-slice.ts +++ b/src/patients/patient-slice.ts @@ -28,6 +28,10 @@ interface Error { message?: string givenName?: string dateOfBirth?: string + suffix?: string + prefix?: string + familyName?: string + preferredLanguage?: string email?: string phoneNumber?: string } @@ -141,6 +145,8 @@ export const fetchPatient = (id: string): AppThunk => async (dispatch) => { function validatePatient(patient: Patient) { const error: Error = {} + const regexContainsNumber = /\d/ + if (!patient.givenName) { error.givenName = 'patient.errors.patientGivenNameFeedback' } @@ -153,6 +159,30 @@ function validatePatient(patient: Patient) { } } + if (patient.suffix) { + if (regexContainsNumber.test(patient.suffix)) { + error.suffix = 'patient.errors.patientNumInSuffixFeedback' + } + } + + if (patient.prefix) { + if (regexContainsNumber.test(patient.prefix)) { + error.prefix = 'patient.errors.patientNumInPrefixFeedback' + } + } + + if (patient.familyName) { + if (regexContainsNumber.test(patient.familyName)) { + error.familyName = 'patient.errors.patientNumInFamilyNameFeedback' + } + } + + if (patient.preferredLanguage) { + if (regexContainsNumber.test(patient.preferredLanguage)) { + error.preferredLanguage = 'patient.errors.patientNumInPreferredLanguageFeedback' + } + } + if (patient.email) { if (!validator.isEmail(patient.email)) { error.email = 'patient.errors.invalidEmail'