@openmrs/esm-form-engine-lib 2.1.0-pre.1435 → 2.1.0-pre.1442
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/package.json +1 -1
- package/src/adapters/obs-adapter.test.ts +908 -0
- package/src/components/inputs/text/text.test.tsx +10 -8
- package/src/provider/form-factory-provider.tsx +11 -2
- package/05e6df0fe8b59eb3/05e6df0fe8b59eb3.gz +0 -0
- package/5b7cf2c900238b5f/5b7cf2c900238b5f.gz +0 -0
- package/6110c95ec25070ab/6110c95ec25070ab.gz +0 -0
- package/70e17c49e61fa7d9/70e17c49e61fa7d9.gz +0 -0
package/package.json
CHANGED
@@ -0,0 +1,908 @@
|
|
1
|
+
import { type FormContextProps } from '../provider/form-provider';
|
2
|
+
import { type FormField } from '../types';
|
3
|
+
import { hasPreviousObsValueChanged, findObsByFormField, ObsAdapter } from './obs-adapter';
|
4
|
+
|
5
|
+
const formContext = {
|
6
|
+
methods: null,
|
7
|
+
workspaceLayout: 'maximized',
|
8
|
+
isSubmitting: false,
|
9
|
+
patient: {
|
10
|
+
id: '833db896-c1f0-11eb-8529-0242ac130003',
|
11
|
+
},
|
12
|
+
formJson: null,
|
13
|
+
visit: null,
|
14
|
+
sessionMode: 'enter',
|
15
|
+
sessionDate: new Date(),
|
16
|
+
location: {
|
17
|
+
uuid: '41e6e516-c1f0-11eb-8529-0242ac130003',
|
18
|
+
},
|
19
|
+
currentProvider: null,
|
20
|
+
layoutType: 'small-desktop',
|
21
|
+
domainObjectValue: {
|
22
|
+
uuid: '873455da-3ec4-453c-b565-7c1fe35426be',
|
23
|
+
obs: [],
|
24
|
+
},
|
25
|
+
previousDomainObjectValue: null,
|
26
|
+
processor: null,
|
27
|
+
formFields: [],
|
28
|
+
formFieldAdapters: null,
|
29
|
+
formFieldValidators: null,
|
30
|
+
customDependencies: null,
|
31
|
+
getFormField: jest.fn(),
|
32
|
+
addFormField: jest.fn(),
|
33
|
+
updateFormField: jest.fn(),
|
34
|
+
removeFormField: () => {},
|
35
|
+
addInvalidField: jest.fn(),
|
36
|
+
removeInvalidField: jest.fn(),
|
37
|
+
setInvalidFields: jest.fn(),
|
38
|
+
setForm: jest.fn(),
|
39
|
+
} as FormContextProps;
|
40
|
+
|
41
|
+
describe('ObsAdapter - transformFieldValue', () => {
|
42
|
+
// new submission (enter mode)
|
43
|
+
it('should handle submission for text input', () => {
|
44
|
+
// setup
|
45
|
+
const field: FormField = {
|
46
|
+
label: 'Visit note',
|
47
|
+
type: 'obs',
|
48
|
+
questionOptions: {
|
49
|
+
rendering: 'text',
|
50
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
51
|
+
},
|
52
|
+
id: 'visit-note',
|
53
|
+
};
|
54
|
+
// replay
|
55
|
+
const obs = ObsAdapter.transformFieldValue(field, 'Can be discharged in next visit', formContext);
|
56
|
+
// verify
|
57
|
+
expect(obs).toEqual({
|
58
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
59
|
+
formFieldNamespace: 'rfe-forms',
|
60
|
+
formFieldPath: 'rfe-forms-visit-note',
|
61
|
+
value: 'Can be discharged in next visit',
|
62
|
+
});
|
63
|
+
});
|
64
|
+
|
65
|
+
it('should handle submission for number input', () => {
|
66
|
+
// setup
|
67
|
+
const field: FormField = {
|
68
|
+
label: 'Temperature',
|
69
|
+
type: 'obs',
|
70
|
+
questionOptions: {
|
71
|
+
rendering: 'number',
|
72
|
+
concept: '2c43u05b-b6d8-4eju-8f37-0b14f5347560',
|
73
|
+
},
|
74
|
+
id: 'temperature',
|
75
|
+
};
|
76
|
+
// replay
|
77
|
+
const obs = ObsAdapter.transformFieldValue(field, 36, formContext);
|
78
|
+
// verify
|
79
|
+
expect(obs).toEqual({
|
80
|
+
concept: '2c43u05b-b6d8-4eju-8f37-0b14f5347560',
|
81
|
+
formFieldNamespace: 'rfe-forms',
|
82
|
+
formFieldPath: 'rfe-forms-temperature',
|
83
|
+
value: 36,
|
84
|
+
});
|
85
|
+
});
|
86
|
+
|
87
|
+
it('should handle submission for multiselect input', () => {
|
88
|
+
// setup
|
89
|
+
const field: FormField = {
|
90
|
+
label: 'Past enrolled patient programs',
|
91
|
+
type: 'obs',
|
92
|
+
questionOptions: {
|
93
|
+
rendering: 'checkbox',
|
94
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
95
|
+
answers: [
|
96
|
+
{ label: 'Oncology Screening and Diagnosis Program', concept: '105e7ad6-c1fd-11eb-8529-0242ac130ju9' },
|
97
|
+
{ label: 'Fight Malaria Initiative', concept: '305e7ad6-c1fd-11eb-8529-0242ac130003' },
|
98
|
+
],
|
99
|
+
},
|
100
|
+
id: 'past-patient-programs',
|
101
|
+
};
|
102
|
+
|
103
|
+
// replay
|
104
|
+
// Select Oncology Screening and Diagnosis Program
|
105
|
+
let obs = ObsAdapter.transformFieldValue(field, ['105e7ad6-c1fd-11eb-8529-0242ac130ju9'], formContext);
|
106
|
+
|
107
|
+
// verify
|
108
|
+
expect(obs).toEqual([
|
109
|
+
{
|
110
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
111
|
+
formFieldNamespace: 'rfe-forms',
|
112
|
+
formFieldPath: 'rfe-forms-past-patient-programs',
|
113
|
+
value: '105e7ad6-c1fd-11eb-8529-0242ac130ju9',
|
114
|
+
},
|
115
|
+
]);
|
116
|
+
|
117
|
+
// replay
|
118
|
+
// Add Fight Malaria Initiative
|
119
|
+
obs = ObsAdapter.transformFieldValue(
|
120
|
+
field,
|
121
|
+
['105e7ad6-c1fd-11eb-8529-0242ac130ju9', '305e7ad6-c1fd-11eb-8529-0242ac130003'],
|
122
|
+
formContext,
|
123
|
+
);
|
124
|
+
|
125
|
+
// verify
|
126
|
+
expect(obs).toEqual([
|
127
|
+
{
|
128
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
129
|
+
formFieldNamespace: 'rfe-forms',
|
130
|
+
formFieldPath: 'rfe-forms-past-patient-programs',
|
131
|
+
value: '105e7ad6-c1fd-11eb-8529-0242ac130ju9',
|
132
|
+
},
|
133
|
+
{
|
134
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
135
|
+
formFieldNamespace: 'rfe-forms',
|
136
|
+
formFieldPath: 'rfe-forms-past-patient-programs',
|
137
|
+
value: '305e7ad6-c1fd-11eb-8529-0242ac130003',
|
138
|
+
},
|
139
|
+
]);
|
140
|
+
});
|
141
|
+
|
142
|
+
it('should handle submission for date input', () => {
|
143
|
+
// setup
|
144
|
+
const field: FormField = {
|
145
|
+
label: 'HTS Date',
|
146
|
+
type: 'obs',
|
147
|
+
datePickerFormat: 'calendar',
|
148
|
+
questionOptions: {
|
149
|
+
rendering: 'date',
|
150
|
+
concept: 'j8b6705b-b6d8-4eju-8f37-0b14f5347569',
|
151
|
+
},
|
152
|
+
id: 'hts-date',
|
153
|
+
};
|
154
|
+
// Dec 20, 2019
|
155
|
+
const htsDate = new Date(2019, 11, 20);
|
156
|
+
// replay
|
157
|
+
const obs = ObsAdapter.transformFieldValue(field, htsDate, formContext);
|
158
|
+
// verify
|
159
|
+
expect(obs).toEqual({
|
160
|
+
concept: 'j8b6705b-b6d8-4eju-8f37-0b14f5347569',
|
161
|
+
formFieldNamespace: 'rfe-forms',
|
162
|
+
formFieldPath: 'rfe-forms-hts-date',
|
163
|
+
value: '2019-12-20',
|
164
|
+
});
|
165
|
+
});
|
166
|
+
|
167
|
+
it('should handle submission for single-select inputs', () => {
|
168
|
+
// setup
|
169
|
+
const field: FormField = {
|
170
|
+
label: 'HTS Result',
|
171
|
+
type: 'obs',
|
172
|
+
questionOptions: {
|
173
|
+
rendering: 'content-switcher',
|
174
|
+
concept: '89jbi9jk-b6d8-4eju-8f37-0b14f53mhj098b',
|
175
|
+
},
|
176
|
+
id: 'hts-result',
|
177
|
+
};
|
178
|
+
// replay
|
179
|
+
const obs = ObsAdapter.transformFieldValue(field, 'n8hynk0j-c1fd-117g-8529-0242ac1hgc9j', formContext);
|
180
|
+
// verify
|
181
|
+
expect(obs).toEqual({
|
182
|
+
concept: '89jbi9jk-b6d8-4eju-8f37-0b14f53mhj098b',
|
183
|
+
formFieldNamespace: 'rfe-forms',
|
184
|
+
formFieldPath: 'rfe-forms-hts-result',
|
185
|
+
value: 'n8hynk0j-c1fd-117g-8529-0242ac1hgc9j',
|
186
|
+
});
|
187
|
+
});
|
188
|
+
|
189
|
+
// editing existing values (edit mode)
|
190
|
+
it('should edit obs text/number value in edit mode', () => {
|
191
|
+
// setup
|
192
|
+
formContext.sessionMode = 'edit';
|
193
|
+
const field: FormField = {
|
194
|
+
label: 'Visit note',
|
195
|
+
type: 'obs',
|
196
|
+
questionOptions: {
|
197
|
+
rendering: 'text',
|
198
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
199
|
+
},
|
200
|
+
meta: {
|
201
|
+
previousValue: {
|
202
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
203
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
204
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
205
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
206
|
+
order: null,
|
207
|
+
groupMembers: [],
|
208
|
+
voided: false,
|
209
|
+
value: 'Can be discharged in next visit',
|
210
|
+
},
|
211
|
+
},
|
212
|
+
id: 'visit-note',
|
213
|
+
};
|
214
|
+
|
215
|
+
// replay
|
216
|
+
ObsAdapter.transformFieldValue(field, 'Discharged with minor symptoms', formContext);
|
217
|
+
|
218
|
+
// verify
|
219
|
+
expect(field.meta.submission.newValue).toEqual({
|
220
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
221
|
+
formFieldNamespace: 'rfe-forms',
|
222
|
+
formFieldPath: 'rfe-forms-visit-note',
|
223
|
+
value: 'Discharged with minor symptoms',
|
224
|
+
});
|
225
|
+
expect(field.meta.submission.voidedValue).toBe(null);
|
226
|
+
});
|
227
|
+
|
228
|
+
it('should edit obs coded value in edit mode', () => {
|
229
|
+
// setup
|
230
|
+
formContext.sessionMode = 'edit';
|
231
|
+
const field: FormField = {
|
232
|
+
label: 'HTS Result',
|
233
|
+
type: 'obs',
|
234
|
+
questionOptions: {
|
235
|
+
rendering: 'radio',
|
236
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
237
|
+
},
|
238
|
+
meta: {
|
239
|
+
previousValue: {
|
240
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
241
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
242
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
243
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
244
|
+
order: null,
|
245
|
+
groupMembers: [],
|
246
|
+
voided: false,
|
247
|
+
value: '5197ca4f-f0f7-4e63-9a68-8614224dce44',
|
248
|
+
},
|
249
|
+
},
|
250
|
+
id: 'hts-result',
|
251
|
+
};
|
252
|
+
// replay
|
253
|
+
ObsAdapter.transformFieldValue(field, 'a7fd300b-f4b5-4cd1-94f8-915adf61a5e3', formContext);
|
254
|
+
// verify
|
255
|
+
expect(field.meta.submission.newValue).toEqual({
|
256
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
257
|
+
formFieldNamespace: 'rfe-forms',
|
258
|
+
formFieldPath: 'rfe-forms-hts-result',
|
259
|
+
value: 'a7fd300b-f4b5-4cd1-94f8-915adf61a5e3',
|
260
|
+
});
|
261
|
+
expect(field.meta.submission.voidedValue).toBe(null);
|
262
|
+
});
|
263
|
+
|
264
|
+
it('should edit obs value(s) from multiselect input component', () => {
|
265
|
+
// setup
|
266
|
+
formContext.sessionMode = 'edit';
|
267
|
+
const field: FormField = {
|
268
|
+
label: 'Past enrolled patient programs',
|
269
|
+
type: 'obs',
|
270
|
+
questionOptions: {
|
271
|
+
rendering: 'checkbox',
|
272
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
273
|
+
answers: [
|
274
|
+
{ label: 'Option 1', concept: '105e7ad6-c1fd-11eb-8529-0242ac130ju9' },
|
275
|
+
{ label: 'Option 2', concept: '305e77c0-c1fd-11eb-8529-0242ac130003' },
|
276
|
+
],
|
277
|
+
},
|
278
|
+
meta: {
|
279
|
+
previousValue: [
|
280
|
+
{
|
281
|
+
uuid: 'f2487de5-e55f-4689-8791-0c919179818b',
|
282
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
283
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
284
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
285
|
+
order: null,
|
286
|
+
groupMembers: [],
|
287
|
+
voided: false,
|
288
|
+
formFieldNamespace: 'rfe-forms',
|
289
|
+
formFieldPath: 'rfe-forms-past-patient-programs',
|
290
|
+
value: {
|
291
|
+
uuid: '105e7ad6-c1fd-11eb-8529-0242ac130ju9',
|
292
|
+
},
|
293
|
+
},
|
294
|
+
],
|
295
|
+
},
|
296
|
+
id: 'past-patient-programs',
|
297
|
+
};
|
298
|
+
|
299
|
+
// replay
|
300
|
+
ObsAdapter.transformFieldValue(
|
301
|
+
field,
|
302
|
+
['105e7ad6-c1fd-11eb-8529-0242ac130ju9', '305e77c0-c1fd-11eb-8529-0242ac130003'],
|
303
|
+
formContext,
|
304
|
+
);
|
305
|
+
|
306
|
+
// verify
|
307
|
+
expect(field.meta.submission.newValue).toEqual([
|
308
|
+
{
|
309
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
310
|
+
formFieldNamespace: 'rfe-forms',
|
311
|
+
formFieldPath: 'rfe-forms-past-patient-programs',
|
312
|
+
value: '305e77c0-c1fd-11eb-8529-0242ac130003',
|
313
|
+
},
|
314
|
+
]);
|
315
|
+
expect(field.meta.submission.voidedValue).toBe(null);
|
316
|
+
});
|
317
|
+
|
318
|
+
it('should edit obs date value in edit mode', () => {
|
319
|
+
// setup
|
320
|
+
formContext.sessionMode = 'edit';
|
321
|
+
const field: FormField = {
|
322
|
+
label: 'HTS date',
|
323
|
+
type: 'obs',
|
324
|
+
datePickerFormat: 'calendar',
|
325
|
+
questionOptions: {
|
326
|
+
rendering: 'date',
|
327
|
+
concept: '3e432ad5-7b19-4866-a68f-abf0d9f52a01',
|
328
|
+
},
|
329
|
+
meta: {
|
330
|
+
previousValue: {
|
331
|
+
uuid: 'bca7277f-a726-4d3d-9db8-40937228ead5',
|
332
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
333
|
+
concept: '3e432ad5-7b19-4866-a68f-abf0d9f52a01',
|
334
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
335
|
+
order: null,
|
336
|
+
groupMembers: [],
|
337
|
+
voided: false,
|
338
|
+
value: new Date(2020, 11, 16),
|
339
|
+
},
|
340
|
+
},
|
341
|
+
id: 'hts-date',
|
342
|
+
};
|
343
|
+
const newHtsDate = new Date(2021, 11, 16);
|
344
|
+
// replay
|
345
|
+
ObsAdapter.transformFieldValue(field, newHtsDate, formContext);
|
346
|
+
// verify
|
347
|
+
expect(field.meta.submission.newValue).toEqual({
|
348
|
+
uuid: 'bca7277f-a726-4d3d-9db8-40937228ead5',
|
349
|
+
formFieldNamespace: 'rfe-forms',
|
350
|
+
formFieldPath: 'rfe-forms-hts-date',
|
351
|
+
value: '2021-12-16',
|
352
|
+
});
|
353
|
+
expect(field.meta.submission.voidedValue).toBe(null);
|
354
|
+
});
|
355
|
+
|
356
|
+
// deleting/voiding existing values (edit mode)
|
357
|
+
it('should void deleted obs text/number value in edit mode', () => {
|
358
|
+
// setup
|
359
|
+
formContext.sessionMode = 'edit';
|
360
|
+
const field: FormField = {
|
361
|
+
label: 'Visit note',
|
362
|
+
type: 'obs',
|
363
|
+
questionOptions: {
|
364
|
+
rendering: 'text',
|
365
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
366
|
+
},
|
367
|
+
meta: {
|
368
|
+
previousValue: {
|
369
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
370
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
371
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
372
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
373
|
+
order: null,
|
374
|
+
groupMembers: [],
|
375
|
+
voided: false,
|
376
|
+
value: 'Can be discharged in next visit',
|
377
|
+
},
|
378
|
+
},
|
379
|
+
id: 'visit-note',
|
380
|
+
};
|
381
|
+
|
382
|
+
// replay
|
383
|
+
ObsAdapter.transformFieldValue(field, '', formContext);
|
384
|
+
|
385
|
+
// verify
|
386
|
+
expect(field.meta.submission.voidedValue).toEqual({
|
387
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
388
|
+
voided: true,
|
389
|
+
});
|
390
|
+
expect(field.meta.submission.newValue).toBe(null);
|
391
|
+
});
|
392
|
+
|
393
|
+
it('should void deleted obs coded value in edit mode', () => {
|
394
|
+
// setup
|
395
|
+
formContext.sessionMode = 'edit';
|
396
|
+
const field: FormField = {
|
397
|
+
label: 'HTS Result',
|
398
|
+
type: 'obs',
|
399
|
+
questionOptions: {
|
400
|
+
rendering: 'content-switcher',
|
401
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
402
|
+
},
|
403
|
+
meta: {
|
404
|
+
previousValue: {
|
405
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
406
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
407
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
408
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
409
|
+
order: null,
|
410
|
+
groupMembers: [],
|
411
|
+
voided: false,
|
412
|
+
value: '5197ca4f-f0f7-4e63-9a68-8614224dce44',
|
413
|
+
},
|
414
|
+
},
|
415
|
+
id: 'hts-result',
|
416
|
+
};
|
417
|
+
// replay
|
418
|
+
ObsAdapter.transformFieldValue(field, null, formContext);
|
419
|
+
// verify
|
420
|
+
expect(field.meta.submission.voidedValue).toEqual({
|
421
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
422
|
+
voided: true,
|
423
|
+
});
|
424
|
+
});
|
425
|
+
|
426
|
+
it('should void deleted obs coded value(s) from a multiselect input component', () => {
|
427
|
+
// setup
|
428
|
+
formContext.sessionMode = 'edit';
|
429
|
+
const field: FormField = {
|
430
|
+
label: 'Past enrolled patient programs',
|
431
|
+
type: 'obs',
|
432
|
+
questionOptions: {
|
433
|
+
rendering: 'checkbox',
|
434
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
435
|
+
answers: [{ label: 'Option 1', concept: '105e7ad6-c1fd-11eb-8529-0242ac130ju9' }],
|
436
|
+
},
|
437
|
+
meta: {
|
438
|
+
previousValue: [
|
439
|
+
{
|
440
|
+
uuid: 'f2487de5-e55f-4689-8791-0c919179818b',
|
441
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
442
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
443
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
444
|
+
order: null,
|
445
|
+
groupMembers: [],
|
446
|
+
voided: false,
|
447
|
+
value: {
|
448
|
+
uuid: '105e7ad6-c1fd-11eb-8529-0242ac130ju9',
|
449
|
+
},
|
450
|
+
},
|
451
|
+
],
|
452
|
+
},
|
453
|
+
id: 'past-patient-programs',
|
454
|
+
};
|
455
|
+
|
456
|
+
// replay
|
457
|
+
ObsAdapter.transformFieldValue(field, [], formContext);
|
458
|
+
|
459
|
+
// verify
|
460
|
+
expect(field.meta.submission.voidedValue).toEqual([
|
461
|
+
{
|
462
|
+
uuid: 'f2487de5-e55f-4689-8791-0c919179818b',
|
463
|
+
voided: true,
|
464
|
+
},
|
465
|
+
]);
|
466
|
+
expect(field.meta.submission.newValue).toBe(null);
|
467
|
+
});
|
468
|
+
|
469
|
+
it('should void deleted obs date value in edit mode', () => {
|
470
|
+
// setup
|
471
|
+
formContext.sessionMode = 'edit';
|
472
|
+
const htsDate = new Date(2020, 11, 16);
|
473
|
+
const field: FormField = {
|
474
|
+
label: 'HTS date',
|
475
|
+
type: 'obs',
|
476
|
+
datePickerFormat: 'calendar',
|
477
|
+
questionOptions: {
|
478
|
+
rendering: 'date',
|
479
|
+
concept: '3e432ad5-7b19-4866-a68f-abf0d9f52a01',
|
480
|
+
},
|
481
|
+
meta: {
|
482
|
+
previousValue: {
|
483
|
+
uuid: 'bca7277f-a726-4d3d-9db8-40937228ead5',
|
484
|
+
person: '833db896-c1f0-11eb-8529-0242ac130003',
|
485
|
+
concept: '3e432ad5-7b19-4866-a68f-abf0d9f52a01',
|
486
|
+
location: { uuid: '41e6e516-c1f0-11eb-8529-0242ac130003' },
|
487
|
+
order: null,
|
488
|
+
groupMembers: [],
|
489
|
+
voided: false,
|
490
|
+
value: htsDate,
|
491
|
+
},
|
492
|
+
},
|
493
|
+
id: 'hts-date',
|
494
|
+
};
|
495
|
+
// replay
|
496
|
+
ObsAdapter.transformFieldValue(field, '', formContext);
|
497
|
+
// verify
|
498
|
+
expect(field.meta.submission.voidedValue).toEqual({
|
499
|
+
uuid: 'bca7277f-a726-4d3d-9db8-40937228ead5',
|
500
|
+
voided: true,
|
501
|
+
});
|
502
|
+
expect(field.meta.submission.newValue).toBe(null);
|
503
|
+
});
|
504
|
+
});
|
505
|
+
|
506
|
+
describe('ObsAdapter - getInitialValue', () => {
|
507
|
+
it('should get initial value for text rendering', async () => {
|
508
|
+
// setup
|
509
|
+
const field: FormField = {
|
510
|
+
label: 'Visit note',
|
511
|
+
type: 'obs',
|
512
|
+
questionOptions: {
|
513
|
+
rendering: 'text',
|
514
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
515
|
+
},
|
516
|
+
id: 'visit-note',
|
517
|
+
};
|
518
|
+
const obs: any = {
|
519
|
+
uuid: '86a9366f-009b-40b7-b8ac-81fc6c4d7ca6',
|
520
|
+
concept: {
|
521
|
+
uuid: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
522
|
+
},
|
523
|
+
value: 'Can be discharged in next visit',
|
524
|
+
};
|
525
|
+
formContext.domainObjectValue['obs'].push(obs);
|
526
|
+
// replay
|
527
|
+
const initialValue = await ObsAdapter.getInitialValue(field, formContext.domainObjectValue, formContext);
|
528
|
+
// verify
|
529
|
+
expect(initialValue).toBe('Can be discharged in next visit');
|
530
|
+
});
|
531
|
+
|
532
|
+
it('should get initial value for number rendering', async () => {
|
533
|
+
// setup
|
534
|
+
const field: FormField = {
|
535
|
+
label: 'Temperature',
|
536
|
+
type: 'obs',
|
537
|
+
questionOptions: {
|
538
|
+
rendering: 'number',
|
539
|
+
concept: '7928c3ab-4d14-471f-94a8-a12eaa59e29c',
|
540
|
+
},
|
541
|
+
id: 'temp',
|
542
|
+
};
|
543
|
+
const obs: any = {
|
544
|
+
uuid: '6ae85e6f-134d-48c2-b89a-8293d6ea7e3d',
|
545
|
+
concept: {
|
546
|
+
uuid: '7928c3ab-4d14-471f-94a8-a12eaa59e29c',
|
547
|
+
},
|
548
|
+
value: 37,
|
549
|
+
};
|
550
|
+
formContext.domainObjectValue['obs'].push(obs);
|
551
|
+
// replay
|
552
|
+
const initialValue = await ObsAdapter.getInitialValue(field, formContext.domainObjectValue, formContext);
|
553
|
+
// verify
|
554
|
+
expect(initialValue).toBe(37);
|
555
|
+
});
|
556
|
+
|
557
|
+
it('should get initial value for multi-checkbox rendering', async () => {
|
558
|
+
// setup
|
559
|
+
const field: FormField = {
|
560
|
+
label: 'Past enrolled patient programs',
|
561
|
+
type: 'obs',
|
562
|
+
questionOptions: {
|
563
|
+
rendering: 'checkbox',
|
564
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
565
|
+
},
|
566
|
+
id: 'past-patient-programs',
|
567
|
+
};
|
568
|
+
const obsList: Array<any> = [
|
569
|
+
{
|
570
|
+
uuid: 'f2487de5-e55f-4689-8791-0c919179818b',
|
571
|
+
concept: {
|
572
|
+
uuid: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
573
|
+
},
|
574
|
+
value: {
|
575
|
+
uuid: '105e7ad6-c1fd-11eb-8529-0242ac130ju9',
|
576
|
+
},
|
577
|
+
},
|
578
|
+
{
|
579
|
+
uuid: '23fd1819-0eb2-4753-88d7-6fc015786c8d',
|
580
|
+
concept: {
|
581
|
+
uuid: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
582
|
+
},
|
583
|
+
value: {
|
584
|
+
uuid: '6f337e18-5445-437f-8298-684a7067dc1c',
|
585
|
+
},
|
586
|
+
},
|
587
|
+
];
|
588
|
+
formContext.domainObjectValue['obs'] = obsList;
|
589
|
+
// replay
|
590
|
+
const initialValue = await ObsAdapter.getInitialValue(field, formContext.domainObjectValue, formContext);
|
591
|
+
// verify
|
592
|
+
expect(initialValue).toEqual(['105e7ad6-c1fd-11eb-8529-0242ac130ju9', '6f337e18-5445-437f-8298-684a7067dc1c']);
|
593
|
+
});
|
594
|
+
|
595
|
+
it('should get initial value for date rendering', async () => {
|
596
|
+
// setup
|
597
|
+
const field: FormField = {
|
598
|
+
label: 'HTS Date',
|
599
|
+
type: 'obs',
|
600
|
+
datePickerFormat: 'calendar',
|
601
|
+
questionOptions: {
|
602
|
+
rendering: 'date',
|
603
|
+
concept: 'j8b6705b-b6d8-4eju-8f37-0b14f5347569',
|
604
|
+
},
|
605
|
+
id: 'hts-date',
|
606
|
+
};
|
607
|
+
const obs: any = {
|
608
|
+
uuid: '828cff78-2c38-4ed2-94f1-61c5f79dda17',
|
609
|
+
concept: {
|
610
|
+
uuid: 'j8b6705b-b6d8-4eju-8f37-0b14f5347569',
|
611
|
+
},
|
612
|
+
value: '2016-11-19T00:00',
|
613
|
+
};
|
614
|
+
formContext.domainObjectValue['obs'].push(obs);
|
615
|
+
// replay
|
616
|
+
const initialValue: any = await ObsAdapter.getInitialValue(field, formContext.domainObjectValue, formContext);
|
617
|
+
// verify
|
618
|
+
expect(initialValue.toLocaleDateString('en-US')).toEqual('11/19/2016');
|
619
|
+
});
|
620
|
+
|
621
|
+
it('should get initial value for coded input types', async () => {
|
622
|
+
// setup
|
623
|
+
const field: FormField = {
|
624
|
+
label: 'HTS Result',
|
625
|
+
type: 'obs',
|
626
|
+
questionOptions: {
|
627
|
+
rendering: 'radio',
|
628
|
+
concept: '4e59df68-9774-49b3-9d33-ab75139c6a68',
|
629
|
+
},
|
630
|
+
id: 'hts-result',
|
631
|
+
};
|
632
|
+
const obs: any = {
|
633
|
+
uuid: '305ed1fc-c1fd-11eb-8529-0242ac130003',
|
634
|
+
concept: {
|
635
|
+
uuid: '4e59df68-9774-49b3-9d33-ab75139c6a68',
|
636
|
+
},
|
637
|
+
value: {
|
638
|
+
uuid: '12f7be3d-fb5d-47dc-b5e3-56c501be80a6',
|
639
|
+
},
|
640
|
+
};
|
641
|
+
formContext.domainObjectValue['obs'].push(obs);
|
642
|
+
// replay
|
643
|
+
const initialValue = await ObsAdapter.getInitialValue(field, formContext.domainObjectValue, formContext);
|
644
|
+
// verify
|
645
|
+
expect(initialValue).toEqual('12f7be3d-fb5d-47dc-b5e3-56c501be80a6');
|
646
|
+
});
|
647
|
+
|
648
|
+
it('should get initial values for obs-group members', async () => {
|
649
|
+
// setup
|
650
|
+
const basePath = 'rfe-forms-';
|
651
|
+
const groupingQuestion: FormField = {
|
652
|
+
label: 'Obs Group',
|
653
|
+
type: 'obsGroup',
|
654
|
+
questionOptions: {
|
655
|
+
rendering: 'group',
|
656
|
+
concept: '3e59df68-v77c-49b3-9d33-aS75133c6a67',
|
657
|
+
},
|
658
|
+
questions: [
|
659
|
+
{
|
660
|
+
label: 'Past enrolled patient programs',
|
661
|
+
type: 'obs',
|
662
|
+
questionOptions: {
|
663
|
+
rendering: 'checkbox',
|
664
|
+
concept: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
665
|
+
},
|
666
|
+
id: 'past-patient-programs',
|
667
|
+
},
|
668
|
+
{
|
669
|
+
label: 'Visit note',
|
670
|
+
type: 'obs',
|
671
|
+
questionOptions: {
|
672
|
+
rendering: 'text',
|
673
|
+
concept: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
674
|
+
},
|
675
|
+
id: 'visit-note',
|
676
|
+
},
|
677
|
+
],
|
678
|
+
id: 'obs-group',
|
679
|
+
};
|
680
|
+
const obsList: Array<any> = [
|
681
|
+
{
|
682
|
+
uuid: 'm2487deh-e55f-4689-8791-nc9191798180',
|
683
|
+
concept: {
|
684
|
+
uuid: '3e59df68-v77c-49b3-9d33-aS75133c6a67',
|
685
|
+
},
|
686
|
+
groupMembers: [
|
687
|
+
{
|
688
|
+
uuid: 'f2487de5-e55f-4689-8791-0c919179818b',
|
689
|
+
concept: {
|
690
|
+
uuid: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
691
|
+
},
|
692
|
+
value: {
|
693
|
+
uuid: '105e7ad6-c1fd-11eb-8529-0242ac130ju9',
|
694
|
+
},
|
695
|
+
obsGroup: {
|
696
|
+
uuid: 'm2487deh-e55f-4689-8791-nc9191798180',
|
697
|
+
},
|
698
|
+
formFieldPath: basePath + 'past-patient-programs',
|
699
|
+
},
|
700
|
+
{
|
701
|
+
uuid: '23fd1819-0eb2-4753-88d7-6fc015786c8d',
|
702
|
+
concept: {
|
703
|
+
uuid: '3hbkj9-b6d8-4eju-8f37-0b14f5347jv9',
|
704
|
+
},
|
705
|
+
value: {
|
706
|
+
uuid: '6f337e18-5445-437f-8298-684a7067dc1c',
|
707
|
+
},
|
708
|
+
obsGroup: {
|
709
|
+
uuid: 'm2487deh-e55f-4689-8791-nc9191798180',
|
710
|
+
},
|
711
|
+
formFieldPath: basePath + 'past-patient-programs',
|
712
|
+
},
|
713
|
+
{
|
714
|
+
uuid: '86a9366f-009b-40b7-b8ac-81fc6c4d7ca6',
|
715
|
+
concept: {
|
716
|
+
uuid: '1c43b05b-b6d8-4eb5-8f37-0b14f5347568',
|
717
|
+
},
|
718
|
+
value: 'Can be discharged in next visit',
|
719
|
+
obsGroup: {
|
720
|
+
uuid: 'm2487deh-e55f-4689-8791-nc9191798180',
|
721
|
+
},
|
722
|
+
formFieldPath: basePath + 'visit-note',
|
723
|
+
},
|
724
|
+
],
|
725
|
+
},
|
726
|
+
];
|
727
|
+
|
728
|
+
formContext.domainObjectValue['obs'] = obsList;
|
729
|
+
|
730
|
+
// past enrolled programs init value
|
731
|
+
let initialValue = await ObsAdapter.getInitialValue(
|
732
|
+
groupingQuestion.questions[0],
|
733
|
+
formContext.domainObjectValue,
|
734
|
+
formContext,
|
735
|
+
);
|
736
|
+
expect(initialValue).toEqual(['105e7ad6-c1fd-11eb-8529-0242ac130ju9', '6f337e18-5445-437f-8298-684a7067dc1c']);
|
737
|
+
|
738
|
+
// visit note init value
|
739
|
+
initialValue = await ObsAdapter.getInitialValue(
|
740
|
+
groupingQuestion.questions[1],
|
741
|
+
formContext.domainObjectValue,
|
742
|
+
formContext,
|
743
|
+
);
|
744
|
+
expect(initialValue).toEqual('Can be discharged in next visit');
|
745
|
+
});
|
746
|
+
});
|
747
|
+
|
748
|
+
describe('hasPreviousObsValueChanged', () => {
|
749
|
+
it('should support coded values', () => {
|
750
|
+
const codedField = {
|
751
|
+
questionOptions: {
|
752
|
+
rendering: 'radio',
|
753
|
+
},
|
754
|
+
meta: {
|
755
|
+
previousValue: {
|
756
|
+
value: {
|
757
|
+
uuid: '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
758
|
+
},
|
759
|
+
},
|
760
|
+
},
|
761
|
+
} as any as FormField;
|
762
|
+
|
763
|
+
expect(hasPreviousObsValueChanged(codedField, '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')).toBe(false);
|
764
|
+
expect(hasPreviousObsValueChanged(codedField, '1066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')).toBe(true);
|
765
|
+
});
|
766
|
+
it('should support date values', () => {
|
767
|
+
const dateField = {
|
768
|
+
datePickerFormat: 'calendar',
|
769
|
+
questionOptions: {
|
770
|
+
rendering: 'date',
|
771
|
+
},
|
772
|
+
meta: {
|
773
|
+
previousValue: {
|
774
|
+
value: '2024-05-01T19:49:50.000+0000',
|
775
|
+
},
|
776
|
+
},
|
777
|
+
} as any as FormField;
|
778
|
+
expect(hasPreviousObsValueChanged(dateField, new Date('2024-05-01T19:49:50.000+0000'))).toBe(false);
|
779
|
+
expect(hasPreviousObsValueChanged(dateField, new Date('2024-05-02T15:49:50.000+0000'))).toBe(true);
|
780
|
+
});
|
781
|
+
it('should support datetime values', () => {
|
782
|
+
const dateTimeField = {
|
783
|
+
datePickerFormat: 'both',
|
784
|
+
questionOptions: {
|
785
|
+
rendering: 'datetime',
|
786
|
+
},
|
787
|
+
meta: {
|
788
|
+
previousValue: {
|
789
|
+
value: '2024-04-01T19:50:00.000+0000',
|
790
|
+
},
|
791
|
+
},
|
792
|
+
} as any as FormField;
|
793
|
+
expect(hasPreviousObsValueChanged(dateTimeField, new Date('2024-04-01T19:50:00.000+0000'))).toBe(false);
|
794
|
+
expect(hasPreviousObsValueChanged(dateTimeField, new Date('2024-04-01T19:40:40.000+0000'))).toBe(true);
|
795
|
+
});
|
796
|
+
it('should support free text', () => {
|
797
|
+
const textField = {
|
798
|
+
questionOptions: {
|
799
|
+
rendering: 'text',
|
800
|
+
},
|
801
|
+
meta: {
|
802
|
+
previousValue: {
|
803
|
+
value: 'Text value',
|
804
|
+
},
|
805
|
+
},
|
806
|
+
} as any as FormField;
|
807
|
+
expect(hasPreviousObsValueChanged(textField, 'Text value')).toBe(false);
|
808
|
+
expect(hasPreviousObsValueChanged(textField, 'Edited')).toBe(true);
|
809
|
+
});
|
810
|
+
});
|
811
|
+
|
812
|
+
describe('findObsByFormField', () => {
|
813
|
+
const namespace = 'rfe-forms';
|
814
|
+
const fields: Array<FormField> = [
|
815
|
+
{
|
816
|
+
label: 'Field One',
|
817
|
+
type: 'obs',
|
818
|
+
questionOptions: {
|
819
|
+
rendering: 'select',
|
820
|
+
concept: '8c3db896-c1f0-11eb-8529-0242acv30003',
|
821
|
+
},
|
822
|
+
id: 'fieldOne',
|
823
|
+
},
|
824
|
+
{
|
825
|
+
label: 'Field two',
|
826
|
+
type: 'obs',
|
827
|
+
questionOptions: {
|
828
|
+
rendering: 'select',
|
829
|
+
concept: '8c3db896-c1f0-11eb-8529-0242acv30003',
|
830
|
+
},
|
831
|
+
id: 'fieldTwo',
|
832
|
+
},
|
833
|
+
{
|
834
|
+
label: 'Field three',
|
835
|
+
type: 'obs',
|
836
|
+
questionOptions: {
|
837
|
+
rendering: 'select',
|
838
|
+
concept: 'mc3db896-c4f0-11eb-8529-0242acv3000c',
|
839
|
+
},
|
840
|
+
id: 'fieldThree',
|
841
|
+
},
|
842
|
+
{
|
843
|
+
label: 'Field four',
|
844
|
+
type: 'obs',
|
845
|
+
questionOptions: {
|
846
|
+
rendering: 'select',
|
847
|
+
concept: 'mc3db896-c4f0-11eb-8529-0242acv3000c',
|
848
|
+
},
|
849
|
+
id: 'fieldFour',
|
850
|
+
},
|
851
|
+
];
|
852
|
+
|
853
|
+
const obsList: Array<any> = [
|
854
|
+
{
|
855
|
+
uuid: '6449d61a-7841-4aaf-a956-e6b1bd731385',
|
856
|
+
concept: {
|
857
|
+
uuid: '8c3db896-c1f0-11eb-8529-0242acv30003',
|
858
|
+
},
|
859
|
+
formFieldNamespace: namespace,
|
860
|
+
formFieldPath: 'rfe-forms-fieldOne',
|
861
|
+
},
|
862
|
+
{
|
863
|
+
uuid: '1449d61a-78b1-4aaf-a956-e6b1bd73138f',
|
864
|
+
concept: {
|
865
|
+
uuid: 'mc3db896-c4f0-11eb-8529-0242acv3000c',
|
866
|
+
},
|
867
|
+
formFieldNamespace: namespace,
|
868
|
+
formFieldPath: 'rfe-forms-fieldThree',
|
869
|
+
},
|
870
|
+
{
|
871
|
+
uuid: '8449d61a-5841-4aaf-a956-e6b1bd73138b',
|
872
|
+
concept: {
|
873
|
+
uuid: '8c3db896-c1f0-11eb-8529-0242acv30003',
|
874
|
+
},
|
875
|
+
formFieldNamespace: namespace,
|
876
|
+
formFieldPath: 'rfe-forms-fieldTwo',
|
877
|
+
},
|
878
|
+
{
|
879
|
+
uuid: '5449d61a-4841-4aaf-a956-26b1bd73138b',
|
880
|
+
concept: {
|
881
|
+
uuid: 'mc3db896-c4f0-11eb-8529-0242acv3000c',
|
882
|
+
},
|
883
|
+
formFieldNamespace: 'some-random-namespace',
|
884
|
+
formFieldPath: 'none-existing-pathname',
|
885
|
+
},
|
886
|
+
];
|
887
|
+
|
888
|
+
it('Should find observation by field path', () => {
|
889
|
+
// do find
|
890
|
+
let matchedObs = findObsByFormField(obsList, [], fields[0]);
|
891
|
+
// verify
|
892
|
+
expect(matchedObs.length).toBe(1);
|
893
|
+
expect(matchedObs[0]).toBe(obsList[0]);
|
894
|
+
// replay
|
895
|
+
matchedObs = findObsByFormField(obsList, [], fields[1]);
|
896
|
+
// verify
|
897
|
+
expect(matchedObs.length).toBe(1);
|
898
|
+
expect(matchedObs[0]).toBe(obsList[2]);
|
899
|
+
});
|
900
|
+
|
901
|
+
it('Should fallback to mapping by concept if no obs was found by fieldpath', () => {
|
902
|
+
// do find
|
903
|
+
const matchedObs = findObsByFormField(obsList, [obsList[1].uuid], fields[3]);
|
904
|
+
// verify
|
905
|
+
expect(matchedObs.length).toBe(1);
|
906
|
+
expect(matchedObs[0]).toBe(obsList[3]);
|
907
|
+
});
|
908
|
+
});
|
@@ -162,15 +162,17 @@ describe('Text field input', () => {
|
|
162
162
|
await renderForm(textValues);
|
163
163
|
const inputField = screen.getByLabelText('Indicate your notes');
|
164
164
|
|
165
|
-
await user.type(inputField, 'Updated patient
|
166
|
-
|
167
|
-
|
168
|
-
expect.
|
169
|
-
|
170
|
-
|
165
|
+
await user.type(inputField, 'Updated patient notes');
|
166
|
+
|
167
|
+
await act(async () => {
|
168
|
+
expect(mockSetFieldValue).toHaveBeenCalledWith(
|
169
|
+
expect.objectContaining({
|
170
|
+
target: expect.objectContaining({
|
171
|
+
value: 'Updated patient notes',
|
172
|
+
}),
|
171
173
|
}),
|
172
|
-
|
173
|
-
);
|
174
|
+
);
|
175
|
+
});
|
174
176
|
});
|
175
177
|
|
176
178
|
it('should have value passed in as prop', async () => {
|
@@ -127,9 +127,18 @@ export const FormFactoryProvider: React.FC<FormFactoryProviderProps> = ({
|
|
127
127
|
handleClose();
|
128
128
|
}
|
129
129
|
})
|
130
|
-
.catch((
|
130
|
+
.catch((errorObject: Error | ToastDescriptor) => {
|
131
131
|
setIsSubmitting(false);
|
132
|
-
|
132
|
+
if (errorObject instanceof Error) {
|
133
|
+
showToast({
|
134
|
+
title: t('errorProcessingFormSubmission', 'Error processing form submission'),
|
135
|
+
kind: 'error',
|
136
|
+
description: errorObject.message,
|
137
|
+
critical: true,
|
138
|
+
});
|
139
|
+
} else {
|
140
|
+
showToast(errorObject);
|
141
|
+
}
|
133
142
|
});
|
134
143
|
} else {
|
135
144
|
setIsSubmitting(false);
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|