@aehrc/smart-forms-renderer 0.27.4 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.swcrc +2 -2
  2. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.d.ts +1 -0
  3. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js +12 -2
  4. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js.map +1 -1
  5. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js +5 -2
  6. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js.map +1 -1
  7. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.d.ts +1 -0
  8. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js +3 -3
  9. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js.map +1 -1
  10. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.d.ts +1 -0
  11. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +12 -2
  12. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
  13. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js +5 -2
  14. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js.map +1 -1
  15. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js +4 -1
  16. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js.map +1 -1
  17. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.d.ts +1 -0
  18. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js +1 -1
  19. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js.map +1 -1
  20. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/DateTimeField.d.ts +2 -1
  21. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/DateTimeField.js.map +1 -1
  22. package/lib/components/FormComponents/DecimalItem/DecimalItem.js +3 -1
  23. package/lib/components/FormComponents/DecimalItem/DecimalItem.js.map +1 -1
  24. package/lib/hooks/useValidationFeedback.js +1 -1
  25. package/lib/utils/validateQuestionnaire.js.map +1 -1
  26. package/package.json +6 -3
  27. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.tsx +28 -1
  28. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.tsx +6 -0
  29. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.tsx +5 -1
  30. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +20 -1
  31. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.tsx +6 -0
  32. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.tsx +5 -0
  33. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.tsx +3 -1
  34. package/src/components/FormComponents/DateTimeItems/CustomDateTimeItem/DateTimeField.tsx +2 -1
  35. package/src/components/FormComponents/DecimalItem/DecimalItem.tsx +15 -12
  36. package/src/hooks/useValidationFeedback.ts +1 -1
  37. package/src/stories/assets/questionnaires/QAdvancedAdditionalDisplayContent.ts +30 -0
  38. package/src/stories/assets/questionnaires/QAdvancedOther.ts +1 -2
  39. package/src/stories/assets/questionnaires/QAdvancedTextApperance.ts +28 -0
  40. package/src/stories/assets/questionnaires/QBehaviorValueConstraints.ts +1 -1
  41. package/src/stories/assets/questionnaires/QBoolean.ts +1 -1
  42. package/src/stories/assets/questionnaires/QChoice.ts +357 -1
  43. package/src/stories/assets/questionnaires/QDate.ts +1 -1
  44. package/src/stories/assets/questionnaires/QDateTime.ts +1 -1
  45. package/src/stories/assets/questionnaires/QDecimal.ts +1 -1
  46. package/src/stories/assets/questionnaires/QInteger.ts +1 -1
  47. package/src/stories/assets/questionnaires/QItemControlDisplay.ts +460 -17
  48. package/src/stories/assets/questionnaires/QItemControlGroup.ts +220 -6
  49. package/src/stories/assets/questionnaires/QOpenChoice.ts +1 -1
  50. package/src/stories/assets/questionnaires/QQuantity.ts +6 -0
  51. package/src/stories/assets/questionnaires/QString.ts +1 -1
  52. package/src/stories/assets/questionnaires/QText.ts +2 -2
  53. package/src/stories/itemTypes/Boolean.stories.tsx +0 -17
  54. package/src/stories/itemTypes/Choice.stories.tsx +15 -0
  55. package/src/stories/itemTypes/Url.stories.tsx +2 -2
  56. package/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx +7 -1
  57. package/src/stories/sdc/AdvancedTextAppearance.stories.tsx +7 -0
  58. package/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx +1 -1
  59. package/src/stories/sdc/ItemControlDisplay.stories.tsx +31 -1
  60. package/src/stories/sdc/ItemControlGroup.stories.tsx +10 -3
  61. package/src/tests/enableWhen.test.ts +112 -0
  62. package/src/tests/test-data/enable-when-items-sample.json +3848 -0
  63. package/src/tests/test-data/initial-answers-sample.json +16 -0
  64. package/src/tests/test-data/linked-questions-map.json +217 -0
  65. package/src/tests/test-data/questionnaire-response-sample.json +650 -0
  66. package/src/utils/validateQuestionnaire.ts +18 -6
@@ -224,17 +224,16 @@ export const qItemControlGroupGTable: Questionnaire = {
224
224
  ]
225
225
  };
226
226
 
227
- // FIXME at the moment, itemControl grid does not work without a parent container
228
- export const qItemControlGroupGrid: Questionnaire = {
227
+ export const qItemControlGroupGridSingleRow: Questionnaire = {
229
228
  resourceType: 'Questionnaire',
230
- id: 'ItemControlGroupGrid',
231
- name: 'ItemControlGroupGrid',
232
- title: 'Item Control Group Grid',
229
+ id: 'ItemControlGroupGridSingleRow',
230
+ name: 'ItemControlGroupGridSingleRow',
231
+ title: 'Item Control Group Grid - Single Row',
233
232
  version: '0.1.0',
234
233
  status: 'draft',
235
234
  publisher: 'AEHRC CSIRO',
236
235
  date: '2024-05-01',
237
- url: 'https://smartforms.csiro.au/docs/advanced/control/item-control-group-grid',
236
+ url: 'https://smartforms.csiro.au/docs/advanced/control/item-control-group-grid-1',
238
237
  item: [
239
238
  {
240
239
  linkId: 'parent-container',
@@ -313,6 +312,221 @@ export const qItemControlGroupGrid: Questionnaire = {
313
312
  ]
314
313
  };
315
314
 
315
+ export const qItemControlGroupGridMultiRow: Questionnaire = {
316
+ resourceType: 'Questionnaire',
317
+ id: 'ItemControlGroupGridMultiRow',
318
+ name: 'ItemControlGroupGridMultiRow',
319
+ title: 'Item Control Group Grid - Multi Row',
320
+ version: '0.1.0',
321
+ status: 'draft',
322
+ publisher: 'AEHRC CSIRO',
323
+ date: '2024-05-01',
324
+ url: 'https://smartforms.csiro.au/docs/advanced/control/item-control-group-grid-2',
325
+ item: [
326
+ {
327
+ linkId: 'parent-container',
328
+ text: '',
329
+ type: 'group',
330
+ repeats: false,
331
+ item: [
332
+ {
333
+ extension: [
334
+ {
335
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl',
336
+ valueCodeableConcept: {
337
+ coding: [
338
+ {
339
+ system: 'http://hl7.org/fhir/questionnaire-item-control',
340
+ version: '1.0.0',
341
+ code: 'grid'
342
+ }
343
+ ]
344
+ }
345
+ }
346
+ ],
347
+ linkId: 'grid-group',
348
+ type: 'group',
349
+ repeats: false,
350
+ item: [
351
+ {
352
+ linkId: 'height-row',
353
+ text: 'Height',
354
+ type: 'group',
355
+ repeats: false,
356
+ item: [
357
+ {
358
+ extension: [
359
+ {
360
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit',
361
+ valueCoding: {
362
+ system: 'http://unitsofmeasure.org',
363
+ code: 'cm',
364
+ display: 'cm'
365
+ }
366
+ }
367
+ ],
368
+ linkId: 'height-value',
369
+ text: 'Value',
370
+ type: 'decimal',
371
+ repeats: false
372
+ },
373
+ {
374
+ linkId: 'height-date-performed',
375
+ text: 'Date performed',
376
+ type: 'date',
377
+ repeats: false
378
+ }
379
+ ]
380
+ },
381
+ {
382
+ linkId: 'weight-row',
383
+ text: 'Weight',
384
+ type: 'group',
385
+ repeats: false,
386
+ item: [
387
+ {
388
+ extension: [
389
+ {
390
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit',
391
+ valueCoding: {
392
+ system: 'http://unitsofmeasure.org',
393
+ code: 'kg',
394
+ display: 'kg'
395
+ }
396
+ }
397
+ ],
398
+ linkId: 'weight-value',
399
+ text: 'Value',
400
+ type: 'decimal',
401
+ repeats: false
402
+ },
403
+ {
404
+ linkId: 'weight-date-performed',
405
+ text: 'Date performed',
406
+ type: 'date',
407
+ repeats: false
408
+ }
409
+ ]
410
+ },
411
+ {
412
+ linkId: 'bmi-row',
413
+ text: 'BMI',
414
+ type: 'group',
415
+ repeats: false,
416
+ item: [
417
+ {
418
+ extension: [
419
+ {
420
+ url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression',
421
+ valueExpression: {
422
+ description: 'BMI calculation',
423
+ language: 'text/fhirpath',
424
+ expression: '(%weight/((%height/100).power(2))).round(1)'
425
+ }
426
+ },
427
+ {
428
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit',
429
+ valueCoding: {
430
+ system: 'http://unitsofmeasure.org',
431
+ code: 'kg/m2',
432
+ display: 'kg/m2'
433
+ }
434
+ }
435
+ ],
436
+ linkId: 'bmi-value',
437
+ text: 'Value',
438
+ type: 'decimal',
439
+ repeats: false,
440
+ readOnly: false
441
+ }
442
+ ]
443
+ },
444
+ {
445
+ linkId: 'heart-rate-row',
446
+ text: 'Heart rate',
447
+ type: 'group',
448
+ repeats: false,
449
+ item: [
450
+ {
451
+ extension: [
452
+ {
453
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit',
454
+ valueCoding: {
455
+ system: 'http://unitsofmeasure.org',
456
+ code: '/min',
457
+ display: '/min'
458
+ }
459
+ }
460
+ ],
461
+ linkId: 'heart-rate-value',
462
+ text: 'Value',
463
+ type: 'integer',
464
+ repeats: false
465
+ },
466
+ {
467
+ linkId: 'heart-rate-date-performed',
468
+ text: 'Date performed',
469
+ type: 'date',
470
+ repeats: false
471
+ }
472
+ ]
473
+ },
474
+ {
475
+ linkId: 'heart-rhythm-row',
476
+ text: 'Heart rhythm',
477
+ type: 'group',
478
+ repeats: false,
479
+ item: [
480
+ {
481
+ extension: [
482
+ {
483
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl',
484
+ valueCodeableConcept: {
485
+ coding: [
486
+ {
487
+ system: 'http://hl7.org/fhir/questionnaire-item-control',
488
+ code: 'radio-button'
489
+ }
490
+ ]
491
+ }
492
+ }
493
+ ],
494
+ linkId: 'heart-rhythm-value',
495
+ text: 'Value',
496
+ type: 'choice',
497
+ repeats: false,
498
+ answerOption: [
499
+ {
500
+ valueCoding: {
501
+ system: 'http://snomed.info/sct',
502
+ code: '271636001',
503
+ display: 'Pulse regular'
504
+ }
505
+ },
506
+ {
507
+ valueCoding: {
508
+ system: 'http://snomed.info/sct',
509
+ code: '61086009',
510
+ display: 'Pulse irregular'
511
+ }
512
+ }
513
+ ]
514
+ },
515
+ {
516
+ linkId: 'heart-rhythm-date-performed',
517
+ text: 'Date performed',
518
+ type: 'date',
519
+ repeats: false
520
+ }
521
+ ]
522
+ }
523
+ ]
524
+ }
525
+ ]
526
+ }
527
+ ]
528
+ };
529
+
316
530
  export const qItemControlDisplayTabContainer: Questionnaire = {
317
531
  resourceType: 'Questionnaire',
318
532
  id: 'ItemControlGroupTabContainer',
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- import { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
18
+ import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
19
19
 
20
20
  export const qOpenChoiceAnswerOptionBasic: Questionnaire = {
21
21
  resourceType: 'Questionnaire',
@@ -29,6 +29,12 @@ export const qQuantityBasic: Questionnaire = {
29
29
  url: 'https://smartforms.csiro.au/docs/components/quantity/basic',
30
30
  item: [
31
31
  {
32
+ extension: [
33
+ {
34
+ url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit',
35
+ valueCoding: { system: 'http://unitsofmeasure.org', code: 'kg', display: 'kg' }
36
+ }
37
+ ],
32
38
  linkId: 'body-weight',
33
39
  type: 'quantity',
34
40
  repeats: false,
@@ -16,7 +16,7 @@
16
16
  */
17
17
 
18
18
  import type { Questionnaire } from 'fhir/r4';
19
- import { QuestionnaireResponse } from 'fhir/r4';
19
+ import type { QuestionnaireResponse } from 'fhir/r4';
20
20
 
21
21
  export const qStringBasic: Questionnaire = {
22
22
  resourceType: 'Questionnaire',
@@ -16,7 +16,7 @@
16
16
  */
17
17
 
18
18
  import type { Questionnaire } from 'fhir/r4';
19
- import { QuestionnaireResponse } from 'fhir/r4';
19
+ import type { QuestionnaireResponse } from 'fhir/r4';
20
20
 
21
21
  export const qTextBasic: Questionnaire = {
22
22
  resourceType: 'Questionnaire',
@@ -48,7 +48,7 @@ export const qrTextBasicResponse: QuestionnaireResponse = {
48
48
  answer: [
49
49
  {
50
50
  valueString:
51
- '- 8 hour eating window\n- cup of black coffee in the morning\n- small portions of lunch and dinner'
51
+ '- 8 hour eating window\n- Cup of black coffee in the morning\n- Small portions of lunch and dinner'
52
52
  }
53
53
  ]
54
54
  }
@@ -15,23 +15,6 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- /*
19
- * Copyright 2024 Commonwealth Scientific and Industrial Research
20
- * Organisation (CSIRO) ABN 41 687 119 230.
21
- *
22
- * Licensed under the Apache License, Version 2.0 (the "License");
23
- * you may not use this file except in compliance with the License.
24
- * You may obtain a copy of the License at
25
- *
26
- * http://www.apache.org/licenses/LICENSE-2.0
27
- *
28
- * Unless required by applicable law or agreed to in writing, software
29
- * distributed under the License is distributed on an "AS IS" BASIS,
30
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31
- * See the License for the specific language governing permissions and
32
- * limitations under the License.
33
- */
34
-
35
18
  import type { Meta, StoryObj } from '@storybook/react';
36
19
  import {
37
20
  qBooleanBasic,
@@ -19,7 +19,9 @@ import type { Meta, StoryObj } from '@storybook/react';
19
19
  import BuildFormWrapper from '../BuildFormWrapper';
20
20
  import {
21
21
  qChoiceAnswerOptionBasic,
22
+ qChoiceAnswerOptionCalculation,
22
23
  qChoiceAnswerValueSetBasic,
24
+ qChoiceAnswerValueSetCalculation,
23
25
  qrChoiceAnswerOptionBasicResponse,
24
26
  qrChoiceAnswerValueSetBasicResponse
25
27
  } from '../assets/questionnaires';
@@ -42,6 +44,7 @@ export const ChoiceAnswerOptionBasic: Story = {
42
44
  questionnaire: qChoiceAnswerOptionBasic
43
45
  }
44
46
  };
47
+
45
48
  export const ChoiceAnswerOptionBasicResponse: Story = {
46
49
  args: {
47
50
  questionnaire: qChoiceAnswerOptionBasic,
@@ -61,3 +64,15 @@ export const ChoiceAnswerValueSetBasicResponse: Story = {
61
64
  questionnaireResponse: qrChoiceAnswerValueSetBasicResponse
62
65
  }
63
66
  };
67
+
68
+ export const ChoiceAnswerOptionCalculation: Story = {
69
+ args: {
70
+ questionnaire: qChoiceAnswerOptionCalculation
71
+ }
72
+ };
73
+
74
+ export const ChoiceAnswerValueSetCalculation: Story = {
75
+ args: {
76
+ questionnaire: qChoiceAnswerValueSetCalculation
77
+ }
78
+ };
@@ -17,7 +17,7 @@
17
17
 
18
18
  import type { Meta, StoryObj } from '@storybook/react';
19
19
  import BuildFormWrapper from '../BuildFormWrapper';
20
- import { qStringBasic } from '../assets/questionnaires';
20
+ import { qUrlBasic } from '../assets/questionnaires';
21
21
 
22
22
  // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
23
23
  const meta = {
@@ -34,6 +34,6 @@ type Story = StoryObj<typeof meta>;
34
34
 
35
35
  export const UrlBasic: Story = {
36
36
  args: {
37
- questionnaire: qStringBasic
37
+ questionnaire: qUrlBasic
38
38
  }
39
39
  };
@@ -17,7 +17,7 @@
17
17
 
18
18
  import type { Meta, StoryObj } from '@storybook/react';
19
19
  import BuildFormWrapper from '../BuildFormWrapper';
20
- import { qEntryFormat, qShortText } from '../assets/questionnaires';
20
+ import { qEntryFormat, qQuestionnaireUnit, qShortText } from '../assets/questionnaires';
21
21
 
22
22
  // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
23
23
  const meta = {
@@ -43,3 +43,9 @@ export const ShortText: Story = {
43
43
  questionnaire: qShortText
44
44
  }
45
45
  };
46
+
47
+ export const QuestionnaireUnit: Story = {
48
+ args: {
49
+ questionnaire: qQuestionnaireUnit
50
+ }
51
+ };
@@ -22,6 +22,7 @@ import {
22
22
  qHidden,
23
23
  qOpenLabel,
24
24
  qRenderingXhtmlBooleanCheckboxItem,
25
+ qRenderingXhtmlDisplayBase64ImageItem,
25
26
  qRenderingXhtmlDisplayListItem
26
27
  } from '../assets/questionnaires';
27
28
 
@@ -50,6 +51,12 @@ export const RenderingXHTMLDisplayList: Story = {
50
51
  }
51
52
  };
52
53
 
54
+ export const RenderingXHTMLDisplayBase64Image: Story = {
55
+ args: {
56
+ questionnaire: qRenderingXhtmlDisplayBase64ImageItem
57
+ }
58
+ };
59
+
53
60
  export const DisplayCategoryInstructions: Story = {
54
61
  args: {
55
62
  questionnaire: qDisplayCategoryInstructions
@@ -31,7 +31,7 @@ const meta = {
31
31
  title: 'Component/SDC/9.1.2 Form Behavior Choice Restriction',
32
32
  component: BuildFormWrapper,
33
33
  // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
34
- tags: ['autodocs']
34
+ tags: []
35
35
  } satisfies Meta<typeof BuildFormWrapper>;
36
36
 
37
37
  export default meta;
@@ -17,7 +17,13 @@
17
17
 
18
18
  import type { Meta, StoryObj } from '@storybook/react';
19
19
  import BuildFormWrapper from '../BuildFormWrapper';
20
- import { qItemControlDisplayLowerAndUpper } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
20
+ import {
21
+ qItemControlDisplayContextDisplay,
22
+ qItemControlDisplayFlyover,
23
+ qItemControlDisplayLowerAndUpper,
24
+ qItemControlDisplayPrompt,
25
+ qItemControlDisplayUnit
26
+ } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
21
27
 
22
28
  // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
23
29
  const meta = {
@@ -32,8 +38,32 @@ type Story = StoryObj<typeof meta>;
32
38
 
33
39
  // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
34
40
 
41
+ export const Prompt: Story = {
42
+ args: {
43
+ questionnaire: qItemControlDisplayPrompt
44
+ }
45
+ };
46
+
47
+ export const Unit: Story = {
48
+ args: {
49
+ questionnaire: qItemControlDisplayUnit
50
+ }
51
+ };
52
+
35
53
  export const LowerAndUpper: Story = {
36
54
  args: {
37
55
  questionnaire: qItemControlDisplayLowerAndUpper
38
56
  }
39
57
  };
58
+
59
+ export const Flyover: Story = {
60
+ args: {
61
+ questionnaire: qItemControlDisplayFlyover
62
+ }
63
+ };
64
+
65
+ export const CustomContextDisplay: Story = {
66
+ args: {
67
+ questionnaire: qItemControlDisplayContextDisplay
68
+ }
69
+ };
@@ -19,7 +19,8 @@ import type { Meta, StoryObj } from '@storybook/react';
19
19
  import BuildFormWrapper from '../BuildFormWrapper';
20
20
  import {
21
21
  qItemControlDisplayTabContainer,
22
- qItemControlGroupGrid,
22
+ qItemControlGroupGridMultiRow,
23
+ qItemControlGroupGridSingleRow,
23
24
  qItemControlGroupGTable
24
25
  } from '../assets/questionnaires';
25
26
 
@@ -42,9 +43,15 @@ export const Gtable: Story = {
42
43
  }
43
44
  };
44
45
 
45
- export const Grid: Story = {
46
+ export const GridSingleRow: Story = {
46
47
  args: {
47
- questionnaire: qItemControlGroupGrid
48
+ questionnaire: qItemControlGroupGridSingleRow
49
+ }
50
+ };
51
+
52
+ export const GridMultiRow: Story = {
53
+ args: {
54
+ questionnaire: qItemControlGroupGridMultiRow
48
55
  }
49
56
  };
50
57
 
@@ -0,0 +1,112 @@
1
+ /*
2
+ * Copyright 2024 Commonwealth Scientific and Industrial Research
3
+ * Organisation (CSIRO) ABN 41 687 119 230.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ // @ts-ignore
19
+ import enableWhenItemsSample from './test-data/enable-when-items-sample.json';
20
+ // @ts-ignore
21
+ import linkedQuestionsMapSample from './test-data/linked-questions-map.json';
22
+ // @ts-ignore
23
+ import questionnaireResponseSample from './test-data/questionnaire-response-sample.json';
24
+ // @ts-ignore
25
+ import initialAnswersSample from './test-data/initial-answers-sample.json';
26
+ import type { QuestionnaireResponse, QuestionnaireResponseItemAnswer } from 'fhir/r4';
27
+ import { describe, expect, test } from '@jest/globals';
28
+ import type { EnableWhenItems } from '../interfaces';
29
+ import { createEnableWhenLinkedQuestions, readInitialAnswers, setInitialAnswers } from '../utils';
30
+
31
+ describe('verify correctness of linked questions map created from enable when items', () => {
32
+ const enableWhenItems = enableWhenItemsSample as unknown as EnableWhenItems;
33
+
34
+ const linkedQuestionsMap = createEnableWhenLinkedQuestions(enableWhenItems);
35
+ const linkedQuestionsOfAge = linkedQuestionsMap['e2a16e4d-2765-4b61-b286-82cfc6356b30'];
36
+
37
+ test('linked questions of Age question should return 147 linkIds', () => {
38
+ expect(linkedQuestionsOfAge.length).toEqual(147);
39
+ });
40
+
41
+ test('specifying age as key in linked questions map should return 2e82032a-dc28-45f2-916e-862303d39fe5 as the first value', () => {
42
+ expect(linkedQuestionsOfAge[0]).toEqual('2e82032a-dc28-45f2-916e-862303d39fe5');
43
+ });
44
+
45
+ test('specifying age as key in linked questions map should return 16971bd2-5494-483d-9713-eda182c47f02 as the last value', () => {
46
+ expect(linkedQuestionsOfAge[linkedQuestionsOfAge.length - 1]).toEqual(
47
+ '16971bd2-5494-483d-9713-eda182c47f02'
48
+ );
49
+ });
50
+
51
+ test('specifying c72933c7-349f-4fef-94ff-c424c69da6f3 as key in linked questions map should return b7d116f9-0425-4cf1-8cde-fbf4dfaee550 as the only value', () => {
52
+ const joinedLinkIds = linkedQuestionsMap['c72933c7-349f-4fef-94ff-c424c69da6f3'].join();
53
+ expect(joinedLinkIds).toEqual('b7d116f9-0425-4cf1-8cde-fbf4dfaee550');
54
+ });
55
+ });
56
+
57
+ describe('verify correctness of initial answers created from linked questions map', () => {
58
+ const linkedQuestionsMap = linkedQuestionsMapSample as Record<string, string[]>;
59
+ const questionnaireResponse = questionnaireResponseSample as QuestionnaireResponse;
60
+
61
+ const initialAnswers = readInitialAnswers(questionnaireResponse, linkedQuestionsMap);
62
+ const ageKey = 'e2a16e4d-2765-4b61-b286-82cfc6356b30';
63
+
64
+ test('specifying age as key in initial answers should return valueInteger of 86', () => {
65
+ const initialAnswer = initialAnswers[ageKey];
66
+ expect(initialAnswer[0].valueInteger).toBe(86);
67
+ });
68
+
69
+ test('specifying b639a3a8-f476-4cc8-b5c7-f5d2abb23511 as key in initial answers should return valueCoding with code 8517006', () => {
70
+ const initialAnswer = initialAnswers['b639a3a8-f476-4cc8-b5c7-f5d2abb23511'];
71
+ expect(initialAnswer[0].valueCoding?.code).toEqual('8517006');
72
+ });
73
+
74
+ test('specifying b639a3a8-f476-4cc8-b5c7-f5d2abb23511 as key in initial answers should return valueCoding with display Former smoker', () => {
75
+ const initialAnswer = initialAnswers['b639a3a8-f476-4cc8-b5c7-f5d2abb23511'];
76
+ expect(initialAnswer[0].valueCoding?.display).toEqual('Former smoker');
77
+ });
78
+ });
79
+
80
+ describe('update enable when items by setting initial answers', () => {
81
+ const enableWhenItems = enableWhenItemsSample as unknown as EnableWhenItems;
82
+ const linkedQuestionsMap = linkedQuestionsMapSample as Record<string, string[]>;
83
+ const initialAnswers = initialAnswersSample as Record<string, QuestionnaireResponseItemAnswer[]>;
84
+
85
+ test('passing an empty initial answers object should cause updated answers to be equal to enable when items', () => {
86
+ const updatedAnswers = setInitialAnswers({}, enableWhenItems, linkedQuestionsMap);
87
+ expect(updatedAnswers).toEqual(enableWhenItems);
88
+ });
89
+
90
+ test('passing an non-empty initial answers object should cause updated answers to be from enable when items', () => {
91
+ const updatedAnswers = setInitialAnswers(initialAnswers, enableWhenItems, linkedQuestionsMap);
92
+ expect(updatedAnswers).not.toEqual(enableWhenItems);
93
+ });
94
+
95
+ test('passing an initial answers object with age - valueInteger of 87 should result in a corresponding linked answer in object with linkId b7a9e23c-b875-4536-b72d-81d361c18e2c', () => {
96
+ const initialAnswers: Record<string, QuestionnaireResponseItemAnswer[]> = {
97
+ 'e2a16e4d-2765-4b61-b286-82cfc6356b30': [
98
+ {
99
+ valueInteger: 87
100
+ }
101
+ ]
102
+ };
103
+
104
+ const updatedAnswers = setInitialAnswers(initialAnswers, enableWhenItems, linkedQuestionsMap);
105
+ const objectWithLinkedAge = updatedAnswers.singleItems['c587e3b6-b91a-40dc-9a16-179342d001e9'];
106
+
107
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
108
+ const answer = objectWithLinkedAge.linked![0].answer!;
109
+
110
+ expect(answer[0].valueInteger).toBe(87);
111
+ });
112
+ });