@openmrs/esm-form-engine-lib 3.0.0-pre.1630 → 3.0.0-pre.1637

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.
@@ -1,137 +1,201 @@
1
1
  {
2
- "name": "ObsGroup Test Form",
3
- "version": "1",
4
- "published": true,
5
- "retired": false,
6
- "pages": [
7
- {
8
- "label": "Introduction",
9
- "sections": [
10
- {
11
- "label": "",
12
- "isExpanded": "true",
13
- "questions": [
14
- {
15
- "type": "markdown",
16
- "questionOptions": {
17
- "rendering": "markdown"
18
- },
19
- "id": "fooMarkdown",
20
- "value": [
21
- "**Use this form to:** Test Obs Group behaviour"
22
- ]
23
- }
24
- ]
25
- }
26
- ]
27
- },
28
- {
29
- "label": "Obs Group Page",
30
- "sections": [
31
- {
32
- "label": "Group Section",
33
- "isExpanded": "true",
34
- "questions": [
35
- {
36
- "id": "myGroup",
37
- "label": "My Group",
38
- "type": "obsGroup",
39
- "questionOptions": {
40
- "rendering": "repeating",
41
- "concept": "1c70c490-cafa-4c95-9fdd-a30b62bb78b8"
2
+ "name": "ObsGroup Test Form",
3
+ "version": "1",
4
+ "published": true,
5
+ "retired": false,
6
+ "pages": [
7
+ {
8
+ "label": "Obs Group Page",
9
+ "sections": [
10
+ {
11
+ "label": "Group Section",
12
+ "isExpanded": "true",
13
+ "questions": [
14
+ {
15
+ "id": "myGroup",
16
+ "label": "My Group",
17
+ "type": "obsGroup",
18
+ "questionOptions": {
19
+ "rendering": "repeating",
20
+ "concept": "1c70c490-cafa-4c95-9fdd-a30b62bb78b8"
21
+ },
22
+ "behaviours": [
23
+ {
24
+ "intent": "*",
25
+ "required": "false",
26
+ "unspecified": "false",
27
+ "hide": {
28
+ "hideWhenExpression": ""
29
+ },
30
+ "validators": []
31
+ }
32
+ ],
33
+ "questions": [
34
+ {
35
+ "label": "Sex",
36
+ "type": "obs",
37
+ "required": "true",
38
+ "questionOptions": {
39
+ "rendering": "radio",
40
+ "concept": "1587AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
41
+ "answers": [
42
+ {
43
+ "concept": "1535AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
44
+ "label": "Female"
45
+ },
46
+ {
47
+ "concept": "1534AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
48
+ "label": "Male"
49
+ }
50
+ ]
51
+ },
52
+ "id": "childSex",
53
+ "behaviours": [
54
+ {
55
+ "intent": "*",
56
+ "required": "true",
57
+ "unspecified": "true",
58
+ "hide": {
59
+ "hideWhenExpression": "false"
60
+ },
61
+ "validators": []
62
+ }
63
+ ]
42
64
  },
43
- "behaviours":[
44
- {
45
- "intent":"*",
46
- "required":"false",
47
- "unspecified":"false",
48
- "hide":{
49
- "hideWhenExpression":""
50
- },
51
- "validators":[]
52
- }
53
- ],
54
- "questions": [
55
- {
56
- "label": "Sex",
57
- "type":"obs",
58
- "required":"true",
59
- "questionOptions":{
60
- "rendering":"radio",
61
- "concept":"1587AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
62
- "answers":[
65
+ {
66
+ "label": "Date of Birth",
67
+ "type": "obs",
68
+ "questionOptions": {
69
+ "rendering": "date",
70
+ "concept": "164802AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
71
+ "weeksList": ""
72
+ },
73
+ "id": "birthDate",
74
+ "behaviours": [
75
+ {
76
+ "intent": "*",
77
+ "required": "true",
78
+ "unspecified": "true",
79
+ "hide": {
80
+ "hideWhenExpression": "false"
81
+ },
82
+ "validators": [
63
83
  {
64
- "concept":"1535AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
65
- "label":"Female"
84
+ "type": "date",
85
+ "allowFutureDates": "false"
66
86
  },
67
87
  {
68
- "concept":"1534AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
69
- "label":"Male"
88
+ "type": "js_expression",
89
+ "failsWhenExpression": "!isDateEqualTo(myValue, useFieldValue('visit_date'))",
90
+ "message": "Child birth date should be the same as the visit date!"
70
91
  }
71
92
  ]
72
- },
73
- "id":"childSex",
74
- "behaviours":[
75
- {
76
- "intent":"*",
77
- "required":"true",
78
- "unspecified":"true",
79
- "hide":{
80
- "hideWhenExpression":"false"
81
- },
82
- "validators":[]
83
- }
84
- ]
93
+ }
94
+ ]
95
+ }
96
+ ]
97
+ }
98
+ ]
99
+ },
100
+ {
101
+ "label": "Screening Section",
102
+ "questions": [
103
+ {
104
+ "label": "Do you have dependents?",
105
+ "id": "hasDependents",
106
+ "type": "obs",
107
+ "questionOptions": {
108
+ "rendering": "radio",
109
+ "concept": "a89e3f94-1350-11df-a1f1-0026b9348837",
110
+ "answers": [
111
+ {
112
+ "concept": "a89ce50e-1350-11df-a1f1-0026b9348839",
113
+ "label": "Yes"
85
114
  },
86
115
  {
87
- "label": "Date of Birth",
88
- "type": "obs",
89
- "questionOptions": {
90
- "rendering": "date",
91
- "concept": "164802AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
92
- "weeksList": ""
93
- },
94
- "id": "birthDate",
95
- "behaviours": [
116
+ "concept": "a89ce50e-1350-11df-a1f1-0026b9348838",
117
+ "label": "No"
118
+ }
119
+ ]
120
+ }
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ "label": "Groups with Hide logic",
126
+ "questions": [
127
+ {
128
+ "type": "obsGroup",
129
+ "label": "Dependents Group",
130
+ "id": "dependentGroup",
131
+ "questionOptions": {
132
+ "concept": "3665d0ef-3718-47b2-9091-8b685bda412d",
133
+ "rendering": "group"
134
+ },
135
+ "questions": [
136
+ {
137
+ "label": "Dependent Type",
138
+ "id": "dependentType",
139
+ "type": "obs",
140
+ "questionOptions": {
141
+ "rendering": "radio",
142
+ "concept": "a89e3f94-1350-11df-a1f1-0026b9348838",
143
+ "answers": [
96
144
  {
97
- "intent": "*",
98
- "required": "true",
99
- "unspecified": "true",
100
- "hide": {
101
- "hideWhenExpression": "false"
102
- },
103
- "validators": [
104
- {
105
- "type": "date",
106
- "allowFutureDates": "false"
107
- },
108
- {
109
- "type": "js_expression",
110
- "failsWhenExpression": "!isDateEqualTo(myValue, useFieldValue('visit_date'))",
111
- "message": "Child birth date should be the same as the visit date!"
112
- }
113
- ]
145
+ "concept": "6daff4ce-bce7-41f5-9141-17e694155180",
146
+ "label": "Child"
147
+ },
148
+ {
149
+ "concept": "a89ce50e-1350-11df-a1f1-0026b9348838",
150
+ "label": "Spouse"
114
151
  }
115
152
  ]
153
+ },
154
+ "hide": {
155
+ "hideWhenExpression": "hasDependents !== 'a89ce50e-1350-11df-a1f1-0026b9348839'"
116
156
  }
117
- ]
118
- }
119
- ]
120
- }
121
- ]
122
- }
123
- ],
124
- "availableIntents": [
125
- {
126
- "intent": "*",
127
- "display": "ObsGroup Test Form"
128
- }
129
- ],
130
- "processor": "EncounterFormProcessor",
131
- "uuid": "8f713e0e-94a0-3c57-9024-69520933802a",
132
- "referencedForms": [],
133
- "encounterType": "7e54cd64-f9c3-11eb-8e6a-57478ce139b0",
134
- "encounter": "Obs Group Test",
135
- "allowUnspecifiedAll": true
136
- }
137
-
157
+ },
158
+ {
159
+ "label": "Dependent Name",
160
+ "id": "dependentName",
161
+ "type": "obs",
162
+ "questionOptions": {
163
+ "rendering": "text",
164
+ "concept": "a8a06fc6-1350-11df-a1f1-0026b9348838"
165
+ },
166
+ "hide": {
167
+ "hideWhenExpression": "isEmpty(dependentType)"
168
+ }
169
+ },
170
+ {
171
+ "label": "Dependent Age",
172
+ "id": "dependentAge",
173
+ "type": "obs",
174
+ "questionOptions": {
175
+ "rendering": "number",
176
+ "concept": "a8a06fc6-1350-11df-a1f1-0026b9348839"
177
+ },
178
+ "hide": {
179
+ "hideWhenExpression": "dependentType !== '6daff4ce-bce7-41f5-9141-17e694155180'"
180
+ }
181
+ }
182
+ ]
183
+ }
184
+ ]
185
+ }
186
+ ]
187
+ }
188
+ ],
189
+ "availableIntents": [
190
+ {
191
+ "intent": "*",
192
+ "display": "ObsGroup Test Form"
193
+ }
194
+ ],
195
+ "processor": "EncounterFormProcessor",
196
+ "uuid": "8f713e0e-94a0-3c57-9024-69520933802a",
197
+ "referencedForms": [],
198
+ "encounterType": "7e54cd64-f9c3-11eb-8e6a-57478ce139b0",
199
+ "encounter": "Obs Group Test",
200
+ "allowUnspecifiedAll": true
201
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-form-engine-lib",
3
- "version": "3.0.0-pre.1630",
3
+ "version": "3.0.0-pre.1637",
4
4
  "description": "React Form Engine for O3",
5
5
  "browser": "dist/openmrs-esm-form-engine-lib.js",
6
6
  "main": "src/index.ts",
@@ -9,13 +9,13 @@ import { useTranslation } from 'react-i18next';
9
9
 
10
10
  export const ObsGroup: React.FC<FormFieldInputProps> = ({ field, ...restProps }) => {
11
11
  const { t } = useTranslation();
12
- const { formFieldAdapters } = useFormProviderContext();
13
- const showLabel = useMemo(() => field.questions?.length > 1, [field]);
12
+ const { formFieldAdapters, formFields } = useFormProviderContext();
14
13
 
15
14
  const content = useMemo(
16
15
  () =>
17
16
  field.questions
18
- ?.filter((child) => !child.isHidden)
17
+ .map((child) => formFields.find((field) => field.id === child.id))
18
+ .filter((child) => !child.isHidden)
19
19
  .map((child, index) => {
20
20
  const key = `${child.id}_${index}`;
21
21
 
@@ -35,12 +35,12 @@ export const ObsGroup: React.FC<FormFieldInputProps> = ({ field, ...restProps })
35
35
  );
36
36
  }
37
37
  }),
38
- [field],
38
+ [field, formFields],
39
39
  );
40
40
 
41
41
  return (
42
42
  <div className={styles.groupContainer}>
43
- {showLabel ? (
43
+ {content.length > 1 ? (
44
44
  <FormGroup legendText={t(field.label)} className={styles.boldLegend}>
45
45
  {content}
46
46
  </FormGroup>
@@ -113,7 +113,7 @@ const DateField: React.FC<FormFieldInputProps> = ({ field, value: dateValue, err
113
113
  id={field.id}
114
114
  labelText={timePickerLabel}
115
115
  placeholder="HH:MM"
116
- pattern="(1[012]|[1-9]):[0-5][0-9])$"
116
+ pattern="(1[012]|[1-9]):[0-5][0-9]$"
117
117
  type="time"
118
118
  disabled={field.datePickerFormat === 'timer' ? field.isDisabled : !dateValue ? true : false}
119
119
  invalid={errors.length > 0}
@@ -876,6 +876,50 @@ describe('Form engine component', () => {
876
876
  });
877
877
 
878
878
  describe('Obs group', () => {
879
+ it('should not render empty obs group', async () => {
880
+ await act(async () => {
881
+ renderForm(null, obsGroupTestForm);
882
+ });
883
+
884
+ // Check that only one obs group is initially rendered
885
+ const initialGroups = screen.getAllByRole('group', { name: /My Group|Dependents Group/i });
886
+ expect(initialGroups.length).toBe(1);
887
+ const dependentTypeRadios = screen.queryAllByRole('radio', { name: /child|spouse/i });
888
+ expect(dependentTypeRadios.length).toBe(0);
889
+
890
+ // Select "Yes" for having dependents
891
+ const yesRadio = screen.getByRole('radio', { name: /yes/i });
892
+ await user.click(yesRadio);
893
+
894
+ // Now the dependent type radios should be visible
895
+ const visibleDependentTypeRadios = screen.getAllByRole('radio', { name: /child|spouse/i });
896
+ expect(visibleDependentTypeRadios.length).toBe(2);
897
+
898
+ // Check that the group label is still hidden since it only has one visible field
899
+ const dependentsGroupResults = screen.queryAllByRole('group', { name: /Dependents Group/i });
900
+ expect(dependentsGroupResults.length).toBe(0);
901
+
902
+ // Check that dependent name and age are still hidden
903
+ const hiddenDependentNameInput = screen.queryByRole('textbox', { name: /dependent name/i });
904
+ const hiddenDependentAgeInput = screen.queryByRole('spinbutton', { name: /dependent age/i });
905
+ expect(hiddenDependentNameInput).toBeNull();
906
+ expect(hiddenDependentAgeInput).toBeNull();
907
+
908
+ // Select "Child" as dependent type
909
+ await user.click(visibleDependentTypeRadios[0]);
910
+
911
+ // Check the visibility of the group label
912
+ const dependentsGroup = screen.getAllByRole('group', { name: /Dependents Group/i })[0];
913
+ expect(dependentsGroup).toBeInTheDocument();
914
+
915
+ // Check that dependent name and age are now visible
916
+ const dependentNameInput = screen.getByRole('textbox', { name: /dependent name/i });
917
+ const dependentAgeInput = screen.getByRole('spinbutton', { name: /dependent age/i });
918
+
919
+ expect(dependentNameInput).toBeInTheDocument();
920
+ expect(dependentAgeInput).toBeInTheDocument();
921
+ });
922
+
879
923
  it('should save obs group on form submission', async () => {
880
924
  const saveEncounterMock = jest.spyOn(api, 'saveEncounter');
881
925
  await act(async () => {