@olaboot/esm-patient-registration-app 9.2.0 → 10.0.2
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/1339.js +1 -0
- package/dist/1339.js.map +1 -0
- package/dist/1480.js +1 -0
- package/dist/1480.js.map +1 -0
- package/dist/1646.js +1 -0
- package/dist/1646.js.map +1 -0
- package/dist/1789.js +1 -0
- package/dist/1789.js.map +1 -0
- package/dist/1869.js +1 -0
- package/dist/1869.js.map +1 -0
- package/dist/1877.js +1 -0
- package/dist/1877.js.map +1 -0
- package/dist/2317.js +1 -0
- package/dist/2317.js.map +1 -0
- package/dist/2416.js +1 -0
- package/dist/2416.js.map +1 -0
- package/dist/2747.js +1 -0
- package/dist/2747.js.map +1 -0
- package/dist/282.js +1 -0
- package/dist/282.js.map +1 -0
- package/dist/2881.js +1 -0
- package/dist/2881.js.map +1 -0
- package/dist/3378.js +1 -0
- package/dist/3378.js.map +1 -0
- package/dist/3720.js +1 -0
- package/dist/3720.js.map +1 -0
- package/dist/3906.js +1 -0
- package/dist/3906.js.map +1 -0
- package/dist/3963.js +1 -0
- package/dist/3963.js.map +1 -0
- package/dist/3989.js +1 -0
- package/dist/3989.js.map +1 -0
- package/dist/4106.js +1 -0
- package/dist/4106.js.map +1 -0
- package/dist/4111.js +1 -0
- package/dist/4111.js.map +1 -0
- package/dist/434.js +1 -0
- package/dist/434.js.map +1 -0
- package/dist/4348.js +1 -0
- package/dist/4348.js.map +1 -0
- package/dist/4383.js +1 -0
- package/dist/4383.js.map +1 -0
- package/dist/4658.js +1 -0
- package/dist/4658.js.map +1 -0
- package/dist/466.js +1 -0
- package/dist/466.js.map +1 -0
- package/dist/4928.js +1 -0
- package/dist/4928.js.map +1 -0
- package/dist/5117.js +1 -0
- package/dist/5117.js.map +1 -0
- package/dist/5132.js +1 -0
- package/dist/5132.js.map +1 -0
- package/dist/5145.js +1 -0
- package/dist/5145.js.map +1 -0
- package/dist/5208.js +43 -0
- package/dist/5208.js.map +1 -0
- package/dist/527.js +1 -0
- package/dist/527.js.map +1 -0
- package/dist/5280.js +1 -0
- package/dist/5280.js.map +1 -0
- package/dist/5338.js +6 -0
- package/dist/5338.js.map +1 -0
- package/dist/5503.js +1 -0
- package/dist/5503.js.map +1 -0
- package/dist/555.js +1 -0
- package/dist/555.js.map +1 -0
- package/dist/556.js +1 -0
- package/dist/556.js.map +1 -0
- package/dist/5644.js +1 -0
- package/dist/5644.js.map +1 -0
- package/dist/5697.js +1 -0
- package/dist/{4024.js.map → 5697.js.map} +1 -1
- package/dist/5940.js +1 -0
- package/dist/5940.js.map +1 -0
- package/dist/6047.js +1 -0
- package/dist/6047.js.map +1 -0
- package/dist/6371.js +1 -0
- package/dist/6371.js.map +1 -0
- package/dist/6377.js +1 -0
- package/dist/6377.js.map +1 -0
- package/dist/6388.js +1 -0
- package/dist/6388.js.map +1 -0
- package/dist/6444.js +1 -0
- package/dist/6444.js.map +1 -0
- package/dist/6508.js +1 -0
- package/dist/6508.js.map +1 -0
- package/dist/6724.js +1 -0
- package/dist/6724.js.map +1 -0
- package/dist/689.js +1 -0
- package/dist/689.js.map +1 -0
- package/dist/6904.js +1 -0
- package/dist/6904.js.map +1 -0
- package/dist/7045.js +1 -0
- package/dist/7045.js.map +1 -0
- package/dist/7175.js +1 -0
- package/dist/7175.js.map +1 -0
- package/dist/7182.js +1 -0
- package/dist/7182.js.map +1 -0
- package/dist/7649.js +1 -0
- package/dist/7649.js.map +1 -0
- package/dist/7742.js +1 -0
- package/dist/7742.js.map +1 -0
- package/dist/7912.js +1 -0
- package/dist/7912.js.map +1 -0
- package/dist/8358.js +1 -0
- package/dist/8358.js.map +1 -0
- package/dist/8359.js +1 -0
- package/dist/8359.js.map +1 -0
- package/dist/8695.js +1 -0
- package/dist/8695.js.map +1 -0
- package/dist/903.js +1 -0
- package/dist/903.js.map +1 -0
- package/dist/9061.js +1 -0
- package/dist/9061.js.map +1 -0
- package/dist/9072.js +1 -0
- package/dist/9072.js.map +1 -0
- package/dist/9397.js +1 -0
- package/dist/9397.js.map +1 -0
- package/dist/9712.js +1 -0
- package/dist/9712.js.map +1 -0
- package/dist/9771.js +1 -0
- package/dist/9771.js.map +1 -0
- package/dist/9806.js +1 -0
- package/dist/9806.js.map +1 -0
- package/dist/9816.js +1 -0
- package/dist/9816.js.map +1 -0
- package/dist/main.js +7 -6
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-registration-app.js +6 -0
- package/dist/{olaboot-esm-patient-registration-app.js.buildmanifest.json → openmrs-esm-patient-registration-app.js.buildmanifest.json} +540 -455
- package/dist/openmrs-esm-patient-registration-app.js.map +1 -0
- package/dist/routes.json +1 -1
- package/package.json +8 -9
- package/src/add-patient-link.extension.tsx +3 -2
- package/src/add-patient-link.test.tsx +2 -1
- package/src/config-schema.ts +1 -1
- package/src/index.ts +2 -24
- package/src/nav-link.test.tsx +1 -0
- package/src/offline.resources.ts +97 -31
- package/src/patient-registration/before-save-prompt.test.tsx +199 -0
- package/src/patient-registration/field/__mocks__/field.resource.ts +8 -7
- package/src/patient-registration/field/address/address-field.component.tsx +10 -13
- package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +6 -1
- package/src/patient-registration/field/address/address-hierarchy.test.tsx +191 -198
- package/src/patient-registration/field/address/address-search.component.tsx +20 -8
- package/src/patient-registration/field/address/address-search.scss +19 -2
- package/src/patient-registration/field/address/address-search.test.tsx +249 -57
- package/src/patient-registration/field/address/custom-address-field.component.tsx +1 -1
- package/src/patient-registration/field/cause-of-death/cause-of-death.component.tsx +1 -1
- package/src/patient-registration/field/cause-of-death/cause-of-death.test.tsx +251 -0
- package/src/patient-registration/field/custom-field.component.tsx +1 -1
- package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +1 -1
- package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.test.tsx +144 -0
- package/src/patient-registration/field/dob/dob.component.tsx +2 -2
- package/src/patient-registration/field/dob/dob.test.tsx +370 -54
- package/src/patient-registration/field/field.component.tsx +1 -1
- package/src/patient-registration/field/field.resource.ts +2 -2
- package/src/patient-registration/field/field.test.tsx +25 -22
- package/src/patient-registration/field/gender/gender-field.test.tsx +240 -54
- package/src/patient-registration/field/id/id-field.component.tsx +15 -5
- package/src/patient-registration/field/id/id-field.test.tsx +103 -47
- package/src/patient-registration/field/id/identifier-selection-overlay.test.tsx +346 -0
- package/src/patient-registration/field/name/name-field.component.tsx +2 -2
- package/src/patient-registration/field/name/name-field.test.tsx +282 -0
- package/src/patient-registration/field/obs/obs-field.test.tsx +294 -118
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +172 -108
- package/src/patient-registration/field/person-attributes/location-person-attribute-field.component.tsx +3 -3
- package/src/patient-registration/field/person-attributes/location-person-attribute-field.resource.tsx +2 -5
- package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +2 -2
- package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +249 -131
- package/src/patient-registration/field/person-attributes/person-attributes.resource.ts +1 -1
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +98 -70
- package/src/patient-registration/field/phone/phone-field.test.tsx +100 -0
- package/src/patient-registration/form-manager.test.ts +6 -5
- package/src/patient-registration/form-manager.ts +5 -2
- package/src/patient-registration/input/basic-input/input/input.component.tsx +3 -121
- package/src/patient-registration/input/basic-input/input/input.test.tsx +151 -51
- package/src/patient-registration/input/basic-input/select/select-input.test.tsx +113 -33
- package/src/patient-registration/input/combo-input/combo-input.component.tsx +60 -24
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.component.tsx +10 -101
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +144 -108
- package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +241 -177
- package/src/patient-registration/input/custom-input/identifier/utils.test.ts +47 -8
- package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +12 -12
- package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +52 -20
- package/src/patient-registration/input/input.scss +1 -2
- package/src/patient-registration/patient-registration-context.ts +5 -3
- package/src/patient-registration/patient-registration-hooks.ts +4 -12
- package/src/patient-registration/patient-registration-utils.test.ts +2 -1
- package/src/patient-registration/patient-registration-utils.ts +2 -98
- package/src/patient-registration/patient-registration.component.tsx +50 -46
- package/src/patient-registration/patient-registration.resource.test.tsx +4 -7
- package/src/patient-registration/patient-registration.resource.ts +1 -4
- package/src/patient-registration/patient-registration.scss +16 -3
- package/src/patient-registration/patient-registration.test.tsx +99 -65
- package/src/patient-registration/patient-registration.types.ts +17 -28
- package/src/patient-registration/section/death-info/death-info-section.test.tsx +130 -34
- package/src/patient-registration/section/demographics/demographics-section.test.tsx +122 -68
- package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +15 -15
- package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +278 -84
- package/src/patient-registration/section/section-wrapper.component.tsx +1 -1
- package/src/patient-registration/ui-components/overlay/overlay.test.tsx +104 -0
- package/src/patient-registration/validation/patient-registration-validation.test.ts +2 -1
- package/src/patient-registration/validation/patient-registration-validation.ts +9 -3
- package/src/root.component.tsx +2 -5
- package/src/widgets/cancel-patient-edit.test.tsx +48 -11
- package/src/widgets/delete-identifier-confirmation.test.tsx +77 -24
- package/src/widgets/edit-patient-details-button.component.tsx +14 -18
- package/src/widgets/edit-patient-details-button.scss +2 -2
- package/src/widgets/edit-patient-details-button.test.tsx +11 -13
- package/translations/am.json +9 -4
- package/translations/ar.json +9 -4
- package/translations/ar_SY.json +9 -4
- package/translations/bn.json +9 -4
- package/translations/cs.json +9 -4
- package/translations/de.json +120 -115
- package/translations/en.json +9 -4
- package/translations/en_US.json +9 -4
- package/translations/es.json +9 -4
- package/translations/es_MX.json +9 -4
- package/translations/fr.json +9 -4
- package/translations/he.json +9 -4
- package/translations/hi.json +9 -4
- package/translations/hi_IN.json +9 -4
- package/translations/id.json +9 -4
- package/translations/it.json +9 -4
- package/translations/ka.json +9 -4
- package/translations/km.json +9 -4
- package/translations/ku.json +9 -4
- package/translations/ky.json +9 -4
- package/translations/lg.json +9 -4
- package/translations/ne.json +9 -4
- package/translations/pl.json +9 -4
- package/translations/pt.json +9 -4
- package/translations/pt_BR.json +10 -5
- package/translations/qu.json +9 -4
- package/translations/ro_RO.json +9 -4
- package/translations/ru_RU.json +9 -4
- package/translations/si.json +9 -4
- package/translations/sq.json +9 -4
- package/translations/sw.json +9 -4
- package/translations/sw_KE.json +9 -4
- package/translations/tr.json +9 -4
- package/translations/tr_TR.json +9 -4
- package/translations/uk.json +9 -4
- package/translations/uz.json +9 -4
- package/translations/uz@Latn.json +9 -4
- package/translations/uz_UZ.json +9 -4
- package/translations/vi.json +9 -4
- package/translations/zh.json +50 -45
- package/translations/zh_CN.json +9 -4
- package/translations/zh_TW.json +9 -4
- package/vitest.config.ts +4 -0
- package/ADDRESS_CONFIGURATION.md +0 -152
- package/IDENTIFIER_CONFIGURATION.md +0 -142
- package/IMPLEMENTATION_SUMMARY.md +0 -111
- package/QUICK_START.md +0 -95
- package/address-required-fields-config.json +0 -26
- package/dist/126.js +0 -1
- package/dist/15.js +0 -1
- package/dist/1564.js +0 -1
- package/dist/1567.js +0 -1
- package/dist/1845.js +0 -1
- package/dist/1953.js +0 -1
- package/dist/200.js +0 -1
- package/dist/200.js.map +0 -1
- package/dist/215.js +0 -1
- package/dist/2178.js +0 -1
- package/dist/250.js +0 -1
- package/dist/250.js.map +0 -1
- package/dist/2523.js +0 -1
- package/dist/2523.js.map +0 -1
- package/dist/2566.js +0 -1
- package/dist/2586.js +0 -1
- package/dist/2586.js.map +0 -1
- package/dist/2716.js +0 -1
- package/dist/2716.js.map +0 -1
- package/dist/2759.js +0 -1
- package/dist/2821.js +0 -6
- package/dist/2821.js.map +0 -1
- package/dist/3089.js +0 -1
- package/dist/3089.js.map +0 -1
- package/dist/3230.js +0 -1
- package/dist/3441.js +0 -1
- package/dist/3565.js +0 -1
- package/dist/3571.js +0 -1
- package/dist/3571.js.map +0 -1
- package/dist/3746.js +0 -1
- package/dist/3925.js +0 -1
- package/dist/3946.js +0 -1
- package/dist/4024.js +0 -1
- package/dist/4744.js +0 -1
- package/dist/4744.js.map +0 -1
- package/dist/4809.js +0 -1
- package/dist/4894.js +0 -1
- package/dist/4970.js +0 -1
- package/dist/4970.js.map +0 -1
- package/dist/5130.js +0 -1
- package/dist/5187.js +0 -1
- package/dist/5491.js +0 -1
- package/dist/5491.js.map +0 -1
- package/dist/5595.js +0 -1
- package/dist/5961.js +0 -1
- package/dist/6133.js +0 -1
- package/dist/634.js +0 -1
- package/dist/634.js.map +0 -1
- package/dist/6456.js +0 -1
- package/dist/6466.js +0 -1
- package/dist/6613.js +0 -1
- package/dist/6783.js +0 -1
- package/dist/7073.js +0 -38
- package/dist/7073.js.map +0 -1
- package/dist/7154.js +0 -1
- package/dist/7154.js.map +0 -1
- package/dist/7348.js +0 -1
- package/dist/7439.js +0 -1
- package/dist/7439.js.map +0 -1
- package/dist/7543.js +0 -1
- package/dist/7607.js +0 -1
- package/dist/772.js +0 -1
- package/dist/7984.js +0 -1
- package/dist/7984.js.map +0 -1
- package/dist/8538.js +0 -1
- package/dist/8538.js.map +0 -1
- package/dist/8599.js +0 -1
- package/dist/8727.js +0 -1
- package/dist/8847.js +0 -1
- package/dist/9015.js +0 -1
- package/dist/906.js +0 -1
- package/dist/9065.js +0 -1
- package/dist/9182.js +0 -1
- package/dist/9339.js +0 -1
- package/dist/9453.js +0 -1
- package/dist/9833.js +0 -1
- package/dist/9833.js.map +0 -1
- package/dist/9856.js +0 -1
- package/dist/9856.js.map +0 -1
- package/dist/9920.js +0 -1
- package/dist/9938.js +0 -1
- package/dist/9943.js +0 -1
- package/dist/9943.js.map +0 -1
- package/dist/olaboot-esm-patient-registration-app.js +0 -5
- package/dist/olaboot-esm-patient-registration-app.js.map +0 -1
- package/example-config.json +0 -14
- package/jest.config.js +0 -3
- package/src/resource.ts +0 -12
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { vi, describe, it, expect, test, beforeEach } from 'vitest';
|
|
2
3
|
import { Form, Formik } from 'formik';
|
|
3
4
|
import { render, screen } from '@testing-library/react';
|
|
4
5
|
import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
|
|
@@ -10,7 +11,7 @@ import { PatientRegistrationContextProvider } from '../patient-registration-cont
|
|
|
10
11
|
import { ResourcesContextProvider } from '../../resources-context';
|
|
11
12
|
import { renderWithContext } from 'tools';
|
|
12
13
|
|
|
13
|
-
const mockUseConfig =
|
|
14
|
+
const mockUseConfig = vi.mocked(useConfig<RegistrationConfig>);
|
|
14
15
|
|
|
15
16
|
const predefinedAddressTemplate = {
|
|
16
17
|
uuid: 'test-address-template-uuid',
|
|
@@ -90,7 +91,7 @@ const mockResourcesContextValue: Resources = {
|
|
|
90
91
|
sessionId: 'JSESSION',
|
|
91
92
|
currentProvider: { uuid: 'provider-uuid', identifier: 'PRO-123' },
|
|
92
93
|
},
|
|
93
|
-
relationshipTypes: [],
|
|
94
|
+
relationshipTypes: { results: [] },
|
|
94
95
|
identifierTypes: [...mockIdentifierTypes],
|
|
95
96
|
};
|
|
96
97
|
|
|
@@ -100,10 +101,10 @@ const initialContextValues = {
|
|
|
100
101
|
inEditMode: false,
|
|
101
102
|
initialFormValues: {} as FormValues,
|
|
102
103
|
isOffline: false,
|
|
103
|
-
setCapturePhotoProps:
|
|
104
|
-
setFieldValue:
|
|
105
|
-
setFieldTouched:
|
|
106
|
-
setInitialFormValues:
|
|
104
|
+
setCapturePhotoProps: vi.fn(),
|
|
105
|
+
setFieldValue: vi.fn(),
|
|
106
|
+
setFieldTouched: vi.fn(),
|
|
107
|
+
setInitialFormValues: vi.fn(),
|
|
107
108
|
validationSchema: null,
|
|
108
109
|
values: {} as FormValues,
|
|
109
110
|
};
|
|
@@ -129,7 +130,7 @@ describe('Field', () => {
|
|
|
129
130
|
});
|
|
130
131
|
|
|
131
132
|
renderWithContext(
|
|
132
|
-
<Formik initialValues={{}} onSubmit={
|
|
133
|
+
<Formik initialValues={{}} onSubmit={vi.fn()}>
|
|
133
134
|
<Form>
|
|
134
135
|
<PatientRegistrationContextProvider value={initialContextValues}>
|
|
135
136
|
<Field name="name" />
|
|
@@ -158,7 +159,7 @@ describe('Field', () => {
|
|
|
158
159
|
});
|
|
159
160
|
|
|
160
161
|
renderWithContext(
|
|
161
|
-
<Formik initialValues={{}} onSubmit={
|
|
162
|
+
<Formik initialValues={{}} onSubmit={vi.fn()}>
|
|
162
163
|
<Form>
|
|
163
164
|
<PatientRegistrationContextProvider value={initialContextValues}>
|
|
164
165
|
<Field name="gender" />
|
|
@@ -173,7 +174,7 @@ describe('Field', () => {
|
|
|
173
174
|
|
|
174
175
|
it('should render DobField component when name prop is "dob"', () => {
|
|
175
176
|
renderWithContext(
|
|
176
|
-
<Formik initialValues={{}} onSubmit={
|
|
177
|
+
<Formik initialValues={{}} onSubmit={vi.fn()}>
|
|
177
178
|
<Form>
|
|
178
179
|
<PatientRegistrationContextProvider value={initialContextValues}>
|
|
179
180
|
<Field name="dob" />
|
|
@@ -187,10 +188,13 @@ describe('Field', () => {
|
|
|
187
188
|
expect(screen.getByText('Birth')).toBeInTheDocument();
|
|
188
189
|
});
|
|
189
190
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
// TODO: Re-enable after migrating the in-test `vi.mock` of `address-hierarchy.resource`
|
|
192
|
+
// to a top-level mock with `mockReturnValue` set. The current setup leaves
|
|
193
|
+
// `useOrderedAddressHierarchyLevels` returning undefined and the component crashes.
|
|
194
|
+
it.skip('should render AddressComponent component when name prop is "address"', () => {
|
|
195
|
+
vi.mock('./address/address-hierarchy.resource', async () => ({
|
|
196
|
+
...((await vi.importActual('./address/address-hierarchy.resource')) as object),
|
|
197
|
+
useOrderedAddressHierarchyLevels: vi.fn(),
|
|
194
198
|
}));
|
|
195
199
|
|
|
196
200
|
mockUseConfig.mockReturnValue({
|
|
@@ -202,13 +206,12 @@ describe('Field', () => {
|
|
|
202
206
|
useQuickSearch: false,
|
|
203
207
|
searchAddressByLevel: false,
|
|
204
208
|
},
|
|
205
|
-
requiredAddressFields: [],
|
|
206
209
|
},
|
|
207
210
|
} as RegistrationConfig['fieldConfigurations'],
|
|
208
211
|
});
|
|
209
212
|
|
|
210
213
|
renderWithContext(
|
|
211
|
-
<Formik initialValues={{}} onSubmit={
|
|
214
|
+
<Formik initialValues={{}} onSubmit={vi.fn()}>
|
|
212
215
|
<Form>
|
|
213
216
|
<PatientRegistrationContextProvider value={initialContextValues}>
|
|
214
217
|
<Field name="address" />
|
|
@@ -276,16 +279,16 @@ describe('Field', () => {
|
|
|
276
279
|
inEditMode: false,
|
|
277
280
|
initialFormValues: { identifiers: { openmrsID } } as unknown as FormValues,
|
|
278
281
|
isOffline: false,
|
|
279
|
-
setCapturePhotoProps:
|
|
280
|
-
setFieldValue:
|
|
281
|
-
setInitialFormValues:
|
|
282
|
+
setCapturePhotoProps: vi.fn(),
|
|
283
|
+
setFieldValue: vi.fn(),
|
|
284
|
+
setInitialFormValues: vi.fn(),
|
|
282
285
|
validationSchema: null,
|
|
283
286
|
values: { identifiers: { openmrsID } } as unknown as FormValues,
|
|
284
|
-
setFieldTouched:
|
|
287
|
+
setFieldTouched: vi.fn(),
|
|
285
288
|
};
|
|
286
289
|
|
|
287
290
|
renderWithContext(
|
|
288
|
-
<Formik initialValues={{}} onSubmit={
|
|
291
|
+
<Formik initialValues={{}} onSubmit={vi.fn()}>
|
|
289
292
|
<Form>
|
|
290
293
|
<PatientRegistrationContextProvider value={updatedContextValues}>
|
|
291
294
|
<Field name="id" />
|
|
@@ -299,7 +302,7 @@ describe('Field', () => {
|
|
|
299
302
|
});
|
|
300
303
|
|
|
301
304
|
it('should return null and report an error for an invalid field name', () => {
|
|
302
|
-
const consoleError =
|
|
305
|
+
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
303
306
|
|
|
304
307
|
mockUseConfig.mockReturnValue({
|
|
305
308
|
...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
|
|
@@ -310,7 +313,7 @@ describe('Field', () => {
|
|
|
310
313
|
|
|
311
314
|
try {
|
|
312
315
|
renderWithContext(
|
|
313
|
-
<Formik initialValues={{}} onSubmit={
|
|
316
|
+
<Formik initialValues={{}} onSubmit={vi.fn()}>
|
|
314
317
|
<Form>
|
|
315
318
|
<Field name="invalidField" />
|
|
316
319
|
</Form>
|
|
@@ -1,40 +1,107 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
2
3
|
import userEvent from '@testing-library/user-event';
|
|
3
4
|
import { Formik, Form } from 'formik';
|
|
4
|
-
import { screen } from '@testing-library/react';
|
|
5
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
5
6
|
import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
type PatientRegistrationContextProps,
|
|
11
|
-
PatientRegistrationContextProvider,
|
|
12
|
-
} from '../../patient-registration-context';
|
|
7
|
+
import { PatientRegistrationContextProvider } from '../../patient-registration-context';
|
|
8
|
+
import { initialFormValues } from '../../patient-registration.component';
|
|
9
|
+
import { getValidationSchema } from '../../validation/patient-registration-validation';
|
|
13
10
|
import { GenderField } from './gender-field.component';
|
|
11
|
+
import { type FormValues } from '../../patient-registration.types';
|
|
12
|
+
import { type RegistrationConfig, esmPatientRegistrationSchema } from '../../../config-schema';
|
|
13
|
+
|
|
14
|
+
const mockUseConfig = vi.mocked(useConfig<RegistrationConfig>);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Helper to render GenderField with Formik render props for state-dependent tests.
|
|
18
|
+
* Returns the render result and a ref to access form values.
|
|
19
|
+
*/
|
|
20
|
+
const renderGenderFieldWithFormik = (
|
|
21
|
+
initialValues: Partial<FormValues> = {},
|
|
22
|
+
options?: { enableReinitialize?: boolean; withValidation?: boolean },
|
|
23
|
+
) => {
|
|
24
|
+
const defaultValues = {
|
|
25
|
+
gender: '',
|
|
26
|
+
...initialValues,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
let formValuesRef: FormValues = { ...initialFormValues, ...defaultValues } as FormValues;
|
|
30
|
+
const config = mockUseConfig();
|
|
31
|
+
const validationSchema = options?.withValidation
|
|
32
|
+
? getValidationSchema(config, (key: string, defaultValue: string) => defaultValue)
|
|
33
|
+
: null;
|
|
14
34
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
const utils = render(
|
|
36
|
+
<Formik
|
|
37
|
+
initialValues={defaultValues}
|
|
38
|
+
onSubmit={() => {}}
|
|
39
|
+
enableReinitialize={options?.enableReinitialize}
|
|
40
|
+
validationSchema={validationSchema || undefined}
|
|
41
|
+
validateOnChange={true}
|
|
42
|
+
validateOnBlur={true}>
|
|
43
|
+
{({ setFieldValue, values, setFieldTouched, errors, touched }) => {
|
|
44
|
+
formValuesRef = { ...initialFormValues, ...values } as FormValues;
|
|
45
|
+
return (
|
|
46
|
+
<Form>
|
|
47
|
+
<PatientRegistrationContextProvider
|
|
48
|
+
value={{
|
|
49
|
+
identifierTypes: [],
|
|
50
|
+
values: formValuesRef,
|
|
51
|
+
validationSchema: validationSchema,
|
|
52
|
+
inEditMode: false,
|
|
53
|
+
setFieldValue: setFieldValue as any,
|
|
54
|
+
setCapturePhotoProps: vi.fn(),
|
|
55
|
+
setFieldTouched: setFieldTouched as any,
|
|
56
|
+
currentPhoto: '',
|
|
57
|
+
isOffline: false,
|
|
58
|
+
initialFormValues: formValuesRef,
|
|
59
|
+
}}>
|
|
60
|
+
<GenderField />
|
|
61
|
+
</PatientRegistrationContextProvider>
|
|
62
|
+
</Form>
|
|
63
|
+
);
|
|
64
|
+
}}
|
|
65
|
+
</Formik>,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
...utils,
|
|
70
|
+
getFormValues: () => formValuesRef,
|
|
71
|
+
};
|
|
32
72
|
};
|
|
33
73
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
})
|
|
74
|
+
/**
|
|
75
|
+
* Helper to render GenderField with mocked Formik functions (for simple rendering tests).
|
|
76
|
+
*/
|
|
77
|
+
const renderGenderField = (initialValues: Partial<FormValues> = {}) => {
|
|
78
|
+
const defaultValues = {
|
|
79
|
+
gender: '',
|
|
80
|
+
...initialValues,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return render(
|
|
84
|
+
<Formik initialValues={defaultValues} onSubmit={() => {}}>
|
|
85
|
+
<Form>
|
|
86
|
+
<PatientRegistrationContextProvider
|
|
87
|
+
value={{
|
|
88
|
+
identifierTypes: [],
|
|
89
|
+
values: { ...initialFormValues, ...defaultValues } as FormValues,
|
|
90
|
+
validationSchema: null,
|
|
91
|
+
inEditMode: false,
|
|
92
|
+
setFieldValue: vi.fn().mockResolvedValue(undefined),
|
|
93
|
+
setCapturePhotoProps: vi.fn(),
|
|
94
|
+
setFieldTouched: vi.fn().mockResolvedValue(undefined),
|
|
95
|
+
currentPhoto: '',
|
|
96
|
+
isOffline: false,
|
|
97
|
+
initialFormValues: { ...initialFormValues, ...defaultValues } as FormValues,
|
|
98
|
+
}}>
|
|
99
|
+
<GenderField />
|
|
100
|
+
</PatientRegistrationContextProvider>
|
|
101
|
+
</Form>
|
|
102
|
+
</Formik>,
|
|
103
|
+
);
|
|
104
|
+
};
|
|
38
105
|
|
|
39
106
|
describe('GenderField', () => {
|
|
40
107
|
beforeEach(() => {
|
|
@@ -50,6 +117,14 @@ describe('GenderField', () => {
|
|
|
50
117
|
value: 'female',
|
|
51
118
|
label: 'Female',
|
|
52
119
|
},
|
|
120
|
+
{
|
|
121
|
+
value: 'other',
|
|
122
|
+
label: 'Other',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
value: 'unknown',
|
|
126
|
+
label: 'Unknown',
|
|
127
|
+
},
|
|
53
128
|
],
|
|
54
129
|
name: {
|
|
55
130
|
displayMiddleName: false,
|
|
@@ -63,37 +138,148 @@ describe('GenderField', () => {
|
|
|
63
138
|
});
|
|
64
139
|
});
|
|
65
140
|
|
|
66
|
-
it('
|
|
67
|
-
|
|
68
|
-
<Formik initialValues={{}} onSubmit={null}>
|
|
69
|
-
<Form>
|
|
70
|
-
<GenderField />
|
|
71
|
-
</Form>
|
|
72
|
-
</Formik>,
|
|
73
|
-
PatientRegistrationContextProvider,
|
|
74
|
-
mockContextValues,
|
|
75
|
-
);
|
|
141
|
+
it('renders the gender field with all options', () => {
|
|
142
|
+
renderGenderField();
|
|
76
143
|
|
|
77
144
|
expect(screen.getByRole('heading', { name: /sex/i })).toBeInTheDocument();
|
|
78
145
|
expect(screen.getByLabelText(/^male/i)).toBeInTheDocument();
|
|
79
146
|
expect(screen.getByLabelText(/female/i)).toBeInTheDocument();
|
|
147
|
+
expect(screen.getByLabelText(/other/i)).toBeInTheDocument();
|
|
148
|
+
expect(screen.getByLabelText(/unknown/i)).toBeInTheDocument();
|
|
80
149
|
});
|
|
81
150
|
|
|
82
|
-
|
|
83
|
-
|
|
151
|
+
describe('Gender selection', () => {
|
|
152
|
+
it('updates form value when user selects female', async () => {
|
|
153
|
+
const user = userEvent.setup();
|
|
154
|
+
const { getFormValues } = renderGenderFieldWithFormik({ gender: 'male' });
|
|
84
155
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
156
|
+
await user.click(screen.getByText(/female/i));
|
|
157
|
+
|
|
158
|
+
await waitFor(() => {
|
|
159
|
+
expect(screen.getByLabelText(/female/i)).toBeChecked();
|
|
160
|
+
});
|
|
161
|
+
expect(screen.getByLabelText(/^male/i)).not.toBeChecked();
|
|
162
|
+
expect(getFormValues().gender).toBe('female');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('updates form value when user selects male', async () => {
|
|
166
|
+
const user = userEvent.setup();
|
|
167
|
+
const { getFormValues } = renderGenderFieldWithFormik({ gender: 'female' });
|
|
168
|
+
|
|
169
|
+
await user.click(screen.getByText(/^male/i));
|
|
170
|
+
|
|
171
|
+
await waitFor(() => {
|
|
172
|
+
expect(screen.getByLabelText(/^male/i)).toBeChecked();
|
|
173
|
+
});
|
|
174
|
+
expect(screen.getByLabelText(/female/i)).not.toBeChecked();
|
|
175
|
+
expect(getFormValues().gender).toBe('male');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('updates form value when user selects other', async () => {
|
|
179
|
+
const user = userEvent.setup();
|
|
180
|
+
const { getFormValues } = renderGenderFieldWithFormik();
|
|
181
|
+
|
|
182
|
+
await user.click(screen.getByText(/other/i));
|
|
183
|
+
|
|
184
|
+
await waitFor(() => {
|
|
185
|
+
expect(screen.getByLabelText(/other/i)).toBeChecked();
|
|
186
|
+
});
|
|
187
|
+
expect(getFormValues().gender).toBe('other');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('updates form value when user selects unknown', async () => {
|
|
191
|
+
const user = userEvent.setup();
|
|
192
|
+
const { getFormValues } = renderGenderFieldWithFormik({ gender: 'male' });
|
|
193
|
+
|
|
194
|
+
await user.click(screen.getByText(/unknown/i));
|
|
195
|
+
|
|
196
|
+
await waitFor(() => {
|
|
197
|
+
expect(screen.getByLabelText(/unknown/i)).toBeChecked();
|
|
198
|
+
});
|
|
199
|
+
expect(screen.getByLabelText(/^male/i)).not.toBeChecked();
|
|
200
|
+
expect(getFormValues().gender).toBe('unknown');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('displays the initial gender value correctly', () => {
|
|
204
|
+
renderGenderFieldWithFormik({ gender: 'female' });
|
|
205
|
+
|
|
206
|
+
expect(screen.getByLabelText(/female/i)).toBeChecked();
|
|
207
|
+
expect(screen.getByLabelText(/^male/i)).not.toBeChecked();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('allows switching between all gender options', async () => {
|
|
211
|
+
const user = userEvent.setup();
|
|
212
|
+
const { getFormValues } = renderGenderFieldWithFormik();
|
|
213
|
+
|
|
214
|
+
// Select male
|
|
215
|
+
await user.click(screen.getByText(/^male/i));
|
|
216
|
+
await waitFor(() => {
|
|
217
|
+
expect(getFormValues().gender).toBe('male');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Switch to female
|
|
221
|
+
await user.click(screen.getByText(/female/i));
|
|
222
|
+
await waitFor(() => {
|
|
223
|
+
expect(getFormValues().gender).toBe('female');
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Switch to other
|
|
227
|
+
await user.click(screen.getByText(/other/i));
|
|
228
|
+
await waitFor(() => {
|
|
229
|
+
expect(getFormValues().gender).toBe('other');
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Switch to unknown
|
|
233
|
+
await user.click(screen.getByText(/unknown/i));
|
|
234
|
+
await waitFor(() => {
|
|
235
|
+
expect(getFormValues().gender).toBe('unknown');
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('Validation error display', () => {
|
|
241
|
+
it('does not show error when field is not touched', () => {
|
|
242
|
+
renderGenderFieldWithFormik({ gender: '' }, { withValidation: true });
|
|
243
|
+
|
|
244
|
+
expect(screen.queryByText(/gender is required/i)).not.toBeInTheDocument();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('shows error message when user selects a gender and then form is validated', async () => {
|
|
248
|
+
const user = userEvent.setup();
|
|
249
|
+
const { getFormValues } = renderGenderFieldWithFormik({ gender: '' }, { withValidation: true });
|
|
250
|
+
|
|
251
|
+
// Initially no error (field not touched)
|
|
252
|
+
expect(screen.queryByText(/gender is required/i)).not.toBeInTheDocument();
|
|
253
|
+
|
|
254
|
+
// User selects a valid gender - this marks field as touched
|
|
255
|
+
await user.click(screen.getByText(/^male/i));
|
|
256
|
+
|
|
257
|
+
await waitFor(() => {
|
|
258
|
+
expect(getFormValues().gender).toBe('male');
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// After valid selection, no error should appear (user-visible)
|
|
262
|
+
expect(screen.queryByText(/gender is required/i)).not.toBeInTheDocument();
|
|
263
|
+
expect(screen.getByLabelText(/^male/i)).toBeChecked();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('clears error message when valid gender is selected', async () => {
|
|
267
|
+
const user = userEvent.setup();
|
|
268
|
+
renderGenderFieldWithFormik({ gender: '' }, { withValidation: true });
|
|
269
|
+
|
|
270
|
+
// Initially no error (field not touched)
|
|
271
|
+
expect(screen.queryByText(/gender is required/i)).not.toBeInTheDocument();
|
|
272
|
+
|
|
273
|
+
// Select a valid gender option - this will mark field as touched
|
|
274
|
+
await user.click(screen.getByText(/^male/i));
|
|
275
|
+
|
|
276
|
+
// Wait for selection to be applied (user-visible)
|
|
277
|
+
await waitFor(() => {
|
|
278
|
+
expect(screen.getByLabelText(/^male/i)).toBeChecked();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Error should not appear after valid selection (user-visible)
|
|
282
|
+
expect(screen.queryByText(/gender is required/i)).not.toBeInTheDocument();
|
|
283
|
+
});
|
|
98
284
|
});
|
|
99
285
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { SkeletonText } from '@carbon/react';
|
|
4
|
-
import {
|
|
3
|
+
import { Button, SkeletonText } from '@carbon/react';
|
|
4
|
+
import { ArrowRight } from '@carbon/react/icons';
|
|
5
|
+
import { useLayoutType, useConfig, isDesktop, UserHasAccess } from '@openmrs/esm-framework';
|
|
5
6
|
import { usePatientRegistrationContext } from '../../patient-registration-context';
|
|
6
7
|
import { useResourcesContext } from '../../../resources-context';
|
|
7
8
|
import type {
|
|
@@ -11,6 +12,7 @@ import type {
|
|
|
11
12
|
PatientIdentifierValue,
|
|
12
13
|
} from '../../patient-registration.types';
|
|
13
14
|
import IdentifierInput from '../../input/custom-input/identifier/identifier-input.component';
|
|
15
|
+
import IdentifierSelectionOverlay from './identifier-selection-overlay.component';
|
|
14
16
|
import styles from '../field.scss';
|
|
15
17
|
|
|
16
18
|
export function setIdentifierSource(
|
|
@@ -43,7 +45,8 @@ export function initializeIdentifier(
|
|
|
43
45
|
): PatientIdentifierValue {
|
|
44
46
|
// Check if there's an override for this identifier type
|
|
45
47
|
const override = identifierTypeOverrides?.find((override) => override.identifierTypeUuid === identifierType.uuid);
|
|
46
|
-
const isRequired =
|
|
48
|
+
const isRequired =
|
|
49
|
+
override?.required !== undefined ? override.required : identifierType.isPrimary || identifierType.required;
|
|
47
50
|
|
|
48
51
|
return {
|
|
49
52
|
identifierTypeUuid: identifierType.uuid,
|
|
@@ -105,7 +108,14 @@ export const Identifiers: React.FC = () => {
|
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
108
|
-
}, [
|
|
111
|
+
}, [
|
|
112
|
+
identifierTypes,
|
|
113
|
+
setFieldValue,
|
|
114
|
+
defaultPatientIdentifierTypes,
|
|
115
|
+
identifierTypeOverrides,
|
|
116
|
+
values.identifiers,
|
|
117
|
+
initializeIdentifier,
|
|
118
|
+
]);
|
|
109
119
|
|
|
110
120
|
if (isLoading && !isOffline) {
|
|
111
121
|
return (
|