@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.
Files changed (346) hide show
  1. package/dist/1339.js +1 -0
  2. package/dist/1339.js.map +1 -0
  3. package/dist/1480.js +1 -0
  4. package/dist/1480.js.map +1 -0
  5. package/dist/1646.js +1 -0
  6. package/dist/1646.js.map +1 -0
  7. package/dist/1789.js +1 -0
  8. package/dist/1789.js.map +1 -0
  9. package/dist/1869.js +1 -0
  10. package/dist/1869.js.map +1 -0
  11. package/dist/1877.js +1 -0
  12. package/dist/1877.js.map +1 -0
  13. package/dist/2317.js +1 -0
  14. package/dist/2317.js.map +1 -0
  15. package/dist/2416.js +1 -0
  16. package/dist/2416.js.map +1 -0
  17. package/dist/2747.js +1 -0
  18. package/dist/2747.js.map +1 -0
  19. package/dist/282.js +1 -0
  20. package/dist/282.js.map +1 -0
  21. package/dist/2881.js +1 -0
  22. package/dist/2881.js.map +1 -0
  23. package/dist/3378.js +1 -0
  24. package/dist/3378.js.map +1 -0
  25. package/dist/3720.js +1 -0
  26. package/dist/3720.js.map +1 -0
  27. package/dist/3906.js +1 -0
  28. package/dist/3906.js.map +1 -0
  29. package/dist/3963.js +1 -0
  30. package/dist/3963.js.map +1 -0
  31. package/dist/3989.js +1 -0
  32. package/dist/3989.js.map +1 -0
  33. package/dist/4106.js +1 -0
  34. package/dist/4106.js.map +1 -0
  35. package/dist/4111.js +1 -0
  36. package/dist/4111.js.map +1 -0
  37. package/dist/434.js +1 -0
  38. package/dist/434.js.map +1 -0
  39. package/dist/4348.js +1 -0
  40. package/dist/4348.js.map +1 -0
  41. package/dist/4383.js +1 -0
  42. package/dist/4383.js.map +1 -0
  43. package/dist/4658.js +1 -0
  44. package/dist/4658.js.map +1 -0
  45. package/dist/466.js +1 -0
  46. package/dist/466.js.map +1 -0
  47. package/dist/4928.js +1 -0
  48. package/dist/4928.js.map +1 -0
  49. package/dist/5117.js +1 -0
  50. package/dist/5117.js.map +1 -0
  51. package/dist/5132.js +1 -0
  52. package/dist/5132.js.map +1 -0
  53. package/dist/5145.js +1 -0
  54. package/dist/5145.js.map +1 -0
  55. package/dist/5208.js +43 -0
  56. package/dist/5208.js.map +1 -0
  57. package/dist/527.js +1 -0
  58. package/dist/527.js.map +1 -0
  59. package/dist/5280.js +1 -0
  60. package/dist/5280.js.map +1 -0
  61. package/dist/5338.js +6 -0
  62. package/dist/5338.js.map +1 -0
  63. package/dist/5503.js +1 -0
  64. package/dist/5503.js.map +1 -0
  65. package/dist/555.js +1 -0
  66. package/dist/555.js.map +1 -0
  67. package/dist/556.js +1 -0
  68. package/dist/556.js.map +1 -0
  69. package/dist/5644.js +1 -0
  70. package/dist/5644.js.map +1 -0
  71. package/dist/5697.js +1 -0
  72. package/dist/{4024.js.map → 5697.js.map} +1 -1
  73. package/dist/5940.js +1 -0
  74. package/dist/5940.js.map +1 -0
  75. package/dist/6047.js +1 -0
  76. package/dist/6047.js.map +1 -0
  77. package/dist/6371.js +1 -0
  78. package/dist/6371.js.map +1 -0
  79. package/dist/6377.js +1 -0
  80. package/dist/6377.js.map +1 -0
  81. package/dist/6388.js +1 -0
  82. package/dist/6388.js.map +1 -0
  83. package/dist/6444.js +1 -0
  84. package/dist/6444.js.map +1 -0
  85. package/dist/6508.js +1 -0
  86. package/dist/6508.js.map +1 -0
  87. package/dist/6724.js +1 -0
  88. package/dist/6724.js.map +1 -0
  89. package/dist/689.js +1 -0
  90. package/dist/689.js.map +1 -0
  91. package/dist/6904.js +1 -0
  92. package/dist/6904.js.map +1 -0
  93. package/dist/7045.js +1 -0
  94. package/dist/7045.js.map +1 -0
  95. package/dist/7175.js +1 -0
  96. package/dist/7175.js.map +1 -0
  97. package/dist/7182.js +1 -0
  98. package/dist/7182.js.map +1 -0
  99. package/dist/7649.js +1 -0
  100. package/dist/7649.js.map +1 -0
  101. package/dist/7742.js +1 -0
  102. package/dist/7742.js.map +1 -0
  103. package/dist/7912.js +1 -0
  104. package/dist/7912.js.map +1 -0
  105. package/dist/8358.js +1 -0
  106. package/dist/8358.js.map +1 -0
  107. package/dist/8359.js +1 -0
  108. package/dist/8359.js.map +1 -0
  109. package/dist/8695.js +1 -0
  110. package/dist/8695.js.map +1 -0
  111. package/dist/903.js +1 -0
  112. package/dist/903.js.map +1 -0
  113. package/dist/9061.js +1 -0
  114. package/dist/9061.js.map +1 -0
  115. package/dist/9072.js +1 -0
  116. package/dist/9072.js.map +1 -0
  117. package/dist/9397.js +1 -0
  118. package/dist/9397.js.map +1 -0
  119. package/dist/9712.js +1 -0
  120. package/dist/9712.js.map +1 -0
  121. package/dist/9771.js +1 -0
  122. package/dist/9771.js.map +1 -0
  123. package/dist/9806.js +1 -0
  124. package/dist/9806.js.map +1 -0
  125. package/dist/9816.js +1 -0
  126. package/dist/9816.js.map +1 -0
  127. package/dist/main.js +7 -6
  128. package/dist/main.js.map +1 -1
  129. package/dist/openmrs-esm-patient-registration-app.js +6 -0
  130. package/dist/{olaboot-esm-patient-registration-app.js.buildmanifest.json → openmrs-esm-patient-registration-app.js.buildmanifest.json} +540 -455
  131. package/dist/openmrs-esm-patient-registration-app.js.map +1 -0
  132. package/dist/routes.json +1 -1
  133. package/package.json +8 -9
  134. package/src/add-patient-link.extension.tsx +3 -2
  135. package/src/add-patient-link.test.tsx +2 -1
  136. package/src/config-schema.ts +1 -1
  137. package/src/index.ts +2 -24
  138. package/src/nav-link.test.tsx +1 -0
  139. package/src/offline.resources.ts +97 -31
  140. package/src/patient-registration/before-save-prompt.test.tsx +199 -0
  141. package/src/patient-registration/field/__mocks__/field.resource.ts +8 -7
  142. package/src/patient-registration/field/address/address-field.component.tsx +10 -13
  143. package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +6 -1
  144. package/src/patient-registration/field/address/address-hierarchy.test.tsx +191 -198
  145. package/src/patient-registration/field/address/address-search.component.tsx +20 -8
  146. package/src/patient-registration/field/address/address-search.scss +19 -2
  147. package/src/patient-registration/field/address/address-search.test.tsx +249 -57
  148. package/src/patient-registration/field/address/custom-address-field.component.tsx +1 -1
  149. package/src/patient-registration/field/cause-of-death/cause-of-death.component.tsx +1 -1
  150. package/src/patient-registration/field/cause-of-death/cause-of-death.test.tsx +251 -0
  151. package/src/patient-registration/field/custom-field.component.tsx +1 -1
  152. package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +1 -1
  153. package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.test.tsx +144 -0
  154. package/src/patient-registration/field/dob/dob.component.tsx +2 -2
  155. package/src/patient-registration/field/dob/dob.test.tsx +370 -54
  156. package/src/patient-registration/field/field.component.tsx +1 -1
  157. package/src/patient-registration/field/field.resource.ts +2 -2
  158. package/src/patient-registration/field/field.test.tsx +25 -22
  159. package/src/patient-registration/field/gender/gender-field.test.tsx +240 -54
  160. package/src/patient-registration/field/id/id-field.component.tsx +15 -5
  161. package/src/patient-registration/field/id/id-field.test.tsx +103 -47
  162. package/src/patient-registration/field/id/identifier-selection-overlay.test.tsx +346 -0
  163. package/src/patient-registration/field/name/name-field.component.tsx +2 -2
  164. package/src/patient-registration/field/name/name-field.test.tsx +282 -0
  165. package/src/patient-registration/field/obs/obs-field.test.tsx +294 -118
  166. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +172 -108
  167. package/src/patient-registration/field/person-attributes/location-person-attribute-field.component.tsx +3 -3
  168. package/src/patient-registration/field/person-attributes/location-person-attribute-field.resource.tsx +2 -5
  169. package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +2 -2
  170. package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +249 -131
  171. package/src/patient-registration/field/person-attributes/person-attributes.resource.ts +1 -1
  172. package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +98 -70
  173. package/src/patient-registration/field/phone/phone-field.test.tsx +100 -0
  174. package/src/patient-registration/form-manager.test.ts +6 -5
  175. package/src/patient-registration/form-manager.ts +5 -2
  176. package/src/patient-registration/input/basic-input/input/input.component.tsx +3 -121
  177. package/src/patient-registration/input/basic-input/input/input.test.tsx +151 -51
  178. package/src/patient-registration/input/basic-input/select/select-input.test.tsx +113 -33
  179. package/src/patient-registration/input/combo-input/combo-input.component.tsx +60 -24
  180. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.component.tsx +10 -101
  181. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +144 -108
  182. package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +241 -177
  183. package/src/patient-registration/input/custom-input/identifier/utils.test.ts +47 -8
  184. package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +12 -12
  185. package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +52 -20
  186. package/src/patient-registration/input/input.scss +1 -2
  187. package/src/patient-registration/patient-registration-context.ts +5 -3
  188. package/src/patient-registration/patient-registration-hooks.ts +4 -12
  189. package/src/patient-registration/patient-registration-utils.test.ts +2 -1
  190. package/src/patient-registration/patient-registration-utils.ts +2 -98
  191. package/src/patient-registration/patient-registration.component.tsx +50 -46
  192. package/src/patient-registration/patient-registration.resource.test.tsx +4 -7
  193. package/src/patient-registration/patient-registration.resource.ts +1 -4
  194. package/src/patient-registration/patient-registration.scss +16 -3
  195. package/src/patient-registration/patient-registration.test.tsx +99 -65
  196. package/src/patient-registration/patient-registration.types.ts +17 -28
  197. package/src/patient-registration/section/death-info/death-info-section.test.tsx +130 -34
  198. package/src/patient-registration/section/demographics/demographics-section.test.tsx +122 -68
  199. package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +15 -15
  200. package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +278 -84
  201. package/src/patient-registration/section/section-wrapper.component.tsx +1 -1
  202. package/src/patient-registration/ui-components/overlay/overlay.test.tsx +104 -0
  203. package/src/patient-registration/validation/patient-registration-validation.test.ts +2 -1
  204. package/src/patient-registration/validation/patient-registration-validation.ts +9 -3
  205. package/src/root.component.tsx +2 -5
  206. package/src/widgets/cancel-patient-edit.test.tsx +48 -11
  207. package/src/widgets/delete-identifier-confirmation.test.tsx +77 -24
  208. package/src/widgets/edit-patient-details-button.component.tsx +14 -18
  209. package/src/widgets/edit-patient-details-button.scss +2 -2
  210. package/src/widgets/edit-patient-details-button.test.tsx +11 -13
  211. package/translations/am.json +9 -4
  212. package/translations/ar.json +9 -4
  213. package/translations/ar_SY.json +9 -4
  214. package/translations/bn.json +9 -4
  215. package/translations/cs.json +9 -4
  216. package/translations/de.json +120 -115
  217. package/translations/en.json +9 -4
  218. package/translations/en_US.json +9 -4
  219. package/translations/es.json +9 -4
  220. package/translations/es_MX.json +9 -4
  221. package/translations/fr.json +9 -4
  222. package/translations/he.json +9 -4
  223. package/translations/hi.json +9 -4
  224. package/translations/hi_IN.json +9 -4
  225. package/translations/id.json +9 -4
  226. package/translations/it.json +9 -4
  227. package/translations/ka.json +9 -4
  228. package/translations/km.json +9 -4
  229. package/translations/ku.json +9 -4
  230. package/translations/ky.json +9 -4
  231. package/translations/lg.json +9 -4
  232. package/translations/ne.json +9 -4
  233. package/translations/pl.json +9 -4
  234. package/translations/pt.json +9 -4
  235. package/translations/pt_BR.json +10 -5
  236. package/translations/qu.json +9 -4
  237. package/translations/ro_RO.json +9 -4
  238. package/translations/ru_RU.json +9 -4
  239. package/translations/si.json +9 -4
  240. package/translations/sq.json +9 -4
  241. package/translations/sw.json +9 -4
  242. package/translations/sw_KE.json +9 -4
  243. package/translations/tr.json +9 -4
  244. package/translations/tr_TR.json +9 -4
  245. package/translations/uk.json +9 -4
  246. package/translations/uz.json +9 -4
  247. package/translations/uz@Latn.json +9 -4
  248. package/translations/uz_UZ.json +9 -4
  249. package/translations/vi.json +9 -4
  250. package/translations/zh.json +50 -45
  251. package/translations/zh_CN.json +9 -4
  252. package/translations/zh_TW.json +9 -4
  253. package/vitest.config.ts +4 -0
  254. package/ADDRESS_CONFIGURATION.md +0 -152
  255. package/IDENTIFIER_CONFIGURATION.md +0 -142
  256. package/IMPLEMENTATION_SUMMARY.md +0 -111
  257. package/QUICK_START.md +0 -95
  258. package/address-required-fields-config.json +0 -26
  259. package/dist/126.js +0 -1
  260. package/dist/15.js +0 -1
  261. package/dist/1564.js +0 -1
  262. package/dist/1567.js +0 -1
  263. package/dist/1845.js +0 -1
  264. package/dist/1953.js +0 -1
  265. package/dist/200.js +0 -1
  266. package/dist/200.js.map +0 -1
  267. package/dist/215.js +0 -1
  268. package/dist/2178.js +0 -1
  269. package/dist/250.js +0 -1
  270. package/dist/250.js.map +0 -1
  271. package/dist/2523.js +0 -1
  272. package/dist/2523.js.map +0 -1
  273. package/dist/2566.js +0 -1
  274. package/dist/2586.js +0 -1
  275. package/dist/2586.js.map +0 -1
  276. package/dist/2716.js +0 -1
  277. package/dist/2716.js.map +0 -1
  278. package/dist/2759.js +0 -1
  279. package/dist/2821.js +0 -6
  280. package/dist/2821.js.map +0 -1
  281. package/dist/3089.js +0 -1
  282. package/dist/3089.js.map +0 -1
  283. package/dist/3230.js +0 -1
  284. package/dist/3441.js +0 -1
  285. package/dist/3565.js +0 -1
  286. package/dist/3571.js +0 -1
  287. package/dist/3571.js.map +0 -1
  288. package/dist/3746.js +0 -1
  289. package/dist/3925.js +0 -1
  290. package/dist/3946.js +0 -1
  291. package/dist/4024.js +0 -1
  292. package/dist/4744.js +0 -1
  293. package/dist/4744.js.map +0 -1
  294. package/dist/4809.js +0 -1
  295. package/dist/4894.js +0 -1
  296. package/dist/4970.js +0 -1
  297. package/dist/4970.js.map +0 -1
  298. package/dist/5130.js +0 -1
  299. package/dist/5187.js +0 -1
  300. package/dist/5491.js +0 -1
  301. package/dist/5491.js.map +0 -1
  302. package/dist/5595.js +0 -1
  303. package/dist/5961.js +0 -1
  304. package/dist/6133.js +0 -1
  305. package/dist/634.js +0 -1
  306. package/dist/634.js.map +0 -1
  307. package/dist/6456.js +0 -1
  308. package/dist/6466.js +0 -1
  309. package/dist/6613.js +0 -1
  310. package/dist/6783.js +0 -1
  311. package/dist/7073.js +0 -38
  312. package/dist/7073.js.map +0 -1
  313. package/dist/7154.js +0 -1
  314. package/dist/7154.js.map +0 -1
  315. package/dist/7348.js +0 -1
  316. package/dist/7439.js +0 -1
  317. package/dist/7439.js.map +0 -1
  318. package/dist/7543.js +0 -1
  319. package/dist/7607.js +0 -1
  320. package/dist/772.js +0 -1
  321. package/dist/7984.js +0 -1
  322. package/dist/7984.js.map +0 -1
  323. package/dist/8538.js +0 -1
  324. package/dist/8538.js.map +0 -1
  325. package/dist/8599.js +0 -1
  326. package/dist/8727.js +0 -1
  327. package/dist/8847.js +0 -1
  328. package/dist/9015.js +0 -1
  329. package/dist/906.js +0 -1
  330. package/dist/9065.js +0 -1
  331. package/dist/9182.js +0 -1
  332. package/dist/9339.js +0 -1
  333. package/dist/9453.js +0 -1
  334. package/dist/9833.js +0 -1
  335. package/dist/9833.js.map +0 -1
  336. package/dist/9856.js +0 -1
  337. package/dist/9856.js.map +0 -1
  338. package/dist/9920.js +0 -1
  339. package/dist/9938.js +0 -1
  340. package/dist/9943.js +0 -1
  341. package/dist/9943.js.map +0 -1
  342. package/dist/olaboot-esm-patient-registration-app.js +0 -5
  343. package/dist/olaboot-esm-patient-registration-app.js.map +0 -1
  344. package/example-config.json +0 -14
  345. package/jest.config.js +0 -3
  346. package/src/resource.ts +0 -12
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { vi, describe, it, expect, beforeEach } from 'vitest';
2
3
  import { screen } from '@testing-library/react';
3
4
  import { Formik, Form } from 'formik';
4
5
  import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
@@ -15,14 +16,14 @@ import { useOrderedAddressHierarchyLevels } from './address-hierarchy.resource';
15
16
  import { ResourcesContextProvider } from '../../../resources-context';
16
17
  import { AddressComponent } from './address-field.component';
17
18
 
18
- const mockUseConfig = jest.mocked(useConfig<RegistrationConfig>);
19
- const mockUseOrderedAddressHierarchyLevels = jest.mocked(useOrderedAddressHierarchyLevels);
19
+ const mockUseConfig = vi.mocked(useConfig<RegistrationConfig>);
20
+ const mockUseOrderedAddressHierarchyLevels = vi.mocked(useOrderedAddressHierarchyLevels);
20
21
 
21
22
  const mockResourcesContextValue = {
22
23
  addressTemplate: {} as AddressTemplate,
23
24
  currentSession: mockSession.data,
24
25
  identifierTypes: [],
25
- relationshipTypes: [],
26
+ relationshipTypes: { results: [] },
26
27
  } as Resources;
27
28
 
28
29
  const mockInitialFormValues = {
@@ -57,240 +58,232 @@ const initialContextValues: PatientRegistrationContextProps = {
57
58
  identifierTypes: [],
58
59
  initialFormValues: mockInitialFormValues,
59
60
  isOffline: false,
60
- setCapturePhotoProps: jest.fn(),
61
- setFieldValue: jest.fn(),
62
- setFieldTouched: jest.fn(),
63
- setInitialFormValues: jest.fn(),
61
+ setCapturePhotoProps: vi.fn(),
62
+ setFieldValue: vi.fn(),
63
+ setFieldTouched: vi.fn(),
64
+ setInitialFormValues: vi.fn(),
64
65
  validationSchema: null,
65
66
  values: mockInitialFormValues,
66
67
  };
67
68
 
68
- jest.mock('./address-hierarchy.resource', () => ({
69
- ...jest.requireActual('./address-hierarchy.resource'),
70
- useOrderedAddressHierarchyLevels: jest.fn(),
69
+ vi.mock('./address-hierarchy.resource', async () => ({
70
+ ...((await vi.importActual('./address-hierarchy.resource')) as object),
71
+ useOrderedAddressHierarchyLevels: vi.fn(),
71
72
  }));
72
73
 
73
- async function renderAddressHierarchy(contextValues: PatientRegistrationContextProps) {
74
- await renderWithContext(
74
+ /**
75
+ * Helper to render AddressComponent with Formik.
76
+ */
77
+ async function renderAddressHierarchy(
78
+ contextValues: PatientRegistrationContextProps,
79
+ resourcesContextValue: Resources = mockResourcesContextValue,
80
+ ) {
81
+ return await renderWithContext(
75
82
  <PatientRegistrationContextProvider value={contextValues}>
76
- <Formik initialValues={mockInitialFormValues} onSubmit={null}>
83
+ <Formik initialValues={mockInitialFormValues} onSubmit={() => {}}>
77
84
  <Form>
78
85
  <AddressComponent />
79
86
  </Form>
80
87
  </Formik>
81
88
  </PatientRegistrationContextProvider>,
82
89
  ResourcesContextProvider,
83
- mockResourcesContextValue,
90
+ resourcesContextValue,
84
91
  );
85
92
  }
86
93
 
87
94
  describe('Address hierarchy', () => {
88
- it('renders a loading skeleton when the address template is loading', () => {
89
- mockUseConfig.mockReturnValue({
90
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
91
- fieldConfigurations: {
92
- address: {
93
- useAddressHierarchy: {
94
- enabled: false,
95
- useQuickSearch: false,
96
- searchAddressByLevel: false,
97
- },
98
- requiredAddressFields: [],
99
- },
100
- } as RegistrationConfig['fieldConfigurations'],
101
- });
102
-
103
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
104
- orderedFields: [],
105
- isLoadingFieldOrder: false,
106
- errorFetchingFieldOrder: undefined,
107
- });
108
-
109
- renderAddressHierarchy(initialContextValues);
110
- expect(screen.getByRole('progressbar')).toBeInTheDocument();
95
+ beforeEach(() => {
96
+ mockResourcesContextValue.addressTemplate = {} as AddressTemplate;
111
97
  });
112
98
 
113
- it('renders a loading skeleton when the address hierarchy feature is enabled and address hierarchy order levels are loading', () => {
114
- mockUseConfig.mockReturnValue({
115
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
116
- fieldConfigurations: {
117
- address: {
118
- useAddressHierarchy: {
119
- enabled: true,
120
- useQuickSearch: false,
121
- searchAddressByLevel: false,
99
+ describe('Loading states', () => {
100
+ it('renders a loading skeleton when the address template is not available', () => {
101
+ mockUseConfig.mockReturnValue({
102
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
103
+ fieldConfigurations: {
104
+ address: {
105
+ useAddressHierarchy: {
106
+ enabled: false,
107
+ useQuickSearch: false,
108
+ searchAddressByLevel: false,
109
+ },
110
+ requiredAddressFields: [],
122
111
  },
123
- },
124
- } as RegistrationConfig['fieldConfigurations'],
112
+ } as RegistrationConfig['fieldConfigurations'],
113
+ fieldDefinitions: [],
114
+ });
115
+
116
+ mockUseOrderedAddressHierarchyLevels.mockReturnValue({
117
+ orderedFields: [],
118
+ isLoadingFieldOrder: false,
119
+ errorFetchingFieldOrder: undefined,
120
+ });
121
+
122
+ renderAddressHierarchy(initialContextValues);
123
+ expect(screen.getByRole('progressbar')).toBeInTheDocument();
125
124
  });
126
125
 
127
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
128
- orderedFields: [],
129
- isLoadingFieldOrder: true,
130
- errorFetchingFieldOrder: undefined,
131
- });
132
-
133
- renderAddressHierarchy(initialContextValues);
134
- expect(screen.getByRole('progressbar')).toBeInTheDocument();
135
- });
136
-
137
- it('renders a loading skeleton when the address hierarchy feature is enabled and address hierarchy order levels are loading', () => {
138
- mockUseConfig.mockReturnValue({
139
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
140
- fieldConfigurations: {
141
- address: {
142
- useAddressHierarchy: {
143
- enabled: true,
144
- useQuickSearch: false,
145
- searchAddressByLevel: false,
126
+ it('renders a loading skeleton when address hierarchy order levels are loading', () => {
127
+ mockUseConfig.mockReturnValue({
128
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
129
+ fieldConfigurations: {
130
+ address: {
131
+ useAddressHierarchy: {
132
+ enabled: true,
133
+ useQuickSearch: false,
134
+ searchAddressByLevel: false,
135
+ },
136
+ requiredAddressFields: [],
146
137
  },
147
- requiredAddressFields: [],
148
- },
149
- } as RegistrationConfig['fieldConfigurations'],
138
+ } as RegistrationConfig['fieldConfigurations'],
139
+ fieldDefinitions: [],
140
+ });
141
+
142
+ mockUseOrderedAddressHierarchyLevels.mockReturnValue({
143
+ orderedFields: [],
144
+ isLoadingFieldOrder: true,
145
+ errorFetchingFieldOrder: undefined,
146
+ });
147
+
148
+ renderAddressHierarchy(initialContextValues);
149
+ expect(screen.getByRole('progressbar')).toBeInTheDocument();
150
150
  });
151
-
152
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
153
- orderedFields: [],
154
- isLoadingFieldOrder: false,
155
- errorFetchingFieldOrder: undefined,
156
- });
157
-
158
- renderAddressHierarchy(initialContextValues);
159
- expect(screen.getByRole('progressbar')).toBeInTheDocument();
160
151
  });
161
152
 
162
- it('renders the address component with address hierarchy disabled', () => {
163
- mockUseConfig.mockReturnValue({
164
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
165
- fieldConfigurations: {
166
- address: {
167
- useAddressHierarchy: {
168
- enabled: false,
169
- useQuickSearch: false,
170
- searchAddressByLevel: false,
171
- },
172
- requiredAddressFields: [],
173
- },
174
- } as RegistrationConfig['fieldConfigurations'],
175
- });
176
-
177
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
178
- orderedFields: [],
179
- isLoadingFieldOrder: false,
180
- errorFetchingFieldOrder: undefined,
153
+ describe('Rendering', () => {
154
+ beforeEach(() => {
155
+ mockResourcesContextValue.addressTemplate = mockedAddressTemplate;
181
156
  });
182
157
 
183
- mockResourcesContextValue.addressTemplate = mockedAddressTemplate;
184
-
185
- renderAddressHierarchy(initialContextValues);
186
-
187
- const allFields = mockedAddressTemplate.lines.flat().filter(({ isToken }) => isToken === 'IS_ADDR_TOKEN');
188
- allFields.forEach((field) => {
189
- const textFieldInput = screen.getByLabelText(`${field.displayText} (optional)`);
190
- expect(textFieldInput).toBeInTheDocument();
191
- });
192
- });
193
-
194
- it('renders the address hierarchy fields in order if the address hierarchy feature is enabled', () => {
195
- mockUseConfig.mockReturnValue({
196
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
197
- fieldConfigurations: {
198
- address: {
199
- useAddressHierarchy: {
200
- enabled: true,
201
- useQuickSearch: false,
202
- searchAddressByLevel: false,
158
+ it('renders address fields when address hierarchy is disabled', () => {
159
+ mockUseConfig.mockReturnValue({
160
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
161
+ fieldConfigurations: {
162
+ address: {
163
+ useAddressHierarchy: {
164
+ enabled: false,
165
+ useQuickSearch: false,
166
+ searchAddressByLevel: false,
167
+ },
168
+ requiredAddressFields: [],
203
169
  },
204
- requiredAddressFields: [],
205
- },
206
- } as RegistrationConfig['fieldConfigurations'],
207
- });
208
-
209
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
210
- orderedFields: [],
211
- isLoadingFieldOrder: false,
212
- errorFetchingFieldOrder: undefined,
170
+ } as RegistrationConfig['fieldConfigurations'],
171
+ fieldDefinitions: [],
172
+ });
173
+
174
+ mockUseOrderedAddressHierarchyLevels.mockReturnValue({
175
+ orderedFields: [],
176
+ isLoadingFieldOrder: false,
177
+ errorFetchingFieldOrder: undefined,
178
+ });
179
+
180
+ renderAddressHierarchy(initialContextValues);
181
+
182
+ const allFields = mockedAddressTemplate.lines.flat().filter(({ isToken }) => isToken === 'IS_ADDR_TOKEN');
183
+ allFields.forEach((field) => {
184
+ const textFieldInput = screen.getByLabelText(`${field.displayText} (optional)`);
185
+ expect(textFieldInput).toBeInTheDocument();
186
+ });
213
187
  });
214
188
 
215
- mockResourcesContextValue.addressTemplate = mockedAddressTemplate;
216
-
217
- renderAddressHierarchy(initialContextValues);
218
-
219
- const allFields = mockedAddressTemplate.lines.flat().filter(({ isToken }) => isToken === 'IS_ADDR_TOKEN');
220
- const orderMap = Object.fromEntries(mockedOrderedFields.map((field, indx) => [field, indx]));
221
- allFields.sort(
222
- (existingField1, existingField2) =>
223
- orderMap[existingField1.codeName ?? 0] - orderMap[existingField2.codeName ?? 0],
224
- );
225
- allFields.forEach((field) => {
226
- const textFieldInput = screen.getByLabelText(`${field.displayText} (optional)`);
227
- expect(textFieldInput).toBeInTheDocument();
228
- });
229
- });
230
-
231
- it('renders the quick search bar above the address hierarchy fields when the address hierarchy feature is enabled and useQuickSearch is set to true', () => {
232
- mockUseConfig.mockReturnValue({
233
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
234
- fieldConfigurations: {
235
- address: {
236
- useAddressHierarchy: {
237
- enabled: true,
238
- useQuickSearch: true,
239
- searchAddressByLevel: false,
189
+ it('renders address hierarchy fields in order when address hierarchy is enabled', () => {
190
+ mockUseConfig.mockReturnValue({
191
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
192
+ fieldConfigurations: {
193
+ address: {
194
+ useAddressHierarchy: {
195
+ enabled: true,
196
+ useQuickSearch: false,
197
+ searchAddressByLevel: false,
198
+ },
199
+ requiredAddressFields: [],
240
200
  },
241
- requiredAddressFields: [],
242
- },
243
- } as RegistrationConfig['fieldConfigurations'],
244
- });
245
-
246
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
247
- orderedFields: [],
248
- isLoadingFieldOrder: false,
249
- errorFetchingFieldOrder: undefined,
201
+ } as RegistrationConfig['fieldConfigurations'],
202
+ fieldDefinitions: [],
203
+ });
204
+
205
+ mockUseOrderedAddressHierarchyLevels.mockReturnValue({
206
+ orderedFields: mockedOrderedFields,
207
+ isLoadingFieldOrder: false,
208
+ errorFetchingFieldOrder: undefined,
209
+ });
210
+
211
+ renderAddressHierarchy(initialContextValues);
212
+
213
+ const allFields = mockedAddressTemplate.lines.flat().filter(({ isToken }) => isToken === 'IS_ADDR_TOKEN');
214
+ const orderMap = Object.fromEntries(mockedOrderedFields.map((field, indx) => [field, indx]));
215
+ allFields.sort(
216
+ (existingField1, existingField2) =>
217
+ orderMap[existingField1.codeName ?? 0] - orderMap[existingField2.codeName ?? 0],
218
+ );
219
+ allFields.forEach((field) => {
220
+ const textFieldInput = screen.getByLabelText(`${field.displayText} (optional)`);
221
+ expect(textFieldInput).toBeInTheDocument();
222
+ });
250
223
  });
251
224
 
252
- mockResourcesContextValue.addressTemplate = mockedAddressTemplate;
253
-
254
- renderAddressHierarchy(initialContextValues);
255
-
256
- const searchbox = screen.getByRole('searchbox', { name: /search address/i });
257
- expect(searchbox).toBeInTheDocument();
258
- });
259
-
260
- it('renders combobox fields when address hierarchy is enabled and searchAddressByLevel is set to true', () => {
261
- mockUseConfig.mockReturnValue({
262
- ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
263
- fieldConfigurations: {
264
- address: {
265
- useAddressHierarchy: {
266
- enabled: true,
267
- useQuickSearch: false,
268
- searchAddressByLevel: true,
225
+ it('renders quick search bar when useQuickSearch is enabled', () => {
226
+ mockUseConfig.mockReturnValue({
227
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
228
+ fieldConfigurations: {
229
+ address: {
230
+ useAddressHierarchy: {
231
+ enabled: true,
232
+ useQuickSearch: true,
233
+ searchAddressByLevel: false,
234
+ },
235
+ requiredAddressFields: [],
269
236
  },
270
- requiredAddressFields: [],
271
- },
272
- } as RegistrationConfig['fieldConfigurations'],
273
- });
237
+ } as RegistrationConfig['fieldConfigurations'],
238
+ fieldDefinitions: [],
239
+ });
274
240
 
275
- mockUseOrderedAddressHierarchyLevels.mockReturnValue({
276
- orderedFields: [],
277
- isLoadingFieldOrder: false,
278
- errorFetchingFieldOrder: undefined,
279
- });
241
+ mockUseOrderedAddressHierarchyLevels.mockReturnValue({
242
+ orderedFields: mockedOrderedFields,
243
+ isLoadingFieldOrder: false,
244
+ errorFetchingFieldOrder: undefined,
245
+ });
280
246
 
281
- mockResourcesContextValue.addressTemplate = mockedAddressTemplate;
247
+ renderAddressHierarchy(initialContextValues);
282
248
 
283
- renderAddressHierarchy(initialContextValues);
249
+ const searchbox = screen.getByRole('searchbox', { name: /search address/i });
250
+ expect(searchbox).toBeInTheDocument();
251
+ });
284
252
 
285
- const allFields = mockedAddressTemplate.lines.flat().filter(({ isToken }) => isToken === 'IS_ADDR_TOKEN');
286
- const orderMap = Object.fromEntries(mockedOrderedFields.map((field, indx) => [field, indx]));
287
- allFields.sort(
288
- (existingField1, existingField2) =>
289
- orderMap[existingField1.codeName ?? 0] - orderMap[existingField2.codeName ?? 0],
290
- );
291
- allFields.forEach((field) => {
292
- const textFieldInput = screen.getByLabelText(`${field.displayText} (optional)`);
293
- expect(textFieldInput).toBeInTheDocument();
253
+ it('renders address fields when searchAddressByLevel is enabled', () => {
254
+ mockUseConfig.mockReturnValue({
255
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
256
+ fieldConfigurations: {
257
+ address: {
258
+ useAddressHierarchy: {
259
+ enabled: true,
260
+ useQuickSearch: false,
261
+ searchAddressByLevel: true,
262
+ },
263
+ requiredAddressFields: [],
264
+ },
265
+ } as RegistrationConfig['fieldConfigurations'],
266
+ fieldDefinitions: [],
267
+ });
268
+
269
+ mockUseOrderedAddressHierarchyLevels.mockReturnValue({
270
+ orderedFields: mockedOrderedFields,
271
+ isLoadingFieldOrder: false,
272
+ errorFetchingFieldOrder: undefined,
273
+ });
274
+
275
+ renderAddressHierarchy(initialContextValues);
276
+
277
+ const allFields = mockedAddressTemplate.lines.flat().filter(({ isToken }) => isToken === 'IS_ADDR_TOKEN');
278
+ const orderMap = Object.fromEntries(mockedOrderedFields.map((field, indx) => [field, indx]));
279
+ allFields.sort(
280
+ (existingField1, existingField2) =>
281
+ orderMap[existingField1.codeName ?? 0] - orderMap[existingField2.codeName ?? 0],
282
+ );
283
+ allFields.forEach((field) => {
284
+ const textFieldInput = screen.getByLabelText(`${field.displayText} (optional)`);
285
+ expect(textFieldInput).toBeInTheDocument();
286
+ });
294
287
  });
295
288
  });
296
289
  });
@@ -16,7 +16,7 @@ const AddressSearchComponent: React.FC<AddressSearchComponentProps> = ({ address
16
16
  const wrapper = useRef(null);
17
17
  const [searchString, setSearchString] = useState('');
18
18
 
19
- const { addresses } = useAddressHierarchy(searchString, separator);
19
+ const { addresses, isLoading, error } = useAddressHierarchy(searchString, separator);
20
20
 
21
21
  const addressOptions: Array<string> = useMemo(() => {
22
22
  const options: Set<string> = new Set();
@@ -65,19 +65,31 @@ const AddressSearchComponent: React.FC<AddressSearchComponentProps> = ({ address
65
65
  <div className={styles.autocomplete} ref={wrapper} style={{ marginBottom: '1rem' }}>
66
66
  <Search
67
67
  onChange={handleInputChange}
68
+ onKeyDown={(e) => {
69
+ if (e.key === 'Enter') {
70
+ e.preventDefault();
71
+ }
72
+ }}
68
73
  labelText={t('searchAddress', 'Search address')}
69
74
  placeholder={t('searchAddress', 'Search address')}
70
75
  ref={searchBox}
71
76
  value={searchString}
72
77
  />
73
- {addressOptions.length > 0 && (
74
- /* Since the input has a marginBottom of 1rem */
78
+ {searchString && (
75
79
  <ul className={styles.suggestions}>
76
- {addressOptions.map((address, index) => (
77
- <li key={index} onClick={(e) => handleChange(address)}>
78
- {address}
79
- </li>
80
- ))}
80
+ {isLoading ? (
81
+ <li className={styles.loading}>{t('searching', 'Searching...')}</li>
82
+ ) : error ? (
83
+ <li className={styles.noResults}>{t('errorFetchingAddresses', 'Error fetching address results')}</li>
84
+ ) : addressOptions.length > 0 ? (
85
+ addressOptions.map((address) => (
86
+ <li key={address} onClick={() => handleChange(address)}>
87
+ {address}
88
+ </li>
89
+ ))
90
+ ) : (
91
+ <li className={styles.noResults}>{t('noAddressResults', 'No matching addresses found')}</li>
92
+ )}
81
93
  </ul>
82
94
  )}
83
95
  </div>
@@ -12,7 +12,7 @@
12
12
  margin-top: 0;
13
13
  max-height: 20rem;
14
14
  overflow-y: auto;
15
- padding-left: 0;
15
+ padding: 0;
16
16
  width: 100%;
17
17
  position: absolute;
18
18
  left: 0;
@@ -26,7 +26,10 @@
26
26
  padding: layout.$spacing-05;
27
27
  line-height: 1.29;
28
28
  color: #525252;
29
- border-bottom: 1px solid #8d8d8d;
29
+ }
30
+
31
+ .suggestions li:last-of-type {
32
+ border-bottom: none;
30
33
  }
31
34
 
32
35
  .suggestions li:hover {
@@ -47,6 +50,20 @@
47
50
  width: 100%;
48
51
  }
49
52
 
53
+ .noResults,
54
+ .loading {
55
+ color: $text-02;
56
+ cursor: default;
57
+ border-bottom: none;
58
+ }
59
+
60
+ .noResults:hover,
61
+ .loading:hover {
62
+ background-color: inherit;
63
+ color: $text-02;
64
+ cursor: default;
65
+ }
66
+
50
67
  .suggestions a {
51
68
  color: inherit;
52
69
  text-decoration: none;