@ampath/esm-patient-registration-app 6.0.1-pre.6

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.
Files changed (176) hide show
  1. package/.turbo/turbo-build.log +41 -0
  2. package/README.md +7 -0
  3. package/dist/130.js +2 -0
  4. package/dist/130.js.LICENSE.txt +3 -0
  5. package/dist/130.js.map +1 -0
  6. package/dist/152.js +1 -0
  7. package/dist/152.js.map +1 -0
  8. package/dist/249.js +2 -0
  9. package/dist/249.js.LICENSE.txt +46 -0
  10. package/dist/249.js.map +1 -0
  11. package/dist/255.js +2 -0
  12. package/dist/255.js.LICENSE.txt +9 -0
  13. package/dist/255.js.map +1 -0
  14. package/dist/271.js +1 -0
  15. package/dist/303.js +1 -0
  16. package/dist/303.js.map +1 -0
  17. package/dist/319.js +1 -0
  18. package/dist/365.js +1 -0
  19. package/dist/365.js.map +1 -0
  20. package/dist/460.js +1 -0
  21. package/dist/525.js +1 -0
  22. package/dist/525.js.map +1 -0
  23. package/dist/537.js +1 -0
  24. package/dist/537.js.map +1 -0
  25. package/dist/574.js +1 -0
  26. package/dist/591.js +2 -0
  27. package/dist/591.js.LICENSE.txt +32 -0
  28. package/dist/591.js.map +1 -0
  29. package/dist/621.js +1 -0
  30. package/dist/621.js.map +1 -0
  31. package/dist/644.js +1 -0
  32. package/dist/729.js +1 -0
  33. package/dist/729.js.map +1 -0
  34. package/dist/735.js +1 -0
  35. package/dist/735.js.map +1 -0
  36. package/dist/757.js +1 -0
  37. package/dist/784.js +2 -0
  38. package/dist/784.js.LICENSE.txt +9 -0
  39. package/dist/784.js.map +1 -0
  40. package/dist/788.js +1 -0
  41. package/dist/807.js +1 -0
  42. package/dist/833.js +1 -0
  43. package/dist/879.js +1 -0
  44. package/dist/879.js.map +1 -0
  45. package/dist/ampath-esm-patient-registration-app.js +1 -0
  46. package/dist/ampath-esm-patient-registration-app.js.buildmanifest.json +649 -0
  47. package/dist/ampath-esm-patient-registration-app.js.map +1 -0
  48. package/dist/main.js +2 -0
  49. package/dist/main.js.LICENSE.txt +56 -0
  50. package/dist/main.js.map +1 -0
  51. package/dist/routes.json +1 -0
  52. package/docs/images/patient-registration-hierarchy.png +0 -0
  53. package/jest.config.js +3 -0
  54. package/package.json +61 -0
  55. package/src/add-patient-link.scss +3 -0
  56. package/src/add-patient-link.test.tsx +20 -0
  57. package/src/add-patient-link.tsx +21 -0
  58. package/src/config-schema.ts +410 -0
  59. package/src/constants.ts +14 -0
  60. package/src/declarations.d.ts +6 -0
  61. package/src/index.ts +71 -0
  62. package/src/nav-link.test.tsx +13 -0
  63. package/src/nav-link.tsx +10 -0
  64. package/src/offline.resources.ts +155 -0
  65. package/src/offline.ts +91 -0
  66. package/src/patient-registration/before-save-prompt.tsx +73 -0
  67. package/src/patient-registration/date-util.ts +52 -0
  68. package/src/patient-registration/field/__mocks__/field.resource.ts +60 -0
  69. package/src/patient-registration/field/address/address-field.component.tsx +153 -0
  70. package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +73 -0
  71. package/src/patient-registration/field/address/address-hierarchy.resource.tsx +157 -0
  72. package/src/patient-registration/field/address/address-search.component.tsx +85 -0
  73. package/src/patient-registration/field/address/address-search.scss +53 -0
  74. package/src/patient-registration/field/address/custom-address-field.component.tsx +31 -0
  75. package/src/patient-registration/field/address/tests/address-hierarchy.test.tsx +214 -0
  76. package/src/patient-registration/field/address/tests/address-search-component.test.tsx +135 -0
  77. package/src/patient-registration/field/custom-field.component.tsx +25 -0
  78. package/src/patient-registration/field/dob/dob.component.tsx +159 -0
  79. package/src/patient-registration/field/dob/dob.test.tsx +75 -0
  80. package/src/patient-registration/field/field.component.tsx +47 -0
  81. package/src/patient-registration/field/field.resource.ts +35 -0
  82. package/src/patient-registration/field/field.scss +127 -0
  83. package/src/patient-registration/field/field.test.tsx +294 -0
  84. package/src/patient-registration/field/gender/gender-field.component.tsx +49 -0
  85. package/src/patient-registration/field/gender/gender-field.test.tsx +59 -0
  86. package/src/patient-registration/field/id/id-field.component.tsx +144 -0
  87. package/src/patient-registration/field/id/id-field.test.tsx +107 -0
  88. package/src/patient-registration/field/id/identifier-selection-overlay.component.tsx +198 -0
  89. package/src/patient-registration/field/id/identifier-selection.scss +37 -0
  90. package/src/patient-registration/field/name/name-field.component.tsx +142 -0
  91. package/src/patient-registration/field/obs/obs-field.component.tsx +204 -0
  92. package/src/patient-registration/field/obs/obs-field.test.tsx +205 -0
  93. package/src/patient-registration/field/person-attributes/coded-attributes.component.tsx +60 -0
  94. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +116 -0
  95. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +127 -0
  96. package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +88 -0
  97. package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +187 -0
  98. package/src/patient-registration/field/person-attributes/person-attributes.resource.ts +20 -0
  99. package/src/patient-registration/field/person-attributes/text-person-attribute-field.component.tsx +58 -0
  100. package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +88 -0
  101. package/src/patient-registration/field/phone/phone-field.component.tsx +16 -0
  102. package/src/patient-registration/form-manager.test.ts +67 -0
  103. package/src/patient-registration/form-manager.ts +414 -0
  104. package/src/patient-registration/input/basic-input/input/input.component.tsx +179 -0
  105. package/src/patient-registration/input/basic-input/input/input.test.tsx +72 -0
  106. package/src/patient-registration/input/basic-input/select/select-input.component.tsx +32 -0
  107. package/src/patient-registration/input/basic-input/select/select-input.test.tsx +49 -0
  108. package/src/patient-registration/input/combo-input/combo-input.component.tsx +128 -0
  109. package/src/patient-registration/input/combo-input/selection-tick.component.tsx +20 -0
  110. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.component.tsx +187 -0
  111. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.scss +62 -0
  112. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +132 -0
  113. package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +156 -0
  114. package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +107 -0
  115. package/src/patient-registration/input/custom-input/identifier/utils.test.ts +81 -0
  116. package/src/patient-registration/input/custom-input/identifier/utils.ts +19 -0
  117. package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +53 -0
  118. package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +43 -0
  119. package/src/patient-registration/input/input.scss +118 -0
  120. package/src/patient-registration/patient-registration-context.ts +24 -0
  121. package/src/patient-registration/patient-registration-hooks.ts +287 -0
  122. package/src/patient-registration/patient-registration-utils.ts +216 -0
  123. package/src/patient-registration/patient-registration.component.tsx +240 -0
  124. package/src/patient-registration/patient-registration.resource.test.tsx +26 -0
  125. package/src/patient-registration/patient-registration.resource.ts +250 -0
  126. package/src/patient-registration/patient-registration.scss +122 -0
  127. package/src/patient-registration/patient-registration.test.tsx +471 -0
  128. package/src/patient-registration/patient-registration.types.ts +318 -0
  129. package/src/patient-registration/section/death-info/death-info-section.component.tsx +31 -0
  130. package/src/patient-registration/section/death-info/death-info-section.test.tsx +64 -0
  131. package/src/patient-registration/section/demographics/demographics-section.component.tsx +30 -0
  132. package/src/patient-registration/section/demographics/demographics-section.test.tsx +83 -0
  133. package/src/patient-registration/section/generic-section.component.tsx +17 -0
  134. package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +235 -0
  135. package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +100 -0
  136. package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +78 -0
  137. package/src/patient-registration/section/patient-relationships/relationships.scss +35 -0
  138. package/src/patient-registration/section/section-wrapper.component.tsx +40 -0
  139. package/src/patient-registration/section/section.component.tsx +23 -0
  140. package/src/patient-registration/section/section.scss +1 -0
  141. package/src/patient-registration/ui-components/overlay/overlay.component.tsx +51 -0
  142. package/src/patient-registration/ui-components/overlay/overlay.scss +63 -0
  143. package/src/patient-registration/validation/patient-registration-validation.test.tsx +157 -0
  144. package/src/patient-registration/validation/patient-registration-validation.tsx +60 -0
  145. package/src/patient-verification/client-registry-constants.ts +13 -0
  146. package/src/patient-verification/client-registry.component.tsx +66 -0
  147. package/src/patient-verification/client-registry.scss +1 -0
  148. package/src/patient-verification/utils.tsx +56 -0
  149. package/src/patient-verification/verification-modal.scss +20 -0
  150. package/src/patient-verification/verification.component.tsx +48 -0
  151. package/src/resource.ts +12 -0
  152. package/src/root.component.tsx +63 -0
  153. package/src/root.scss +7 -0
  154. package/src/root.test.tsx +32 -0
  155. package/src/routes.json +66 -0
  156. package/src/widgets/cancel-patient-edit.component.tsx +37 -0
  157. package/src/widgets/cancel-patient-edit.test.tsx +27 -0
  158. package/src/widgets/delete-identifier-confirmation-modal.test.tsx +34 -0
  159. package/src/widgets/delete-identifier-confirmation-modal.tsx +41 -0
  160. package/src/widgets/delete-identifier-modal.scss +34 -0
  161. package/src/widgets/display-photo.component.tsx +30 -0
  162. package/src/widgets/display-photo.test.tsx +37 -0
  163. package/src/widgets/edit-patient-details-button.component.tsx +34 -0
  164. package/src/widgets/edit-patient-details-button.scss +3 -0
  165. package/src/widgets/edit-patient-details-button.test.tsx +41 -0
  166. package/translations/am.json +97 -0
  167. package/translations/ar.json +97 -0
  168. package/translations/en.json +103 -0
  169. package/translations/es.json +97 -0
  170. package/translations/fr.json +97 -0
  171. package/translations/he.json +97 -0
  172. package/translations/km.json +97 -0
  173. package/translations/zh.json +89 -0
  174. package/translations/zh_CN.json +89 -0
  175. package/tsconfig.json +5 -0
  176. package/webpack.config.js +1 -0
@@ -0,0 +1,187 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { usePersonAttributeType } from './person-attributes.resource';
4
+ import { PersonAttributeField } from './person-attribute-field.component';
5
+ import { useConceptAnswers } from '../field.resource';
6
+ import { Form, Formik } from 'formik';
7
+ import { type FieldDefinition } from '../../../config-schema';
8
+
9
+ jest.mock('./person-attributes.resource'); // Mock the usePersonAttributeType hook
10
+ jest.mock('../field.resource'); // Mock the useConceptAnswers hook
11
+
12
+ jest.mock('formik', () => ({
13
+ ...jest.requireActual('formik'),
14
+ }));
15
+
16
+ const mockedUsePersonAttributeType = usePersonAttributeType as jest.Mock;
17
+ const mockedUseConceptAnswers = useConceptAnswers as jest.Mock;
18
+
19
+ let fieldDefinition: FieldDefinition;
20
+
21
+ describe('PersonAttributeField', () => {
22
+ let mockPersonAttributeType = {
23
+ format: 'java.lang.String',
24
+ display: 'Referred by',
25
+ uuid: '4dd56a75-14ab-4148-8700-1f4f704dc5b0',
26
+ };
27
+
28
+ beforeEach(() => {
29
+ fieldDefinition = {
30
+ id: 'referredby',
31
+ name: 'Referred by',
32
+ type: 'person attribute',
33
+ uuid: '4dd56a75-14ab-4148-8700-1f4f704dc5b0',
34
+ answerConceptSetUuid: '6682d17f-0777-45e4-a39b-93f77eb3531c',
35
+ validation: {
36
+ matches: '',
37
+ required: true,
38
+ },
39
+ showHeading: true,
40
+ };
41
+ mockedUsePersonAttributeType.mockReturnValue({
42
+ data: mockPersonAttributeType,
43
+ isLoading: false,
44
+ error: null,
45
+ uuid: '14d4f066-15f5-102d-96e4-000c29c2a5d7d',
46
+ });
47
+ });
48
+
49
+ afterEach(() => {
50
+ jest.resetAllMocks();
51
+ });
52
+
53
+ it('renders the text input field for String format', () => {
54
+ render(
55
+ <Formik initialValues={{}} onSubmit={() => {}}>
56
+ <Form>
57
+ <PersonAttributeField fieldDefinition={fieldDefinition} />
58
+ </Form>
59
+ </Formik>,
60
+ );
61
+
62
+ const input = screen.getByLabelText(/Referred by/i) as HTMLInputElement;
63
+ expect(screen.getByRole('heading')).toBeInTheDocument();
64
+ expect(input).toBeInTheDocument();
65
+ expect(input.type).toBe('text');
66
+ });
67
+
68
+ it('should not show heading if showHeading is false', () => {
69
+ fieldDefinition = {
70
+ ...fieldDefinition,
71
+ showHeading: false,
72
+ };
73
+
74
+ render(
75
+ <Formik initialValues={{}} onSubmit={() => {}}>
76
+ <Form>
77
+ <PersonAttributeField fieldDefinition={fieldDefinition} />
78
+ </Form>
79
+ </Formik>,
80
+ );
81
+ expect(screen.queryByRole('heading')).not.toBeInTheDocument();
82
+ });
83
+
84
+ it('renders the coded attribute field for Concept format', () => {
85
+ mockedUsePersonAttributeType.mockReturnValue({
86
+ data: { ...mockPersonAttributeType, format: 'org.openmrs.Concept' },
87
+ isLoading: false,
88
+ error: null,
89
+ });
90
+
91
+ fieldDefinition = {
92
+ id: 'referredby',
93
+ ...fieldDefinition,
94
+ label: 'Referred by',
95
+ };
96
+
97
+ mockedUseConceptAnswers.mockReturnValueOnce({
98
+ data: [
99
+ { uuid: '1', display: 'Option 1' },
100
+ { uuid: '2', display: 'Option 2' },
101
+ ],
102
+ isLoading: false,
103
+ });
104
+
105
+ render(
106
+ <Formik initialValues={{}} onSubmit={() => {}}>
107
+ <Form>
108
+ <PersonAttributeField fieldDefinition={fieldDefinition} />
109
+ </Form>
110
+ </Formik>,
111
+ );
112
+
113
+ const input = screen.getByLabelText(/Referred by/i) as HTMLInputElement;
114
+ expect(input).toBeInTheDocument();
115
+ expect(input.type).toBe('select-one');
116
+ expect(screen.getByText('Option 1')).toBeInTheDocument();
117
+ expect(screen.getByText('Option 2')).toBeInTheDocument();
118
+ });
119
+
120
+ it('renders an error notification if attribute type has unknown format', () => {
121
+ mockedUsePersonAttributeType.mockReturnValue({
122
+ data: { ...mockPersonAttributeType, format: 'unknown' },
123
+ isLoading: false,
124
+ error: null,
125
+ });
126
+
127
+ render(
128
+ <Formik initialValues={{}} onSubmit={() => {}}>
129
+ <Form>
130
+ <PersonAttributeField fieldDefinition={fieldDefinition} />
131
+ </Form>
132
+ </Formik>,
133
+ );
134
+
135
+ expect(screen.getByText('Error')).toBeInTheDocument();
136
+ expect(screen.getByText(/Patient attribute type has unknown format/i)).toBeInTheDocument();
137
+ });
138
+ it('renders an error notification if unable to fetch attribute type', () => {
139
+ mockedUsePersonAttributeType.mockReturnValue({
140
+ data: null,
141
+ isLoading: false,
142
+ error: new Error('Failed to fetch attribute type'),
143
+ });
144
+
145
+ fieldDefinition = {
146
+ uuid: 'attribute-uuid',
147
+ label: 'Attribute',
148
+ showHeading: false,
149
+ };
150
+
151
+ render(
152
+ <Formik initialValues={{}} onSubmit={() => {}}>
153
+ <Form>
154
+ <PersonAttributeField fieldDefinition={fieldDefinition} />
155
+ </Form>
156
+ </Formik>,
157
+ );
158
+
159
+ expect(screen.getByText('Error')).toBeInTheDocument();
160
+ expect(screen.getByText(/Unable to fetch person attribute type/i)).toBeInTheDocument();
161
+ });
162
+
163
+ it('renders a skeleton if attribute type is loading', () => {
164
+ mockedUsePersonAttributeType.mockReturnValue({
165
+ data: null,
166
+ isLoading: true,
167
+ error: null,
168
+ });
169
+
170
+ fieldDefinition = {
171
+ uuid: 'attribute-uuid',
172
+ label: 'Attribute',
173
+ showHeading: true,
174
+ };
175
+
176
+ render(
177
+ <Formik initialValues={{}} onSubmit={() => {}}>
178
+ <Form>
179
+ <PersonAttributeField fieldDefinition={fieldDefinition} />
180
+ </Form>
181
+ </Formik>,
182
+ );
183
+ const input = screen.findByLabelText(/Reffered by/i);
184
+ expect(screen.getByText(/Attribute/i)).toBeInTheDocument();
185
+ expect(input).not.toBeNull(); // checks that the input is not rendered when the attribute type is loading
186
+ });
187
+ });
@@ -0,0 +1,20 @@
1
+ import { type FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
2
+ import useSWRImmutable from 'swr/immutable';
3
+ import { type PersonAttributeTypeResponse } from '../../patient-registration.types';
4
+
5
+ export function usePersonAttributeType(personAttributeTypeUuid: string): {
6
+ data: PersonAttributeTypeResponse;
7
+ isLoading: boolean;
8
+ error: any;
9
+ } {
10
+ const { data, error, isLoading } = useSWRImmutable<FetchResponse<PersonAttributeTypeResponse>>(
11
+ `/ws/rest/v1/personattributetype/${personAttributeTypeUuid}`,
12
+ openmrsFetch,
13
+ );
14
+
15
+ return {
16
+ data: data?.data,
17
+ isLoading,
18
+ error,
19
+ };
20
+ }
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import classNames from 'classnames';
3
+ import { Field } from 'formik';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { Input } from '../../input/basic-input/input/input.component';
6
+ import { type PersonAttributeTypeResponse } from '../../patient-registration.types';
7
+ import styles from './../field.scss';
8
+
9
+ export interface TextPersonAttributeFieldProps {
10
+ id: string;
11
+ personAttributeType: PersonAttributeTypeResponse;
12
+ validationRegex?: string;
13
+ label?: string;
14
+ required?: boolean;
15
+ }
16
+
17
+ export function TextPersonAttributeField({
18
+ id,
19
+ personAttributeType,
20
+ validationRegex,
21
+ label,
22
+ required,
23
+ }: TextPersonAttributeFieldProps) {
24
+ const { t } = useTranslation();
25
+
26
+ const validateInput = (value: string) => {
27
+ if (!value || !validationRegex || validationRegex === '' || typeof validationRegex !== 'string' || value === '') {
28
+ return;
29
+ }
30
+ const regex = new RegExp(validationRegex);
31
+ if (regex.test(value)) {
32
+ return;
33
+ } else {
34
+ return t('invalidInput', 'Invalid Input');
35
+ }
36
+ };
37
+
38
+ const fieldName = `attributes.${personAttributeType.uuid}`;
39
+
40
+ return (
41
+ <div className={classNames(styles.customField, styles.halfWidthInDesktopView)}>
42
+ <Field name={fieldName} validate={validateInput}>
43
+ {({ field, form: { touched, errors }, meta }) => {
44
+ return (
45
+ <Input
46
+ id={id}
47
+ name={`person-attribute-${personAttributeType.uuid}`}
48
+ labelText={label ?? personAttributeType?.display}
49
+ invalid={errors[fieldName] && touched[fieldName]}
50
+ {...field}
51
+ required={required}
52
+ />
53
+ );
54
+ }}
55
+ </Field>
56
+ </div>
57
+ );
58
+ }
@@ -0,0 +1,88 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { Form, Formik } from 'formik';
5
+ import { TextPersonAttributeField } from './text-person-attribute-field.component';
6
+
7
+ describe('TextPersonAttributeField', () => {
8
+ const mockPersonAttributeType = {
9
+ format: 'java.lang.String',
10
+ display: 'Referred by',
11
+ uuid: '4dd56a75-14ab-4148-8700-1f4f704dc5b0',
12
+ };
13
+
14
+ it('renders the input field with a label', () => {
15
+ render(
16
+ <Formik initialValues={{}} onSubmit={() => {}}>
17
+ <Form>
18
+ <TextPersonAttributeField
19
+ id="attributeId"
20
+ personAttributeType={mockPersonAttributeType}
21
+ label="Custom Label"
22
+ />
23
+ </Form>
24
+ </Formik>,
25
+ );
26
+
27
+ expect(screen.getByRole('textbox', { name: /custom label \(optional\)/i })).toBeInTheDocument();
28
+ });
29
+
30
+ it('renders the input field with the default label if label prop is not provided', () => {
31
+ render(
32
+ <Formik initialValues={{}} onSubmit={() => {}}>
33
+ <Form>
34
+ <TextPersonAttributeField id="attributeId" personAttributeType={mockPersonAttributeType} />
35
+ </Form>
36
+ </Formik>,
37
+ );
38
+
39
+ expect(screen.getByRole('textbox', { name: /referred by \(optional\)/i })).toBeInTheDocument();
40
+ });
41
+
42
+ it('validates the input with the provided validationRegex', async () => {
43
+ const user = userEvent.setup();
44
+ const validationRegex = '^[A-Z]+$'; // Accepts only uppercase letters
45
+
46
+ render(
47
+ <Formik initialValues={{}} onSubmit={() => {}}>
48
+ <Form>
49
+ <TextPersonAttributeField
50
+ id="attributeId"
51
+ personAttributeType={mockPersonAttributeType}
52
+ validationRegex={validationRegex}
53
+ />
54
+ </Form>
55
+ </Formik>,
56
+ );
57
+
58
+ const textbox = screen.getByRole('textbox', { name: /referred by \(optional\)/i });
59
+ expect(textbox).toBeInTheDocument();
60
+
61
+ // Valid input: "ABC"
62
+ await user.type(textbox, 'ABC');
63
+ await user.tab();
64
+
65
+ expect(screen.queryByText(/invalid input/i)).not.toBeInTheDocument();
66
+ await user.clear(textbox);
67
+
68
+ // // Invalid input: "abc" (contains lowercase letters)
69
+ await user.type(textbox, 'abc');
70
+ await user.tab();
71
+ expect(screen.getByText(/invalid input/i)).toBeInTheDocument();
72
+ });
73
+
74
+ it('renders the input field as required when required prop is true', () => {
75
+ render(
76
+ <Formik initialValues={{}} onSubmit={() => {}}>
77
+ <Form>
78
+ <TextPersonAttributeField id="attributeId" personAttributeType={mockPersonAttributeType} required />
79
+ </Form>
80
+ </Formik>,
81
+ );
82
+ const textbox = screen.getByRole('textbox', { name: /referred by/i });
83
+
84
+ // Required attribute should be truthy on the input element
85
+ expect(textbox).toBeInTheDocument();
86
+ expect(textbox).toBeRequired();
87
+ });
88
+ });
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { PersonAttributeField } from '../person-attributes/person-attribute-field.component';
3
+ import { useConfig } from '@openmrs/esm-framework';
4
+ import { type RegistrationConfig } from '../../../config-schema';
5
+
6
+ export function PhoneField() {
7
+ const config = useConfig<RegistrationConfig>();
8
+
9
+ const fieldDefinition = {
10
+ id: 'phone',
11
+ type: 'person attribute',
12
+ uuid: config.fieldConfigurations.phone.personAttributeUuid,
13
+ showHeading: false,
14
+ };
15
+ return <PersonAttributeField fieldDefinition={fieldDefinition} />;
16
+ }
@@ -0,0 +1,67 @@
1
+ import { FormManager } from './form-manager';
2
+ import { type FormValues } from './patient-registration.types';
3
+
4
+ jest.mock('./patient-registration.resource');
5
+
6
+ const formValues: FormValues = {
7
+ patientUuid: '',
8
+ givenName: '',
9
+ middleName: '',
10
+ familyName: '',
11
+ additionalGivenName: '',
12
+ additionalMiddleName: '',
13
+ additionalFamilyName: '',
14
+ addNameInLocalLanguage: false,
15
+ gender: '',
16
+ birthdate: '',
17
+ yearsEstimated: 1000,
18
+ monthsEstimated: 11,
19
+ birthdateEstimated: false,
20
+ telephoneNumber: '',
21
+ isDead: false,
22
+ deathDate: 'string',
23
+ deathCause: 'string',
24
+ relationships: [],
25
+ address: {
26
+ address1: '',
27
+ address2: '',
28
+ cityVillage: '',
29
+ stateProvince: 'New York',
30
+ country: 'string',
31
+ postalCode: 'string',
32
+ },
33
+ identifiers: {
34
+ foo: {
35
+ identifierUuid: 'aUuid',
36
+ identifierName: 'Foo',
37
+ required: false,
38
+ initialValue: 'foo',
39
+ identifierValue: 'foo',
40
+ identifierTypeUuid: 'identifierType',
41
+ preferred: true,
42
+ autoGeneration: false,
43
+ selectedSource: {
44
+ uuid: 'some-uuid',
45
+ name: 'unique',
46
+ autoGenerationOption: { manualEntryEnabled: true, automaticGenerationEnabled: false },
47
+ },
48
+ },
49
+ },
50
+ };
51
+
52
+ describe('FormManager', () => {
53
+ describe('createIdentifiers', () => {
54
+ it('uses the uuid of a field name if it exists', async () => {
55
+ const result = await FormManager.savePatientIdentifiers(true, undefined, formValues.identifiers, {}, 'Nyc');
56
+ expect(result).toEqual([
57
+ {
58
+ uuid: 'aUuid',
59
+ identifier: 'foo',
60
+ identifierType: 'identifierType',
61
+ location: 'Nyc',
62
+ preferred: true,
63
+ },
64
+ ]);
65
+ });
66
+ });
67
+ });