@kenyaemr/esm-patient-registration-app 5.2.2 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/271.js +1 -0
- package/dist/319.js +1 -1
- package/dist/330.js +1 -1
- package/dist/460.js +1 -1
- package/dist/537.js +1 -1
- package/dist/574.js +1 -1
- package/dist/59.js +1 -1
- package/dist/59.js.map +1 -1
- package/dist/619.js +1 -0
- package/dist/619.js.map +1 -0
- package/dist/644.js +1 -0
- package/dist/735.js +1 -1
- package/dist/757.js +1 -1
- package/dist/784.js +1 -1
- package/dist/788.js +1 -1
- package/dist/807.js +1 -1
- package/dist/833.js +1 -1
- package/dist/895.js +2 -0
- package/dist/{388.js.LICENSE.txt → 895.js.LICENSE.txt} +4 -2
- package/dist/895.js.map +1 -0
- package/dist/{openmrs-esm-patient-registration-app.js → kenyaemr-esm-patient-registration-app.js} +1 -1
- package/dist/{openmrs-esm-patient-registration-app.js.buildmanifest.json → kenyaemr-esm-patient-registration-app.js.buildmanifest.json} +117 -73
- package/dist/kenyaemr-esm-patient-registration-app.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +4 -2
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +6 -5
- package/src/add-patient-link.test.tsx +9 -7
- package/src/config-schema.ts +31 -38
- package/src/constants.ts +1 -1
- package/src/offline.resources.ts +13 -18
- package/src/offline.ts +8 -6
- package/src/patient-registration/before-save-prompt.tsx +2 -1
- package/src/patient-registration/field/__mocks__/field.resource.ts +1 -1
- package/src/patient-registration/field/address/address-field.component.tsx +5 -4
- package/src/patient-registration/field/address/address-hierarchy.resource.tsx +2 -2
- package/src/patient-registration/field/address/address-search.component.tsx +1 -14
- package/src/patient-registration/field/address/custom-address-field.component.tsx +1 -1
- package/src/patient-registration/field/address/tests/address-hierarchy.test.tsx +3 -3
- package/src/patient-registration/field/address/tests/address-search-component.test.tsx +14 -7
- package/src/patient-registration/field/custom-field.component.tsx +1 -1
- package/src/patient-registration/field/dob/dob.component.tsx +2 -2
- package/src/patient-registration/field/dob/dob.test.tsx +0 -3
- package/src/patient-registration/field/field.component.tsx +4 -1
- package/src/patient-registration/field/field.resource.ts +4 -4
- package/src/patient-registration/field/field.test.tsx +98 -95
- package/src/patient-registration/field/gender/gender-field.component.tsx +4 -4
- package/src/patient-registration/field/gender/gender-field.test.tsx +7 -14
- package/src/patient-registration/field/id/id-field.component.tsx +6 -6
- package/src/patient-registration/field/id/id-field.test.tsx +9 -7
- package/src/patient-registration/field/id/identifier-selection-overlay.component.tsx +1 -1
- package/src/patient-registration/field/name/name-field.component.tsx +1 -1
- package/src/patient-registration/field/obs/obs-field.component.tsx +35 -33
- package/src/patient-registration/field/obs/obs-field.test.tsx +106 -28
- package/src/patient-registration/field/person-attributes/coded-attributes.component.tsx +1 -1
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +70 -24
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +54 -30
- package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +4 -3
- package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +1 -1
- package/src/patient-registration/field/person-attributes/{person-attributes.resource.tsx → person-attributes.resource.ts} +3 -3
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.component.tsx +1 -1
- package/src/patient-registration/field/phone/phone-field.component.tsx +16 -0
- package/src/patient-registration/form-manager.test.ts +1 -1
- package/src/patient-registration/form-manager.ts +22 -24
- package/src/patient-registration/input/basic-input/select/select-input.test.tsx +3 -3
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.component.tsx +5 -5
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +70 -58
- package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +2 -2
- package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +2 -5
- package/src/patient-registration/input/custom-input/identifier/utils.ts +1 -1
- package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +1 -1
- package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +6 -6
- package/src/patient-registration/patient-registration-context.ts +3 -4
- package/src/patient-registration/patient-registration-hooks.ts +25 -20
- package/src/patient-registration/patient-registration-utils.ts +7 -7
- package/src/patient-registration/patient-registration.component.tsx +20 -10
- package/src/patient-registration/patient-registration.resource.test.tsx +3 -3
- package/src/patient-registration/{patient-registration.resource.tsx → patient-registration.resource.ts} +15 -15
- package/src/patient-registration/patient-registration.test.tsx +270 -251
- package/src/patient-registration/{patient-registration.types.tsx → patient-registration.types.ts} +12 -3
- package/src/patient-registration/section/death-info/death-info-section.test.tsx +33 -45
- package/src/patient-registration/section/demographics/demographics-section.test.tsx +1 -2
- package/src/patient-registration/section/generic-section.component.tsx +1 -1
- package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +3 -3
- package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +17 -5
- package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +4 -4
- package/src/patient-registration/section/section-wrapper.component.tsx +1 -1
- package/src/patient-registration/section/section.component.tsx +1 -1
- package/src/patient-registration/validation/patient-registration-validation.test.tsx +140 -126
- package/src/patient-registration/validation/patient-registration-validation.tsx +54 -46
- package/src/patient-verification/patient-verification-hook.tsx +13 -4
- package/src/patient-verification/patient-verification-utils.ts +20 -12
- package/src/patient-verification/patient-verification.component.tsx +13 -6
- package/src/patient-verification/patient-verification.scss +0 -1
- package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +2 -11
- package/src/routes.json +1 -0
- package/src/widgets/cancel-patient-edit.test.tsx +7 -4
- package/src/widgets/delete-identifier-confirmation-modal.test.tsx +7 -4
- package/src/widgets/display-photo.test.tsx +1 -1
- package/src/widgets/edit-patient-details-button.test.tsx +12 -7
- package/translations/am.json +30 -14
- package/translations/ar.json +30 -14
- package/translations/en.json +11 -11
- package/translations/es.json +34 -22
- package/translations/fr.json +48 -40
- package/translations/he.json +22 -2
- package/translations/km.json +22 -2
- package/translations/zh.json +97 -0
- package/translations/zh_CN.json +97 -0
- package/tsconfig.json +1 -1
- package/__mocks__/autogenerationoptions.mock.ts +0 -34
- package/dist/388.js +0 -2
- package/dist/388.js.map +0 -1
- package/dist/598.js +0 -1
- package/dist/598.js.map +0 -1
- package/dist/openmrs-esm-patient-registration-app.js.map +0 -1
- package/src/patient-registration/field/__mocks__/identifier-types.mock.ts +0 -76
- package/src/patient-registration/field/__mocks__/identifiers.mock.ts +0 -27
- package/src/patient-registration/field/address/tests/mocks.ts +0 -98
|
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react';
|
|
|
3
3
|
import { Formik, Form } from 'formik';
|
|
4
4
|
import { initialFormValues } from '../../patient-registration.component';
|
|
5
5
|
import { DeathInfoSection } from './death-info-section.component';
|
|
6
|
-
import { FormValues } from '../../patient-registration
|
|
6
|
+
import { type FormValues } from '../../patient-registration.types';
|
|
7
7
|
import { PatientRegistrationContext } from '../../patient-registration-context';
|
|
8
8
|
|
|
9
9
|
jest.mock('@openmrs/esm-framework', () => {
|
|
@@ -15,62 +15,50 @@ jest.mock('@openmrs/esm-framework', () => {
|
|
|
15
15
|
};
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const initialContextValues = {
|
|
19
|
+
currentPhoto: 'data:image/png;base64,1234567890',
|
|
20
|
+
identifierTypes: [],
|
|
21
|
+
inEditMode: false,
|
|
22
|
+
initialFormValues: {} as FormValues,
|
|
23
|
+
isOffline: false,
|
|
24
|
+
setCapturePhotoProps: jest.fn(),
|
|
25
|
+
setFieldValue: jest.fn(),
|
|
26
|
+
setInitialFormValues: jest.fn(),
|
|
27
|
+
validationSchema: null,
|
|
28
|
+
values: {
|
|
29
|
+
isDead: true,
|
|
30
|
+
} as FormValues,
|
|
31
|
+
};
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
describe('Death info section', () => {
|
|
34
|
+
const renderDeathInfoSection = (isDead) => {
|
|
35
|
+
initialContextValues.values.isDead = isDead;
|
|
36
|
+
|
|
37
|
+
return render(
|
|
38
|
+
<PatientRegistrationContext.Provider value={initialContextValues}>
|
|
39
|
+
<Formik initialValues={initialFormValues} onSubmit={jest.fn()}>
|
|
26
40
|
<Form>
|
|
27
41
|
<DeathInfoSection />
|
|
28
42
|
</Form>
|
|
29
43
|
</Formik>
|
|
30
44
|
</PatientRegistrationContext.Provider>,
|
|
31
45
|
);
|
|
32
|
-
const allInputs = screen.queryAllByLabelText(
|
|
33
|
-
(content, element) => element.tagName.toLowerCase() === 'input',
|
|
34
|
-
) as Array<HTMLInputElement>;
|
|
35
|
-
const allSelects = screen.queryAllByRole('combobox') as Array<HTMLInputElement>;
|
|
36
|
-
let inputAndSelectNames = [];
|
|
37
|
-
allInputs.forEach((input) => inputAndSelectNames.push(input.name));
|
|
38
|
-
allSelects.forEach((select) => inputAndSelectNames.push(select.name));
|
|
39
|
-
return inputAndSelectNames;
|
|
40
46
|
};
|
|
41
47
|
|
|
42
|
-
it('
|
|
43
|
-
|
|
44
|
-
expect(inputAndSelectNames.length).toBe(3);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('has the correct number of inputs if is dead is not checked', async () => {
|
|
48
|
-
const inputAndSelectNames = await setupSection(false);
|
|
49
|
-
expect(inputAndSelectNames.length).toBe(1);
|
|
50
|
-
});
|
|
48
|
+
it('shows fields for recording death info when the patient is marked as dead', () => {
|
|
49
|
+
renderDeathInfoSection(true);
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
expect(
|
|
51
|
+
expect(screen.getByRole('region', { name: /death info section/i })).toBeInTheDocument();
|
|
52
|
+
expect(screen.getByRole('heading', { name: /death info/i })).toBeInTheDocument();
|
|
53
|
+
expect(screen.getByRole('textbox', { name: /is dead \(optional\)/i })).toBeInTheDocument();
|
|
54
|
+
expect(screen.getByRole('textbox', { name: /date of death \(optional\)/i })).toBeInTheDocument();
|
|
55
|
+
expect(screen.getByRole('combobox', { name: /cause of death \(optional\)/i })).toBeInTheDocument();
|
|
55
56
|
});
|
|
56
57
|
|
|
57
|
-
it('has
|
|
58
|
-
|
|
59
|
-
expect(inputAndSelectNames).toContain('deathDate');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('has no death date if is dead is not checked', async () => {
|
|
63
|
-
const inputAndSelectNames = await setupSection(false);
|
|
64
|
-
expect(inputAndSelectNames).not.toContain('deathDate');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('has death cause if is dead is checked', async () => {
|
|
68
|
-
const inputAndSelectNames = await setupSection(true);
|
|
69
|
-
expect(inputAndSelectNames).toContain('deathCause');
|
|
70
|
-
});
|
|
58
|
+
it('has the correct number of inputs if is dead is not checked', async () => {
|
|
59
|
+
renderDeathInfoSection(false);
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(inputAndSelectNames).not.toContain('deathCause');
|
|
61
|
+
expect(screen.queryByRole('textbox', { name: /date of death \(optional\)/i })).not.toBeInTheDocument();
|
|
62
|
+
expect(screen.queryByRole('combobox', { name: /cause of death \(optional\)/i })).not.toBeInTheDocument();
|
|
75
63
|
});
|
|
76
64
|
});
|
|
@@ -4,7 +4,7 @@ import { Formik, Form } from 'formik';
|
|
|
4
4
|
import { initialFormValues } from '../../patient-registration.component';
|
|
5
5
|
import { DemographicsSection } from './demographics-section.component';
|
|
6
6
|
import { PatientRegistrationContext } from '../../patient-registration-context';
|
|
7
|
-
import { FormValues } from '../../patient-registration.types';
|
|
7
|
+
import { type FormValues } from '../../patient-registration.types';
|
|
8
8
|
|
|
9
9
|
jest.mock('@openmrs/esm-framework', () => {
|
|
10
10
|
const originalModule = jest.requireActual('@openmrs/esm-framework');
|
|
@@ -60,7 +60,6 @@ describe('demographics section', () => {
|
|
|
60
60
|
initialFormValues: null,
|
|
61
61
|
identifierTypes: [],
|
|
62
62
|
validationSchema: {},
|
|
63
|
-
setValidationSchema: () => {},
|
|
64
63
|
values: { ...initialFormValues, birthdateEstimated, addNameInLocalLanguage },
|
|
65
64
|
inEditMode: false,
|
|
66
65
|
setFieldValue: () => {},
|
package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import { Autosuggest } from '../../input/custom-input/autosuggest/autosuggest.co
|
|
|
15
15
|
import { PatientRegistrationContext } from '../../patient-registration-context';
|
|
16
16
|
import { ResourcesContext } from '../../../offline.resources';
|
|
17
17
|
import { fetchPerson } from '../../patient-registration.resource';
|
|
18
|
-
import { RelationshipValue } from '../../patient-registration.types';
|
|
18
|
+
import { type RelationshipValue } from '../../patient-registration.types';
|
|
19
19
|
import sectionStyles from '../section.scss';
|
|
20
20
|
import styles from './relationships.scss';
|
|
21
21
|
|
|
@@ -168,12 +168,12 @@ export const RelationshipsSection = () => {
|
|
|
168
168
|
const tmp: RelationshipType[] = [];
|
|
169
169
|
relationshipTypes.results.forEach((type) => {
|
|
170
170
|
const aIsToB = {
|
|
171
|
-
display: type.displayAIsToB ? type.displayAIsToB : type.
|
|
171
|
+
display: type.displayAIsToB ? type.displayAIsToB : type.displayBIsToA,
|
|
172
172
|
uuid: type.uuid,
|
|
173
173
|
direction: 'aIsToB',
|
|
174
174
|
};
|
|
175
175
|
const bIsToA = {
|
|
176
|
-
display: type.displayBIsToA ? type.displayBIsToA : type.
|
|
176
|
+
display: type.displayBIsToA ? type.displayBIsToA : type.displayAIsToB,
|
|
177
177
|
uuid: type.uuid,
|
|
178
178
|
direction: 'bIsToA',
|
|
179
179
|
};
|
package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { Form, Formik } from 'formik';
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
4
|
import { PatientRegistrationContext } from '../../patient-registration-context';
|
|
5
|
-
import { Resources, ResourcesContext } from '../../../offline.resources';
|
|
5
|
+
import { type Resources, ResourcesContext } from '../../../offline.resources';
|
|
6
6
|
import { RelationshipsSection } from './relationships-section.component';
|
|
7
7
|
|
|
8
8
|
jest.mock('../../patient-registration.resource', () => ({
|
|
@@ -17,7 +17,7 @@ jest.mock('../../patient-registration.resource', () => ({
|
|
|
17
17
|
}));
|
|
18
18
|
|
|
19
19
|
let mockResourcesContextValue = {
|
|
20
|
-
addressTemplate:
|
|
20
|
+
addressTemplate: null,
|
|
21
21
|
currentSession: {
|
|
22
22
|
authenticated: true,
|
|
23
23
|
sessionId: 'JSESSION',
|
|
@@ -40,15 +40,27 @@ describe('RelationshipsSection', () => {
|
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
expect(screen.getByLabelText(/loading relationships section/i)).toBeInTheDocument();
|
|
43
|
-
expect(screen.getByRole(
|
|
43
|
+
expect(screen.getByRole('progressbar')).toBeInTheDocument();
|
|
44
44
|
expect(screen.queryByText(/add relationship/i)).not.toBeInTheDocument();
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
it('renders relationships when relationshipTypes are available', () => {
|
|
48
48
|
const relationshipTypes = {
|
|
49
49
|
results: [
|
|
50
|
-
{
|
|
51
|
-
|
|
50
|
+
{
|
|
51
|
+
displayAIsToB: 'Mother',
|
|
52
|
+
aIsToB: 'Mother',
|
|
53
|
+
bIsToA: 'Child',
|
|
54
|
+
displayBIsToA: 'Child',
|
|
55
|
+
uuid: '42ae5ce0-d64b-11ea-9064-5adc43bbdd34',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
displayAIsToB: 'Father',
|
|
59
|
+
aIsToB: 'Father',
|
|
60
|
+
bIsToA: 'Child',
|
|
61
|
+
displayBIsToA: 'Child',
|
|
62
|
+
uuid: '52ae5ce0-d64b-11ea-9064-5adc43bbdd24',
|
|
63
|
+
},
|
|
52
64
|
],
|
|
53
65
|
};
|
|
54
66
|
mockResourcesContextValue = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
|
|
2
|
-
import { RelationshipValue } from '../../patient-registration.types';
|
|
3
|
-
import useSWR from 'swr';
|
|
4
1
|
import { useMemo } from 'react';
|
|
2
|
+
import useSWR from 'swr';
|
|
3
|
+
import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
4
|
+
import { type RelationshipValue } from '../../patient-registration.types';
|
|
5
5
|
import { personRelationshipRepresentation } from '../../../constants';
|
|
6
6
|
|
|
7
7
|
export function useInitialPatientRelationships(patientUuid: string): {
|
|
@@ -10,7 +10,7 @@ export function useInitialPatientRelationships(patientUuid: string): {
|
|
|
10
10
|
} {
|
|
11
11
|
const shouldFetch = !!patientUuid;
|
|
12
12
|
const { data, error, isLoading } = useSWR<FetchResponse<RelationshipsResponse>, Error>(
|
|
13
|
-
shouldFetch ?
|
|
13
|
+
shouldFetch ? `${restBaseUrl}/relationship?v=${personRelationshipRepresentation}&person=${patientUuid}` : null,
|
|
14
14
|
openmrsFetch,
|
|
15
15
|
);
|
|
16
16
|
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import styles from '../patient-registration.scss';
|
|
3
3
|
import { Tile } from '@carbon/react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { SectionDefinition } from '../../config-schema';
|
|
5
|
+
import { type SectionDefinition } from '../../config-schema';
|
|
6
6
|
import { Section } from './section.component';
|
|
7
7
|
|
|
8
8
|
export interface SectionWrapperProps {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { SectionDefinition } from '../../config-schema';
|
|
2
|
+
import { type SectionDefinition } from '../../config-schema';
|
|
3
3
|
import { GenericSection } from './generic-section.component';
|
|
4
4
|
import { DeathInfoSection } from './death-info/death-info-section.component';
|
|
5
5
|
import { DemographicsSection } from './demographics/demographics-section.component';
|
|
@@ -1,143 +1,157 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { defineConfigSchema, getConfig } from '@openmrs/esm-framework';
|
|
2
|
+
import { getValidationSchema } from './patient-registration-validation';
|
|
3
|
+
import { type RegistrationConfig, esmPatientRegistrationSchema } from '../../config-schema';
|
|
3
4
|
describe('Patient Registration Validation', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
identifierValue: '',
|
|
23
|
-
},
|
|
5
|
+
beforeAll(() => {
|
|
6
|
+
defineConfigSchema('@openmrs/esm-patient-registration-app', esmPatientRegistrationSchema);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const validFormValues = {
|
|
10
|
+
givenName: 'John',
|
|
11
|
+
familyName: 'Doe',
|
|
12
|
+
additionalGivenName: '',
|
|
13
|
+
additionalFamilyName: '',
|
|
14
|
+
gender: 'male',
|
|
15
|
+
birthdate: new Date('1990-01-01'),
|
|
16
|
+
birthdateEstimated: false,
|
|
17
|
+
deathDate: null,
|
|
18
|
+
email: 'john.doe@example.com',
|
|
19
|
+
identifiers: {
|
|
20
|
+
nationalId: {
|
|
21
|
+
required: true,
|
|
22
|
+
identifierValue: '123456789',
|
|
24
23
|
},
|
|
25
|
-
|
|
24
|
+
passportId: {
|
|
25
|
+
required: false,
|
|
26
|
+
identifierValue: '',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const validateFormValues = async (formValues) => {
|
|
32
|
+
const config = (await getConfig('@openmrs/esm-patient-registration-app')) as any as RegistrationConfig;
|
|
33
|
+
const validationSchema = getValidationSchema(config);
|
|
34
|
+
try {
|
|
35
|
+
await validationSchema.validate(formValues, { abortEarly: false });
|
|
36
|
+
} catch (err) {
|
|
37
|
+
return err;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
it('should allow valid form values', async () => {
|
|
42
|
+
const validationError = await validateFormValues(validFormValues);
|
|
43
|
+
expect(validationError).toBeFalsy();
|
|
44
|
+
});
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
it('should require givenName', async () => {
|
|
47
|
+
const invalidFormValues = {
|
|
48
|
+
...validFormValues,
|
|
49
|
+
givenName: '',
|
|
50
|
+
};
|
|
51
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
52
|
+
expect(validationError.errors).toContain('givenNameRequired');
|
|
53
|
+
});
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
it('should require familyName', async () => {
|
|
56
|
+
const invalidFormValues = {
|
|
57
|
+
...validFormValues,
|
|
58
|
+
familyName: '',
|
|
59
|
+
};
|
|
60
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
61
|
+
expect(validationError.errors).toContain('familyNameRequired');
|
|
62
|
+
});
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
it('should require additionalGivenName when addNameInLocalLanguage is true', async () => {
|
|
65
|
+
const invalidFormValues = {
|
|
66
|
+
...validFormValues,
|
|
67
|
+
addNameInLocalLanguage: true,
|
|
68
|
+
additionalGivenName: '',
|
|
69
|
+
};
|
|
70
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
71
|
+
expect(validationError.errors).toContain('givenNameRequired');
|
|
72
|
+
});
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
it('should require additionalFamilyName when addNameInLocalLanguage is true', async () => {
|
|
75
|
+
const invalidFormValues = {
|
|
76
|
+
...validFormValues,
|
|
77
|
+
addNameInLocalLanguage: true,
|
|
78
|
+
additionalFamilyName: '',
|
|
79
|
+
};
|
|
80
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
81
|
+
expect(validationError.errors).toContain('familyNameRequired');
|
|
82
|
+
});
|
|
77
83
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
it('should require gender', async () => {
|
|
85
|
+
const invalidFormValues = {
|
|
86
|
+
...validFormValues,
|
|
87
|
+
gender: '',
|
|
88
|
+
};
|
|
89
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
90
|
+
expect(validationError.errors).toContain('genderUnspecified');
|
|
91
|
+
});
|
|
86
92
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
it('should allow female as a valid gender', async () => {
|
|
94
|
+
const validFormValuesWithOtherGender = {
|
|
95
|
+
...validFormValues,
|
|
96
|
+
gender: 'female',
|
|
97
|
+
};
|
|
98
|
+
const validationError = await validateFormValues(validFormValuesWithOtherGender);
|
|
99
|
+
expect(validationError).toBeFalsy();
|
|
100
|
+
});
|
|
95
101
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
it('should allow other as a valid gender', async () => {
|
|
103
|
+
const validFormValuesWithOtherGender = {
|
|
104
|
+
...validFormValues,
|
|
105
|
+
gender: 'other',
|
|
106
|
+
};
|
|
107
|
+
const validationError = await validateFormValues(validFormValuesWithOtherGender);
|
|
108
|
+
expect(validationError).toBeFalsy();
|
|
109
|
+
});
|
|
104
110
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
it('should allow unknown as a valid gender', async () => {
|
|
112
|
+
const validFormValuesWithOtherGender = {
|
|
113
|
+
...validFormValues,
|
|
114
|
+
gender: 'unknown',
|
|
115
|
+
};
|
|
116
|
+
const validationError = await validateFormValues(validFormValuesWithOtherGender);
|
|
117
|
+
expect(validationError).toBeFalsy();
|
|
118
|
+
});
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
it('should throw error when date of birth is a future date', async () => {
|
|
121
|
+
const invalidFormValues = {
|
|
122
|
+
...validFormValues,
|
|
123
|
+
birthdate: new Date('2100-01-01'),
|
|
124
|
+
};
|
|
125
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
126
|
+
expect(validationError.errors).toContain('birthdayNotInTheFuture');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should require yearsEstimated when birthdateEstimated is true', async () => {
|
|
130
|
+
const invalidFormValues = {
|
|
131
|
+
...validFormValues,
|
|
132
|
+
birthdateEstimated: true,
|
|
133
|
+
};
|
|
134
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
135
|
+
expect(validationError.errors).toContain('yearsEstimateRequired');
|
|
136
|
+
});
|
|
122
137
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
138
|
+
it('should throw error when monthEstimated is negative', async () => {
|
|
139
|
+
const invalidFormValues = {
|
|
140
|
+
...validFormValues,
|
|
141
|
+
birthdateEstimated: true,
|
|
142
|
+
yearsEstimated: 0,
|
|
143
|
+
monthsEstimated: -1,
|
|
144
|
+
};
|
|
145
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
146
|
+
expect(validationError.errors).toContain('negativeMonths');
|
|
147
|
+
});
|
|
133
148
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
});
|
|
149
|
+
it('should throw error when deathDate is in future', async () => {
|
|
150
|
+
const invalidFormValues = {
|
|
151
|
+
...validFormValues,
|
|
152
|
+
deathDate: new Date('2100-01-01'),
|
|
153
|
+
};
|
|
154
|
+
const validationError = await validateFormValues(invalidFormValues);
|
|
155
|
+
expect(validationError.errors).toContain('deathdayNotInTheFuture');
|
|
142
156
|
});
|
|
143
157
|
});
|
|
@@ -1,52 +1,60 @@
|
|
|
1
1
|
import * as Yup from 'yup';
|
|
2
2
|
import mapValues from 'lodash/mapValues';
|
|
3
|
-
import { FormValues } from '../patient-registration.types';
|
|
3
|
+
import { type FormValues } from '../patient-registration.types';
|
|
4
|
+
import { type RegistrationConfig } from '../../config-schema';
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
6
|
+
export function getValidationSchema(config: RegistrationConfig) {
|
|
7
|
+
return Yup.object({
|
|
8
|
+
givenName: Yup.string().required('givenNameRequired'),
|
|
9
|
+
familyName: Yup.string().required('familyNameRequired'),
|
|
10
|
+
additionalGivenName: Yup.string().when('addNameInLocalLanguage', {
|
|
11
|
+
is: true,
|
|
12
|
+
then: Yup.string().required('givenNameRequired'),
|
|
13
|
+
otherwise: Yup.string().notRequired(),
|
|
14
|
+
}),
|
|
15
|
+
additionalFamilyName: Yup.string().when('addNameInLocalLanguage', {
|
|
16
|
+
is: true,
|
|
17
|
+
then: Yup.string().required('familyNameRequired'),
|
|
18
|
+
otherwise: Yup.string().notRequired(),
|
|
19
|
+
}),
|
|
20
|
+
gender: Yup.string()
|
|
21
|
+
.oneOf(
|
|
22
|
+
config.fieldConfigurations.gender.map((g) => g.value),
|
|
23
|
+
'genderUnspecified',
|
|
24
|
+
)
|
|
25
|
+
.required('genderRequired'),
|
|
26
|
+
birthdate: Yup.date().when('birthdateEstimated', {
|
|
27
|
+
is: false,
|
|
28
|
+
then: Yup.date().required('birthdayRequired').max(Date(), 'birthdayNotInTheFuture').nullable(),
|
|
29
|
+
otherwise: Yup.date().nullable(),
|
|
30
|
+
}),
|
|
31
|
+
yearsEstimated: Yup.number().when('birthdateEstimated', {
|
|
32
|
+
is: true,
|
|
33
|
+
then: Yup.number().required('yearsEstimateRequired').min(0, 'negativeYears'),
|
|
34
|
+
otherwise: Yup.number().nullable(),
|
|
35
|
+
}),
|
|
36
|
+
monthsEstimated: Yup.number().min(0, 'negativeMonths'),
|
|
37
|
+
deathDate: Yup.date().max(Date(), 'deathdayNotInTheFuture').nullable(),
|
|
38
|
+
email: Yup.string().optional().email('invalidEmail'),
|
|
39
|
+
identifiers: Yup.lazy((obj: FormValues['identifiers']) =>
|
|
40
|
+
Yup.object(
|
|
41
|
+
mapValues(obj, () =>
|
|
42
|
+
Yup.object({
|
|
43
|
+
required: Yup.bool(),
|
|
44
|
+
identifierValue: Yup.string().when('required', {
|
|
45
|
+
is: true,
|
|
46
|
+
then: Yup.string().required('identifierValueRequired'),
|
|
47
|
+
otherwise: Yup.string().notRequired(),
|
|
48
|
+
}),
|
|
41
49
|
}),
|
|
42
|
-
|
|
50
|
+
),
|
|
43
51
|
),
|
|
44
52
|
),
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
+
relationships: Yup.array().of(
|
|
54
|
+
Yup.object().shape({
|
|
55
|
+
relatedPersonUuid: Yup.string().required(),
|
|
56
|
+
relationshipType: Yup.string().required(),
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
59
|
+
});
|
|
60
|
+
}
|