@openmrs/esm-form-engine-lib 2.1.0-pre.1413 → 2.1.0-pre.1418

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.
@@ -0,0 +1,198 @@
1
+ {
2
+ "name": "A Radio Button Test",
3
+ "pages": [
4
+ {
5
+ "label": "Page 1",
6
+ "sections": [
7
+ {
8
+ "label": "1",
9
+ "isExpanded": "true",
10
+ "questions": [
11
+ {
12
+ "label": "Visit type",
13
+ "type": "obs",
14
+ "required": "false",
15
+ "id": "visitType",
16
+ "questionOptions": {
17
+ "rendering": "radio",
18
+ "concept": "164181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
19
+ "conceptMappings": [
20
+ {
21
+ "relationship": "SAME-AS",
22
+ "type": "CIEL",
23
+ "value": "164181"
24
+ }
25
+ ],
26
+ "answers": [
27
+ {
28
+ "concept": "164180AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
29
+ "label": "New visit"
30
+ },
31
+ {
32
+ "concept": "160530AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
33
+ "label": "Return visit type"
34
+ },
35
+ {
36
+ "concept": "5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
37
+ "label": "Other"
38
+ }
39
+ ]
40
+ },
41
+ "validators": [
42
+ {
43
+ "type": "form_field"
44
+ },
45
+ {
46
+ "type": "default_value"
47
+ }
48
+ ],
49
+ "meta": {
50
+ "submission": null,
51
+ "concept": {
52
+ "uuid": "164181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
53
+ "display": "Visit type",
54
+ "conceptClass": {
55
+ "uuid": "8d491e50-c2cc-11de-8d13-0010c6dffd0f",
56
+ "display": "Question"
57
+ },
58
+ "answers": [
59
+ {
60
+ "uuid": "164180AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
61
+ "display": "New visit"
62
+ },
63
+ {
64
+ "uuid": "160530AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
65
+ "display": "Return visit type"
66
+ },
67
+ {
68
+ "uuid": "5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
69
+ "display": "Other"
70
+ }
71
+ ],
72
+ "conceptMappings": [
73
+ {
74
+ "conceptReferenceTerm": {
75
+ "conceptSource": {
76
+ "name": "CIEL"
77
+ },
78
+ "code": "164181"
79
+ }
80
+ }
81
+ ]
82
+ }
83
+ },
84
+ "isHidden": false,
85
+ "isRequired": false,
86
+ "isDisabled": false
87
+ },
88
+ {
89
+ "label": "Visit punctuality",
90
+ "type": "obs",
91
+ "required": false,
92
+ "id": "visitPunctuality",
93
+ "questionOptions": {
94
+ "rendering": "radio",
95
+ "concept": "d81d4698-e78c-420d-aac5-cb1f606fb32e",
96
+ "answers": [
97
+ {
98
+ "concept": "5c3ce9c9-75bd-4730-8878-08c03ec02e9d",
99
+ "label": "Early"
100
+ },
101
+ {
102
+ "concept": "90af4b72-442a-4fcc-84c2-2bb1c0361737",
103
+ "label": "Late"
104
+ },
105
+ {
106
+ "concept": "66cdc0a1-aa19-4676-af51-80f66d78d9eb",
107
+ "label": "On time"
108
+ }
109
+ ]
110
+ },
111
+ "validators": [
112
+ {
113
+ "type": "form_field"
114
+ },
115
+ {
116
+ "type": "default_value"
117
+ }
118
+ ],
119
+ "meta": {
120
+ "submission": null,
121
+ "concept": {
122
+ "uuid": "d81d4698-e78c-420d-aac5-cb1f606fb32e",
123
+ "display": "Visit Punctuality",
124
+ "conceptClass": {
125
+ "uuid": "8d491e50-c2cc-11de-8d13-0010c6dffd0f",
126
+ "display": "Question"
127
+ },
128
+ "answers": [
129
+ {
130
+ "uuid": "66cdc0a1-aa19-4676-af51-80f66d78d9eb",
131
+ "display": "On time"
132
+ },
133
+ {
134
+ "uuid": "90af4b72-442a-4fcc-84c2-2bb1c0361737",
135
+ "display": "Late"
136
+ },
137
+ {
138
+ "uuid": "5c3ce9c9-75bd-4730-8878-08c03ec02e9d",
139
+ "display": "Early"
140
+ }
141
+ ],
142
+ "conceptMappings": []
143
+ }
144
+ },
145
+ "isHidden": false,
146
+ "isRequired": false,
147
+ "isDisabled": false
148
+ }
149
+ ],
150
+ "isHidden": false
151
+ }
152
+ ],
153
+ "isHidden": false
154
+ }
155
+ ],
156
+ "processor": "EncounterFormProcessor",
157
+ "encounterType": "0e8230ce-bd1d-43f5-a863-cf44344fa4b0",
158
+ "referencedForms": [],
159
+ "uuid": "fd067f44-99fd-4b07-b238-cea7b278c2b2",
160
+ "description": "A Radio Button Test",
161
+ "version": "1.0",
162
+ "translations": {},
163
+ "conceptReferences": {
164
+ "164181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {
165
+ "uuid": "164181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
166
+ "display": "Visit type"
167
+ },
168
+ "164180AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {
169
+ "uuid": "164180AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
170
+ "display": "New visit"
171
+ },
172
+ "160530AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {
173
+ "uuid": "160530AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
174
+ "display": "Return visit type"
175
+ },
176
+ "5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {
177
+ "uuid": "5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
178
+ "display": "Other"
179
+ },
180
+ "d81d4698-e78c-420d-aac5-cb1f606fb32e": {
181
+ "uuid": "d81d4698-e78c-420d-aac5-cb1f606fb32e",
182
+ "display": "Visit Punctuality"
183
+ },
184
+ "5c3ce9c9-75bd-4730-8878-08c03ec02e9d": {
185
+ "uuid": "5c3ce9c9-75bd-4730-8878-08c03ec02e9d",
186
+ "display": "Early"
187
+ },
188
+ "90af4b72-442a-4fcc-84c2-2bb1c0361737": {
189
+ "uuid": "90af4b72-442a-4fcc-84c2-2bb1c0361737",
190
+ "display": "Late"
191
+ },
192
+ "66cdc0a1-aa19-4676-af51-80f66d78d9eb": {
193
+ "uuid": "66cdc0a1-aa19-4676-af51-80f66d78d9eb",
194
+ "display": "On time"
195
+ }
196
+ },
197
+ "encounter": ""
198
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-form-engine-lib",
3
- "version": "2.1.0-pre.1413",
3
+ "version": "2.1.0-pre.1418",
4
4
  "description": "React Form Engine for O3",
5
5
  "browser": "dist/openmrs-esm-form-engine-lib.js",
6
6
  "main": "src/index.ts",
@@ -117,7 +117,7 @@ const MultiSelect: React.FC<FormFieldInputProps> = ({ field, value, errors, warn
117
117
  items={selectOptions}
118
118
  initialSelectedItems={initiallySelectedQuestionItems}
119
119
  label={''}
120
- titleText={label}
120
+ titleText={<FieldLabel field={field} />}
121
121
  key={counter}
122
122
  itemToString={(item) => (item ? item.label : ' ')}
123
123
  disabled={field.isDisabled}
@@ -37,7 +37,7 @@ const Radio: React.FC<FormFieldInputProps> = ({ field, value, errors, warnings,
37
37
  legendText={<FieldLabel field={field} />}
38
38
  className={styles.boldedLegend}
39
39
  disabled={field.isDisabled}
40
- invalid={errors.length > 0}>
40
+ invalid={errors?.length > 0}>
41
41
  <RadioButtonGroup
42
42
  name={field.id}
43
43
  valueSelected={value}
@@ -0,0 +1,198 @@
1
+ import React from 'react';
2
+ import { act, render, screen } from '@testing-library/react';
3
+ import { type FetchResponse, openmrsFetch, usePatient, useSession } from '@openmrs/esm-framework';
4
+ import { mockPatient } from '__mocks__/patient.mock';
5
+ import { mockSessionDataResponse } from '__mocks__/session.mock';
6
+ import { mockVisit } from '__mocks__/visit.mock';
7
+ import radioButtonFormSchema from '__mocks__/forms/rfe-forms/radio-button-form.json';
8
+ import Radio from './radio.component';
9
+ import { useFormProviderContext } from 'src/provider/form-provider';
10
+
11
+ const mockOpenmrsFetch = jest.mocked(openmrsFetch);
12
+ const mockUseSession = jest.mocked(useSession);
13
+ const mockUsePatient = jest.mocked(usePatient);
14
+
15
+ jest.mock('../../../api', () => {
16
+ const originalModule = jest.requireActual('../../../api');
17
+
18
+ return {
19
+ ...originalModule,
20
+ getPreviousEncounter: jest.fn().mockImplementation(() => Promise.resolve(null)),
21
+ };
22
+ });
23
+
24
+ jest.mock('src/provider/form-provider', () => ({
25
+ useFormProviderContext: jest.fn(),
26
+ }));
27
+
28
+ const mockUseFormProviderContext = useFormProviderContext as jest.Mock;
29
+
30
+ const addTestValues = {
31
+ field: {
32
+ label: 'Visit type',
33
+ type: 'obs',
34
+ required: false,
35
+ id: 'visitType',
36
+ questionOptions: {
37
+ rendering: 'radio',
38
+ concept: '164181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
39
+ conceptMappings: [
40
+ {
41
+ relationship: 'SAME-AS',
42
+ type: 'CIEL',
43
+ value: '164181',
44
+ },
45
+ ],
46
+ answers: [
47
+ {
48
+ concept: '164180AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
49
+ label: 'New visit',
50
+ },
51
+ {
52
+ concept: '160530AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
53
+ label: 'Return visit type',
54
+ },
55
+ {
56
+ concept: '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
57
+ label: 'Other',
58
+ },
59
+ ],
60
+ },
61
+ validators: [
62
+ {
63
+ type: 'form_field',
64
+ },
65
+ {
66
+ type: 'default_value',
67
+ },
68
+ ],
69
+ meta: {
70
+ submission: null,
71
+ concept: {
72
+ uuid: '164181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
73
+ display: 'Visit type',
74
+ conceptClass: {
75
+ uuid: '8d491e50-c2cc-11de-8d13-0010c6dffd0f',
76
+ display: 'Question',
77
+ },
78
+ answers: [
79
+ {
80
+ uuid: '164180AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
81
+ display: 'New visit',
82
+ },
83
+ {
84
+ uuid: '160530AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
85
+ display: 'Return visit type',
86
+ },
87
+ {
88
+ uuid: '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
89
+ display: 'Other',
90
+ },
91
+ ],
92
+ conceptMappings: [
93
+ {
94
+ conceptReferenceTerm: {
95
+ conceptSource: {
96
+ name: 'CIEL',
97
+ },
98
+ code: '164181',
99
+ },
100
+ },
101
+ ],
102
+ },
103
+ },
104
+ isHidden: false,
105
+ isRequired: false,
106
+ isDisabled: false,
107
+ },
108
+ value: null,
109
+ errors: null,
110
+ warnings: undefined,
111
+ setFieldValue: null,
112
+ };
113
+
114
+ const renderForm = async (props) => {
115
+ await act(() => render(<Radio {...props} />));
116
+ };
117
+
118
+ let formProcessor;
119
+
120
+ const mockProviderValues = {
121
+ layoutType: 'small-desktop',
122
+ sessionMode: 'enter',
123
+ workspaceLayout: 'minimized',
124
+ formFieldAdapters: {},
125
+ patient: mockPatient,
126
+ methods: undefined,
127
+ formJson: radioButtonFormSchema as any,
128
+ visit: mockVisit,
129
+ sessionDate: new Date(),
130
+ location: mockVisit.location,
131
+ currentProvider: mockVisit.encounters[0]?.encounterProvider,
132
+ processor: formProcessor,
133
+ };
134
+
135
+ describe('Radio Component', () => {
136
+ beforeEach(() => {
137
+ formProcessor = {
138
+ getInitialValues: jest.fn(),
139
+ };
140
+ mockOpenmrsFetch.mockResolvedValue({
141
+ data: { results: [{ ...radioButtonFormSchema }] },
142
+ } as unknown as FetchResponse);
143
+
144
+ mockUseSession.mockReturnValue(mockSessionDataResponse.data);
145
+
146
+ mockUsePatient.mockReturnValue({
147
+ isLoading: false,
148
+ patient: mockPatient,
149
+ patientUuid: mockPatient.id,
150
+ error: null,
151
+ });
152
+ });
153
+
154
+ it('renders correctly', async () => {
155
+ mockUseFormProviderContext.mockReturnValue({
156
+ ...mockProviderValues,
157
+ });
158
+
159
+ await renderForm(addTestValues);
160
+ expect(screen.getByText('Visit type')).toBeInTheDocument();
161
+ expect(screen.getByLabelText('New visit')).toBeInTheDocument();
162
+ expect(screen.getByLabelText('Return visit type')).toBeInTheDocument();
163
+ expect(screen.getByLabelText('Other')).toBeInTheDocument();
164
+
165
+ const radioButtons = screen.getAllByRole('radio');
166
+ expect(radioButtons).toHaveLength(3);
167
+ });
168
+
169
+ it('renders correctly on view mode', async () => {
170
+ mockUseFormProviderContext.mockReturnValue({
171
+ ...mockProviderValues,
172
+ sessionMode: 'view',
173
+ });
174
+
175
+ await renderForm(addTestValues);
176
+ expect(screen.getByRole('button', { name: /visit type/i })).toBeInTheDocument();
177
+ const visitTypeElements = screen.getAllByText('Visit type');
178
+ expect(visitTypeElements.length).toBeGreaterThan(0);
179
+ });
180
+
181
+ it('renders radio buttons as disabled when the field is disabled', async () => {
182
+ mockUseFormProviderContext.mockReturnValue({
183
+ ...mockProviderValues,
184
+ });
185
+
186
+ await renderForm({ ...addTestValues, field: { ...addTestValues.field, isDisabled: true } });
187
+ expect(screen.getByText('Visit type')).toBeInTheDocument();
188
+
189
+ const radioButtons = screen.getAllByRole('radio');
190
+ expect(radioButtons).toHaveLength(3);
191
+ radioButtons.forEach((radio) => {
192
+ expect(radio).toBeDisabled();
193
+ });
194
+ expect(screen.getByLabelText('New visit')).toBeDisabled();
195
+ expect(screen.getByLabelText('Return visit type')).toBeDisabled();
196
+ expect(screen.getByLabelText('Other')).toBeDisabled();
197
+ });
198
+ });
@@ -10,7 +10,7 @@ type LabelProps = {
10
10
  const LabelField: React.FC<LabelProps> = ({ value, tooltipText }) => {
11
11
  return (
12
12
  <div className={styles.label}>
13
- <DefinitionTooltip direction="bottom" tabIndex={0} tooltipText={tooltipText}>
13
+ <DefinitionTooltip direction="bottom" tabIndex={0} definition={tooltipText}>
14
14
  <span className="cds--label">{`${value}:`}</span>
15
15
  </DefinitionTooltip>
16
16
  </div>