@openmrs/esm-patient-tests-app 11.3.1-pre.9433 → 11.3.1-pre.9437
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/.turbo/turbo-build.log +3 -3
- package/dist/1477.js +1 -1
- package/dist/1477.js.map +1 -1
- package/dist/1935.js +1 -1
- package/dist/1935.js.map +1 -1
- package/dist/3509.js +1 -1
- package/dist/3509.js.map +1 -1
- package/dist/4300.js +1 -1
- package/dist/6301.js +1 -1
- package/dist/6301.js.map +1 -1
- package/dist/7202.js +1 -1
- package/dist/7202.js.map +1 -1
- package/dist/8555.js +1 -1
- package/dist/8555.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-tests-app.js +1 -1
- package/dist/openmrs-esm-patient-tests-app.js.buildmanifest.json +19 -19
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -1
- package/src/routes.json +1 -1
- package/src/test-orders/add-test-order/add-test-order.test.tsx +1 -1
- package/src/test-orders/add-test-order/add-test-order.workspace.tsx +1 -1
- package/src/test-orders/add-test-order/test-order-form.component.tsx +1 -1
- package/src/test-orders/add-test-order/test-type-search.component.tsx +1 -1
- package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.extension.tsx +1 -1
- package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.test.tsx +2 -2
- package/src/test-results/filter/filter-context.test.tsx +556 -0
- package/src/test-results/filter/filter-context.tsx +1 -1
- package/src/test-results/filter/filter-reducer.test.ts +540 -0
- package/src/test-results/filter/filter-reducer.ts +1 -1
- package/src/test-results/filter/filter-set.test.tsx +694 -0
- package/src/test-results/grouped-timeline/grouped-timeline.test.tsx +1 -1
- package/src/test-results/grouped-timeline/useObstreeData.test.ts +471 -0
- package/src/test-results/individual-results-table-tablet/usePanelData.tsx +40 -26
- package/src/test-results/loadPatientTestData/helpers.ts +29 -12
- package/src/test-results/loadPatientTestData/usePatientResultsData.ts +18 -7
- package/src/test-results/overview/external-overview.extension.tsx +1 -2
- package/src/test-results/print-modal/print-modal.extension.tsx +1 -1
- package/src/test-results/results-viewer/results-viewer.extension.tsx +7 -3
- package/src/test-results/tree-view/tree-view.component.tsx +6 -1
- package/src/test-results/tree-view/tree-view.test.tsx +117 -1
- package/src/test-results/trendline/trendline.component.tsx +88 -52
- package/src/test-results/ui-elements/reset-filters-empty-state/filter-empty-data-illustration.tsx +2 -2
- package/translations/en.json +1 -1
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
import reducer from './filter-reducer';
|
|
2
|
+
import { ReducerActionType, type ReducerState, type TreeNode } from './filter-types';
|
|
3
|
+
|
|
4
|
+
describe('filterReducer', () => {
|
|
5
|
+
const initialState: ReducerState = {
|
|
6
|
+
checkboxes: {},
|
|
7
|
+
parents: {},
|
|
8
|
+
roots: [],
|
|
9
|
+
tests: {},
|
|
10
|
+
lowestParents: [],
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe('INITIALIZE action', () => {
|
|
14
|
+
it('should initialize checkboxes for all leaf tests', () => {
|
|
15
|
+
const mockTrees: Array<TreeNode> = [
|
|
16
|
+
{
|
|
17
|
+
flatName: 'CBC',
|
|
18
|
+
display: 'Complete Blood Count',
|
|
19
|
+
subSets: [
|
|
20
|
+
{
|
|
21
|
+
flatName: 'CBC: Hemoglobin',
|
|
22
|
+
display: 'Hemoglobin',
|
|
23
|
+
obs: [{ obsDatetime: '2024-01-01', value: '12', interpretation: 'NORMAL' }],
|
|
24
|
+
hasData: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
flatName: 'CBC: Hematocrit',
|
|
28
|
+
display: 'Hematocrit',
|
|
29
|
+
obs: [{ obsDatetime: '2024-01-01', value: '36', interpretation: 'NORMAL' }],
|
|
30
|
+
hasData: true,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
hasData: true,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const newState = reducer(initialState, {
|
|
38
|
+
type: ReducerActionType.INITIALIZE,
|
|
39
|
+
trees: mockTrees,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
expect(newState.checkboxes).toEqual({
|
|
43
|
+
'CBC: Hemoglobin': false,
|
|
44
|
+
'CBC: Hematocrit': false,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should build parent-child relationships for nested tree structure', () => {
|
|
49
|
+
const mockTrees: Array<TreeNode> = [
|
|
50
|
+
{
|
|
51
|
+
flatName: 'CBC',
|
|
52
|
+
display: 'Complete Blood Count',
|
|
53
|
+
subSets: [
|
|
54
|
+
{
|
|
55
|
+
flatName: 'CBC: Hemoglobin',
|
|
56
|
+
display: 'Hemoglobin',
|
|
57
|
+
obs: [{ obsDatetime: '2024-01-01', value: '12', interpretation: 'NORMAL' }],
|
|
58
|
+
hasData: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
flatName: 'CBC: Hematocrit',
|
|
62
|
+
display: 'Hematocrit',
|
|
63
|
+
obs: [{ obsDatetime: '2024-01-01', value: '36', interpretation: 'NORMAL' }],
|
|
64
|
+
hasData: true,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
hasData: true,
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const newState = reducer(initialState, {
|
|
72
|
+
type: ReducerActionType.INITIALIZE,
|
|
73
|
+
trees: mockTrees,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
expect(newState.parents['CBC']).toEqual(['CBC: Hemoglobin', 'CBC: Hematocrit']);
|
|
77
|
+
expect(newState.roots).toEqual(mockTrees);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should store tests in tests object keyed by flatName', () => {
|
|
81
|
+
const mockTrees: Array<TreeNode> = [
|
|
82
|
+
{
|
|
83
|
+
flatName: 'Chemistry',
|
|
84
|
+
display: 'Chemistry Panel',
|
|
85
|
+
subSets: [
|
|
86
|
+
{
|
|
87
|
+
flatName: 'Chemistry: Sodium',
|
|
88
|
+
display: 'Sodium',
|
|
89
|
+
obs: [{ obsDatetime: '2024-01-01', value: '140', interpretation: 'NORMAL' }],
|
|
90
|
+
units: 'mmol/L',
|
|
91
|
+
hasData: true,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
hasData: true,
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const newState = reducer(initialState, {
|
|
99
|
+
type: ReducerActionType.INITIALIZE,
|
|
100
|
+
trees: mockTrees,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
expect(newState.tests['Chemistry: Sodium']).toEqual({
|
|
104
|
+
flatName: 'Chemistry: Sodium',
|
|
105
|
+
display: 'Sodium',
|
|
106
|
+
obs: [{ obsDatetime: '2024-01-01', value: '140', interpretation: 'NORMAL' }],
|
|
107
|
+
units: 'mmol/L',
|
|
108
|
+
hasData: true,
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should handle multiple trees with independent parent-child relationships', () => {
|
|
113
|
+
const mockTrees: Array<TreeNode> = [
|
|
114
|
+
{
|
|
115
|
+
flatName: 'CBC',
|
|
116
|
+
display: 'Complete Blood Count',
|
|
117
|
+
subSets: [
|
|
118
|
+
{
|
|
119
|
+
flatName: 'CBC: Hemoglobin',
|
|
120
|
+
display: 'Hemoglobin',
|
|
121
|
+
obs: [{ obsDatetime: '2024-01-01', value: '12', interpretation: 'NORMAL' }],
|
|
122
|
+
hasData: true,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
hasData: true,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
flatName: 'Lipid Panel',
|
|
129
|
+
display: 'Lipid Panel',
|
|
130
|
+
subSets: [
|
|
131
|
+
{
|
|
132
|
+
flatName: 'Lipid Panel: Cholesterol',
|
|
133
|
+
display: 'Cholesterol',
|
|
134
|
+
obs: [{ obsDatetime: '2024-01-01', value: '180', interpretation: 'NORMAL' }],
|
|
135
|
+
hasData: true,
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
hasData: true,
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
const newState = reducer(initialState, {
|
|
143
|
+
type: ReducerActionType.INITIALIZE,
|
|
144
|
+
trees: mockTrees,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(newState.parents['CBC']).toEqual(['CBC: Hemoglobin']);
|
|
148
|
+
expect(newState.parents['Lipid Panel']).toEqual(['Lipid Panel: Cholesterol']);
|
|
149
|
+
expect(newState.checkboxes).toEqual({
|
|
150
|
+
'CBC: Hemoglobin': false,
|
|
151
|
+
'Lipid Panel: Cholesterol': false,
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should handle deeply nested tree structures', () => {
|
|
156
|
+
const mockTrees: Array<TreeNode> = [
|
|
157
|
+
{
|
|
158
|
+
flatName: 'Lab Results',
|
|
159
|
+
display: 'Lab Results',
|
|
160
|
+
subSets: [
|
|
161
|
+
{
|
|
162
|
+
flatName: 'Hematology',
|
|
163
|
+
display: 'Hematology',
|
|
164
|
+
subSets: [
|
|
165
|
+
{
|
|
166
|
+
flatName: 'Hematology: WBC',
|
|
167
|
+
display: 'White Blood Cell Count',
|
|
168
|
+
obs: [{ obsDatetime: '2024-01-01', value: '7.5', interpretation: 'NORMAL' }],
|
|
169
|
+
hasData: true,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
hasData: true,
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
hasData: true,
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
const newState = reducer(initialState, {
|
|
180
|
+
type: ReducerActionType.INITIALIZE,
|
|
181
|
+
trees: mockTrees,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
expect(newState.checkboxes['Hematology: WBC']).toBe(false);
|
|
185
|
+
expect(newState.parents['Hematology']).toEqual(['Hematology: WBC']);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should merge duplicate tests with same flatName', () => {
|
|
189
|
+
const mockTrees: Array<TreeNode> = [
|
|
190
|
+
{
|
|
191
|
+
flatName: 'Panel1',
|
|
192
|
+
display: 'Panel 1',
|
|
193
|
+
subSets: [
|
|
194
|
+
{
|
|
195
|
+
flatName: 'Test: Glucose',
|
|
196
|
+
display: 'Glucose',
|
|
197
|
+
obs: [{ obsDatetime: '2024-01-01', value: '90', interpretation: 'NORMAL' }],
|
|
198
|
+
hasData: true,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
hasData: true,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
flatName: 'Panel2',
|
|
205
|
+
display: 'Panel 2',
|
|
206
|
+
subSets: [
|
|
207
|
+
{
|
|
208
|
+
flatName: 'Test: Glucose',
|
|
209
|
+
display: 'Glucose',
|
|
210
|
+
obs: [{ obsDatetime: '2024-01-02', value: '95', interpretation: 'NORMAL' }],
|
|
211
|
+
hasData: true,
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
hasData: true,
|
|
215
|
+
},
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
const newState = reducer(initialState, {
|
|
219
|
+
type: ReducerActionType.INITIALIZE,
|
|
220
|
+
trees: mockTrees,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
expect(newState.tests['Test: Glucose'].obs).toHaveLength(2);
|
|
224
|
+
expect(newState.tests['Test: Glucose'].obs).toEqual([
|
|
225
|
+
{ obsDatetime: '2024-01-01', value: '90', interpretation: 'NORMAL' },
|
|
226
|
+
{ obsDatetime: '2024-01-02', value: '95', interpretation: 'NORMAL' },
|
|
227
|
+
]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should identify lowestParents with children that have data', () => {
|
|
231
|
+
const mockTrees: Array<TreeNode> = [
|
|
232
|
+
{
|
|
233
|
+
flatName: 'CBC',
|
|
234
|
+
display: 'Complete Blood Count',
|
|
235
|
+
subSets: [
|
|
236
|
+
{
|
|
237
|
+
flatName: 'CBC: Hemoglobin',
|
|
238
|
+
display: 'Hemoglobin',
|
|
239
|
+
obs: [{ obsDatetime: '2024-01-01', value: '12', interpretation: 'NORMAL' }],
|
|
240
|
+
hasData: true,
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
hasData: true,
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
const newState = reducer(initialState, {
|
|
248
|
+
type: ReducerActionType.INITIALIZE,
|
|
249
|
+
trees: mockTrees,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
expect(newState.lowestParents).toHaveLength(1);
|
|
253
|
+
expect(newState.lowestParents[0].flatName).toBe('CBC');
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('should handle leaf nodes without subSets', () => {
|
|
257
|
+
const mockTrees: Array<TreeNode> = [
|
|
258
|
+
{
|
|
259
|
+
flatName: 'Standalone Test',
|
|
260
|
+
display: 'Standalone Test',
|
|
261
|
+
obs: [{ obsDatetime: '2024-01-01', value: '100', interpretation: 'NORMAL' }],
|
|
262
|
+
hasData: true,
|
|
263
|
+
},
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
const newState = reducer(initialState, {
|
|
267
|
+
type: ReducerActionType.INITIALIZE,
|
|
268
|
+
trees: mockTrees,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
expect(newState.checkboxes['Standalone Test']).toBe(false);
|
|
272
|
+
expect(newState.tests['Standalone Test']).toBeDefined();
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
describe('TOGGLE_CHECKBOX action', () => {
|
|
277
|
+
it('should toggle a single checkbox from false to true', () => {
|
|
278
|
+
const stateWithCheckboxes: ReducerState = {
|
|
279
|
+
...initialState,
|
|
280
|
+
checkboxes: {
|
|
281
|
+
'CBC: Hemoglobin': false,
|
|
282
|
+
'CBC: Hematocrit': false,
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const newState = reducer(stateWithCheckboxes, {
|
|
287
|
+
type: ReducerActionType.TOGGLE_CHECKBOX,
|
|
288
|
+
name: 'CBC: Hemoglobin',
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
expect(newState.checkboxes['CBC: Hemoglobin']).toBe(true);
|
|
292
|
+
expect(newState.checkboxes['CBC: Hematocrit']).toBe(false);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should toggle a single checkbox from true to false', () => {
|
|
296
|
+
const stateWithCheckboxes: ReducerState = {
|
|
297
|
+
...initialState,
|
|
298
|
+
checkboxes: {
|
|
299
|
+
'CBC: Hemoglobin': true,
|
|
300
|
+
'CBC: Hematocrit': true,
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const newState = reducer(stateWithCheckboxes, {
|
|
305
|
+
type: ReducerActionType.TOGGLE_CHECKBOX,
|
|
306
|
+
name: 'CBC: Hemoglobin',
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
expect(newState.checkboxes['CBC: Hemoglobin']).toBe(false);
|
|
310
|
+
expect(newState.checkboxes['CBC: Hematocrit']).toBe(true);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('should not affect other checkboxes when toggling one', () => {
|
|
314
|
+
const stateWithCheckboxes: ReducerState = {
|
|
315
|
+
...initialState,
|
|
316
|
+
checkboxes: {
|
|
317
|
+
Test1: false,
|
|
318
|
+
Test2: true,
|
|
319
|
+
Test3: false,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const newState = reducer(stateWithCheckboxes, {
|
|
324
|
+
type: ReducerActionType.TOGGLE_CHECKBOX,
|
|
325
|
+
name: 'Test2',
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
expect(newState.checkboxes).toEqual({
|
|
329
|
+
Test1: false,
|
|
330
|
+
Test2: false,
|
|
331
|
+
Test3: false,
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
describe('TOGGLE_PARENT action', () => {
|
|
337
|
+
it('should uncheck all children when they are all checked', () => {
|
|
338
|
+
const stateWithParents: ReducerState = {
|
|
339
|
+
...initialState,
|
|
340
|
+
checkboxes: {
|
|
341
|
+
'CBC: Hemoglobin': true,
|
|
342
|
+
'CBC: Hematocrit': true,
|
|
343
|
+
'CBC: WBC': true,
|
|
344
|
+
},
|
|
345
|
+
parents: {
|
|
346
|
+
CBC: ['CBC: Hemoglobin', 'CBC: Hematocrit', 'CBC: WBC'],
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const newState = reducer(stateWithParents, {
|
|
351
|
+
type: ReducerActionType.TOGGLE_PARENT,
|
|
352
|
+
name: 'CBC',
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
expect(newState.checkboxes['CBC: Hemoglobin']).toBe(false);
|
|
356
|
+
expect(newState.checkboxes['CBC: Hematocrit']).toBe(false);
|
|
357
|
+
expect(newState.checkboxes['CBC: WBC']).toBe(false);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('should check all children when any child is unchecked', () => {
|
|
361
|
+
const stateWithParents: ReducerState = {
|
|
362
|
+
...initialState,
|
|
363
|
+
checkboxes: {
|
|
364
|
+
'CBC: Hemoglobin': true,
|
|
365
|
+
'CBC: Hematocrit': false,
|
|
366
|
+
'CBC: WBC': true,
|
|
367
|
+
},
|
|
368
|
+
parents: {
|
|
369
|
+
CBC: ['CBC: Hemoglobin', 'CBC: Hematocrit', 'CBC: WBC'],
|
|
370
|
+
},
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const newState = reducer(stateWithParents, {
|
|
374
|
+
type: ReducerActionType.TOGGLE_PARENT,
|
|
375
|
+
name: 'CBC',
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
expect(newState.checkboxes['CBC: Hemoglobin']).toBe(true);
|
|
379
|
+
expect(newState.checkboxes['CBC: Hematocrit']).toBe(true);
|
|
380
|
+
expect(newState.checkboxes['CBC: WBC']).toBe(true);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('should check all children when all children are unchecked', () => {
|
|
384
|
+
const stateWithParents: ReducerState = {
|
|
385
|
+
...initialState,
|
|
386
|
+
checkboxes: {
|
|
387
|
+
'CBC: Hemoglobin': false,
|
|
388
|
+
'CBC: Hematocrit': false,
|
|
389
|
+
},
|
|
390
|
+
parents: {
|
|
391
|
+
CBC: ['CBC: Hemoglobin', 'CBC: Hematocrit'],
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const newState = reducer(stateWithParents, {
|
|
396
|
+
type: ReducerActionType.TOGGLE_PARENT,
|
|
397
|
+
name: 'CBC',
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
expect(newState.checkboxes['CBC: Hemoglobin']).toBe(true);
|
|
401
|
+
expect(newState.checkboxes['CBC: Hematocrit']).toBe(true);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should not affect children of other parents', () => {
|
|
405
|
+
const stateWithParents: ReducerState = {
|
|
406
|
+
...initialState,
|
|
407
|
+
checkboxes: {
|
|
408
|
+
'CBC: Hemoglobin': true,
|
|
409
|
+
'Lipid: Cholesterol': true,
|
|
410
|
+
},
|
|
411
|
+
parents: {
|
|
412
|
+
CBC: ['CBC: Hemoglobin'],
|
|
413
|
+
Lipid: ['Lipid: Cholesterol'],
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const newState = reducer(stateWithParents, {
|
|
418
|
+
type: ReducerActionType.TOGGLE_PARENT,
|
|
419
|
+
name: 'CBC',
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
expect(newState.checkboxes['CBC: Hemoglobin']).toBe(false);
|
|
423
|
+
expect(newState.checkboxes['Lipid: Cholesterol']).toBe(true);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('should handle parent with no children gracefully', () => {
|
|
427
|
+
const stateWithParents: ReducerState = {
|
|
428
|
+
...initialState,
|
|
429
|
+
checkboxes: {
|
|
430
|
+
Test1: false,
|
|
431
|
+
},
|
|
432
|
+
parents: {
|
|
433
|
+
EmptyParent: [],
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const newState = reducer(stateWithParents, {
|
|
438
|
+
type: ReducerActionType.TOGGLE_PARENT,
|
|
439
|
+
name: 'EmptyParent',
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
expect(newState.checkboxes).toEqual({ Test1: false });
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it('should handle parent that does not exist in parents mapping', () => {
|
|
446
|
+
const stateWithParents: ReducerState = {
|
|
447
|
+
...initialState,
|
|
448
|
+
checkboxes: {
|
|
449
|
+
Test1: false,
|
|
450
|
+
},
|
|
451
|
+
parents: {
|
|
452
|
+
CBC: ['CBC: Hemoglobin'],
|
|
453
|
+
},
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const newState = reducer(stateWithParents, {
|
|
457
|
+
type: ReducerActionType.TOGGLE_PARENT,
|
|
458
|
+
name: 'NonExistentParent',
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
expect(newState.checkboxes).toEqual({ Test1: false });
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
describe('RESET_TREE action', () => {
|
|
466
|
+
it('should reset all checkboxes to false', () => {
|
|
467
|
+
const stateWithMixedCheckboxes: ReducerState = {
|
|
468
|
+
...initialState,
|
|
469
|
+
checkboxes: {
|
|
470
|
+
Test1: true,
|
|
471
|
+
Test2: false,
|
|
472
|
+
Test3: true,
|
|
473
|
+
Test4: false,
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
const newState = reducer(stateWithMixedCheckboxes, {
|
|
478
|
+
type: ReducerActionType.RESET_TREE,
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
expect(newState.checkboxes).toEqual({
|
|
482
|
+
Test1: false,
|
|
483
|
+
Test2: false,
|
|
484
|
+
Test3: false,
|
|
485
|
+
Test4: false,
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it('should not affect other state properties', () => {
|
|
490
|
+
const stateWithData: ReducerState = {
|
|
491
|
+
checkboxes: { Test1: true, Test2: true },
|
|
492
|
+
parents: { Parent1: ['Test1', 'Test2'] },
|
|
493
|
+
roots: [{ flatName: 'Root', display: 'Root', hasData: true }],
|
|
494
|
+
tests: { Test1: { flatName: 'Test1', display: 'Test1' } },
|
|
495
|
+
lowestParents: [{ flatName: 'Parent1', display: 'Parent1' }],
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const newState = reducer(stateWithData, {
|
|
499
|
+
type: ReducerActionType.RESET_TREE,
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
expect(newState.checkboxes).toEqual({ Test1: false, Test2: false });
|
|
503
|
+
expect(newState.parents).toEqual({ Parent1: ['Test1', 'Test2'] });
|
|
504
|
+
expect(newState.roots).toEqual(stateWithData.roots);
|
|
505
|
+
expect(newState.tests).toEqual(stateWithData.tests);
|
|
506
|
+
expect(newState.lowestParents).toEqual(stateWithData.lowestParents);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
it('should handle empty checkboxes object', () => {
|
|
510
|
+
const stateWithNoCheckboxes: ReducerState = {
|
|
511
|
+
...initialState,
|
|
512
|
+
checkboxes: {},
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const newState = reducer(stateWithNoCheckboxes, {
|
|
516
|
+
type: ReducerActionType.RESET_TREE,
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
expect(newState.checkboxes).toEqual({});
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
describe('Default case', () => {
|
|
524
|
+
it('should return unchanged state for unknown action type', () => {
|
|
525
|
+
const currentState: ReducerState = {
|
|
526
|
+
checkboxes: { Test1: true },
|
|
527
|
+
parents: {},
|
|
528
|
+
roots: [],
|
|
529
|
+
tests: {},
|
|
530
|
+
lowestParents: [],
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
const newState = reducer(currentState, {
|
|
534
|
+
type: 'UNKNOWN_ACTION' as any,
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
expect(newState).toEqual(currentState);
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
});
|
|
@@ -131,7 +131,7 @@ function reducer(state: ReducerState, action: ReducerAction): ReducerState {
|
|
|
131
131
|
|
|
132
132
|
case ReducerActionType.TOGGLE_PARENT: {
|
|
133
133
|
const affectedLeaves = state.parents[action.name];
|
|
134
|
-
const checkboxes =
|
|
134
|
+
const checkboxes = { ...state.checkboxes };
|
|
135
135
|
|
|
136
136
|
if (affectedLeaves && Array.isArray(affectedLeaves)) {
|
|
137
137
|
const allChecked = affectedLeaves.every((leaf) => checkboxes[leaf]);
|