@centreon/ui 25.10.29 → 25.10.30
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 +3 -3
- package/public/mockServiceWorker.js +8 -31
- package/src/Dashboard/Item.tsx +142 -149
- package/src/Form/Inputs/ConnectedAutocomplete.tsx +2 -0
- package/src/Form/Inputs/Grid.tsx +2 -3
- package/src/Form/Inputs/models.ts +2 -0
- package/src/Form/Section/navigateToSection.ts +6 -6
- package/src/Graph/BarChart/BarChart.cypress.spec.tsx +55 -102
- package/src/Graph/BarChart/BarChart.stories.tsx +1 -51
- package/src/Graph/BarChart/BarChart.tsx +1 -1
- package/src/Graph/BarChart/BarGroup.tsx +32 -22
- package/src/Graph/BarChart/BarStack.tsx +26 -15
- package/src/Graph/BarChart/MemoizedGroup.tsx +18 -14
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +6 -7
- package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +2 -2
- package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +5 -4
- package/src/Graph/Chart/BasicComponents/Lines/StackedLines/useStackedLines.ts +45 -18
- package/src/Graph/Chart/BasicComponents/Lines/index.tsx +118 -124
- package/src/Graph/Chart/Chart.cypress.spec.tsx +6 -25
- package/src/Graph/Chart/Chart.stories.tsx +1 -43
- package/src/Graph/Chart/Chart.tsx +13 -9
- package/src/Graph/Chart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +4 -2
- package/src/Graph/Chart/Legend/index.tsx +2 -26
- package/src/Graph/Chart/index.tsx +45 -31
- package/src/Graph/Chart/models.ts +1 -6
- package/src/Graph/Chart/translatedLabels.ts +1 -0
- package/src/Graph/Chart/useChartData.ts +24 -3
- package/src/Graph/common/Axes/index.tsx +1 -1
- package/src/Graph/common/BaseChart/BaseChart.tsx +1 -6
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +23 -16
- package/src/Graph/common/Error/NoData.tsx +18 -0
- package/src/Graph/common/Grids/index.tsx +4 -4
- package/src/Graph/common/timeSeries/index.test.ts +4 -24
- package/src/Graph/common/timeSeries/index.ts +120 -184
- package/src/Graph/common/timeSeries/models.ts +1 -1
- package/src/Graph/common/utils.ts +4 -10
- package/src/Graph/index.ts +20 -20
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +3 -3
- package/src/InputField/Select/Autocomplete/Multi/Listbox.tsx +11 -3
- package/src/InputField/Select/Autocomplete/Multi/Multi.tsx +3 -2
- package/src/InputField/Select/index.tsx +2 -1
- package/src/Listing/ActionBar/Pagination.tsx +2 -1
- package/src/Listing/ActionBar/index.tsx +113 -8
- package/src/Listing/index.tsx +19 -2
- package/src/Listing/translatedLabels.ts +4 -0
- package/src/Module/index.tsx +2 -8
- package/src/ThemeProvider/index.tsx +21 -30
- package/src/ThemeProvider/tailwindcss.css +12 -10
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -5
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -1
- package/src/api/useGraphQuery/index.ts +7 -4
- package/src/components/Layout/PageLayout/PageLayout.tsx +3 -9
- package/src/components/Layout/PageLayout/PageLayoutActions.tsx +3 -5
- package/src/components/Layout/PageLayout/PageLayoutBody.tsx +3 -5
- package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +3 -5
- package/src/components/Layout/PageLayout/PageQuickAccess.tsx +44 -25
- package/src/components/Layout/PageLayout/translatedLabels.ts +1 -0
- package/src/components/Menu/Button/MenuButton.styles.ts +27 -0
- package/src/components/Menu/Button/MenuButton.tsx +5 -6
- package/src/components/Menu/Menu.styles.ts +68 -0
- package/src/components/Menu/MenuDivider.tsx +5 -1
- package/src/components/Menu/MenuItem.tsx +5 -1
- package/src/components/Menu/MenuItems.tsx +4 -5
- package/src/components/Modal/Modal.styles.ts +2 -1
- package/src/components/Modal/ModalHeader.tsx +1 -5
- package/src/utils/useInfiniteScrollListing.ts +11 -7
- package/src/utils/useViewportIntersection.ts +3 -4
- package/src/Graph/mockedData/dataWithMissingPoint.json +0 -74
- package/src/Graph/mockedData/pingServiceWithStackedKeys.json +0 -205
|
@@ -175,11 +175,6 @@ export interface LegendModel {
|
|
|
175
175
|
mode: 'grid' | 'list';
|
|
176
176
|
placement: 'bottom' | 'left' | 'right';
|
|
177
177
|
renderExtraComponent?: ReactNode;
|
|
178
|
-
secondaryClick?: (props: {
|
|
179
|
-
element: EventTarget | null;
|
|
180
|
-
metricId: number | string;
|
|
181
|
-
position: [number, number];
|
|
182
|
-
}) => void;
|
|
183
178
|
}
|
|
184
179
|
|
|
185
180
|
export interface GetDate {
|
|
@@ -198,4 +193,4 @@ export interface GraphTooltipData {
|
|
|
198
193
|
unit: string;
|
|
199
194
|
value: number;
|
|
200
195
|
}>;
|
|
201
|
-
}
|
|
196
|
+
}
|
|
@@ -31,6 +31,15 @@ interface Props {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const getBoolean = (value) => Boolean(Number(value));
|
|
34
|
+
const defaultDsData = {
|
|
35
|
+
ds_color_line: '#000000',
|
|
36
|
+
ds_filled: false,
|
|
37
|
+
ds_invert: false,
|
|
38
|
+
ds_legend: '',
|
|
39
|
+
ds_order: '0',
|
|
40
|
+
ds_stack: '0',
|
|
41
|
+
ds_transparency: 80
|
|
42
|
+
};
|
|
34
43
|
|
|
35
44
|
const useGraphData = ({ data, end, start }: Props): GraphDataResult => {
|
|
36
45
|
const adjustedDataRef = useRef<Data>();
|
|
@@ -40,13 +49,25 @@ const useGraphData = ({ data, end, start }: Props): GraphDataResult => {
|
|
|
40
49
|
return data;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
|
-
if (isEmpty(data.metrics)) {
|
|
52
|
+
if (isEmpty(data.metrics) || isEmpty(data.times)) {
|
|
44
53
|
return undefined;
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
const metricsWithValidDsData = (data?.metrics || []).map((metric) => ({
|
|
57
|
+
...metric,
|
|
58
|
+
ds_data: {
|
|
59
|
+
...defaultDsData,
|
|
60
|
+
...(metric?.ds_data || {}),
|
|
61
|
+
ds_color_area:
|
|
62
|
+
metric?.ds_data?.ds_color_area ??
|
|
63
|
+
metric?.ds_data?.ds_color_line ??
|
|
64
|
+
defaultDsData.ds_color_line
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
|
|
47
68
|
const metricsGroupedByColor = groupBy(
|
|
48
|
-
(metric) => metric.ds_data
|
|
49
|
-
)(
|
|
69
|
+
(metric) => metric.ds_data?.ds_color_line || '#000000'
|
|
70
|
+
)(metricsWithValidDsData);
|
|
50
71
|
|
|
51
72
|
const newMetrics = Object.entries(metricsGroupedByColor).map(
|
|
52
73
|
([color, value]) => {
|
|
@@ -59,7 +59,7 @@ const Axes = ({
|
|
|
59
59
|
const formatAxisTick = (tick): string =>
|
|
60
60
|
format({ date: new Date(tick), formatString: tickFormat });
|
|
61
61
|
|
|
62
|
-
const displayAxisRight = !isNil(secondUnit);
|
|
62
|
+
const displayAxisRight = !isNil(secondUnit) && !isNil(rightScale);
|
|
63
63
|
|
|
64
64
|
const AxisBottom = isHorizontal ? Axis.AxisBottom : Axis.AxisLeft;
|
|
65
65
|
const AxisLeft = isHorizontal ? Axis.AxisLeft : Axis.AxisTop;
|
|
@@ -19,10 +19,7 @@ interface Props {
|
|
|
19
19
|
header?: LineChartHeader;
|
|
20
20
|
height: number | null;
|
|
21
21
|
isHorizontal?: boolean;
|
|
22
|
-
legend: Pick<
|
|
23
|
-
LegendModel,
|
|
24
|
-
'renderExtraComponent' | 'placement' | 'mode' | 'secondaryClick'
|
|
25
|
-
> & {
|
|
22
|
+
legend: Pick<LegendModel, 'renderExtraComponent' | 'placement' | 'mode'> & {
|
|
26
23
|
displayLegend: boolean;
|
|
27
24
|
legendHeight?: number;
|
|
28
25
|
};
|
|
@@ -104,7 +101,6 @@ const BaseChart = ({
|
|
|
104
101
|
shouldDisplayLegendInCompactMode={
|
|
105
102
|
shouldDisplayLegendInCompactMode
|
|
106
103
|
}
|
|
107
|
-
secondaryClick={legend?.secondaryClick}
|
|
108
104
|
/>
|
|
109
105
|
</div>
|
|
110
106
|
)}
|
|
@@ -126,7 +122,6 @@ const BaseChart = ({
|
|
|
126
122
|
renderExtraComponent={legend.renderExtraComponent}
|
|
127
123
|
setLinesGraph={setLines}
|
|
128
124
|
shouldDisplayLegendInCompactMode={shouldDisplayLegendInCompactMode}
|
|
129
|
-
secondaryClick={legend?.secondaryClick}
|
|
130
125
|
/>
|
|
131
126
|
</div>
|
|
132
127
|
)}
|
|
@@ -50,6 +50,11 @@ const ChartSvgWrapper = ({
|
|
|
50
50
|
hasSecondUnit
|
|
51
51
|
}: Props): JSX.Element => {
|
|
52
52
|
const isHorizontal = equals(orientation, 'horizontal');
|
|
53
|
+
const hasValidLeftScale = Boolean(leftScale);
|
|
54
|
+
const hasValidXScale = Boolean(xScale);
|
|
55
|
+
const canRenderAxes = hasValidLeftScale && hasValidXScale;
|
|
56
|
+
const canRenderGridRows = Boolean(isHorizontal ? leftScale : xScale);
|
|
57
|
+
const canRenderGridColumns = Boolean(isHorizontal ? xScale : leftScale);
|
|
53
58
|
|
|
54
59
|
return (
|
|
55
60
|
<svg
|
|
@@ -65,7 +70,7 @@ const ChartSvgWrapper = ({
|
|
|
65
70
|
})}
|
|
66
71
|
top={margin.top}
|
|
67
72
|
>
|
|
68
|
-
{showGridLines && (
|
|
73
|
+
{showGridLines && (canRenderGridRows || canRenderGridColumns) && (
|
|
69
74
|
<Grids
|
|
70
75
|
gridLinesType={gridLinesType}
|
|
71
76
|
height={graphHeight - margin.top}
|
|
@@ -74,21 +79,23 @@ const ChartSvgWrapper = ({
|
|
|
74
79
|
xScale={isHorizontal ? xScale : leftScale}
|
|
75
80
|
/>
|
|
76
81
|
)}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
{canRenderAxes && (
|
|
83
|
+
<Axes
|
|
84
|
+
allUnits={allUnits}
|
|
85
|
+
data={{
|
|
86
|
+
baseAxis: base,
|
|
87
|
+
lines: displayedLines,
|
|
88
|
+
timeSeries,
|
|
89
|
+
...axis
|
|
90
|
+
}}
|
|
91
|
+
height={graphHeight}
|
|
92
|
+
leftScale={leftScale}
|
|
93
|
+
orientation={orientation}
|
|
94
|
+
rightScale={rightScale}
|
|
95
|
+
width={graphWidth}
|
|
96
|
+
xScale={xScale}
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
92
99
|
{children}
|
|
93
100
|
</Group.Group>
|
|
94
101
|
</svg>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Typography } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
import { labelNoDataForThisPeriod } from '../../Chart/translatedLabels';
|
|
6
|
+
|
|
7
|
+
const NoData = () => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
return (
|
|
10
|
+
<div className={'flex items-center justify-center h-full'}>
|
|
11
|
+
<Typography align="center" variant="body1">
|
|
12
|
+
{t(labelNoDataForThisPeriod)}
|
|
13
|
+
</Typography>
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default NoData;
|
|
@@ -8,9 +8,9 @@ import { ChartAxis } from '../../Chart/models';
|
|
|
8
8
|
|
|
9
9
|
interface Props extends Pick<ChartAxis, 'gridLinesType'> {
|
|
10
10
|
height: number;
|
|
11
|
-
leftScale
|
|
11
|
+
leftScale?: ScaleLinear<number, number>;
|
|
12
12
|
width: number;
|
|
13
|
-
xScale
|
|
13
|
+
xScale?: ScaleLinear<number, number>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const Grids = ({
|
|
@@ -31,10 +31,10 @@ const Grids = ({
|
|
|
31
31
|
|
|
32
32
|
return (
|
|
33
33
|
<g>
|
|
34
|
-
{displayRows && (
|
|
34
|
+
{displayRows && leftScale && (
|
|
35
35
|
<Grid.GridRows height={height} scale={leftScale} width={width} />
|
|
36
36
|
)}
|
|
37
|
-
{displayColumns && (
|
|
37
|
+
{displayColumns && xScale && (
|
|
38
38
|
<Grid.GridColumns height={height} scale={xScale} width={width} />
|
|
39
39
|
)}
|
|
40
40
|
</g>
|
|
@@ -185,7 +185,6 @@ describe('timeSeries', () => {
|
|
|
185
185
|
average_value: 1,
|
|
186
186
|
color: 'black',
|
|
187
187
|
display: true,
|
|
188
|
-
displayAs: undefined,
|
|
189
188
|
filled: false,
|
|
190
189
|
highlight: undefined,
|
|
191
190
|
invert: null,
|
|
@@ -196,7 +195,6 @@ describe('timeSeries', () => {
|
|
|
196
195
|
metric_id: 1,
|
|
197
196
|
minimum_value: 0.5,
|
|
198
197
|
name: 'Round-Trip-Time Average (ms)',
|
|
199
|
-
stackKey: null,
|
|
200
198
|
stackOrder: null,
|
|
201
199
|
transparency: 80,
|
|
202
200
|
unit: 'ms'
|
|
@@ -206,7 +204,6 @@ describe('timeSeries', () => {
|
|
|
206
204
|
average_value: 1,
|
|
207
205
|
color: 'blue',
|
|
208
206
|
display: true,
|
|
209
|
-
displayAs: undefined,
|
|
210
207
|
filled: true,
|
|
211
208
|
highlight: undefined,
|
|
212
209
|
invert: null,
|
|
@@ -217,7 +214,6 @@ describe('timeSeries', () => {
|
|
|
217
214
|
metric_id: 2,
|
|
218
215
|
minimum_value: 0.5,
|
|
219
216
|
name: 'Time (ms)',
|
|
220
|
-
stackKey: null,
|
|
221
217
|
stackOrder: null,
|
|
222
218
|
transparency: 80,
|
|
223
219
|
unit: 'ms'
|
|
@@ -227,7 +223,6 @@ describe('timeSeries', () => {
|
|
|
227
223
|
average_value: 1,
|
|
228
224
|
color: 'red',
|
|
229
225
|
display: true,
|
|
230
|
-
displayAs: undefined,
|
|
231
226
|
filled: true,
|
|
232
227
|
highlight: undefined,
|
|
233
228
|
invert: null,
|
|
@@ -238,7 +233,6 @@ describe('timeSeries', () => {
|
|
|
238
233
|
metric_id: 3,
|
|
239
234
|
minimum_value: 0.5,
|
|
240
235
|
name: 'Average duration (ms)',
|
|
241
|
-
stackKey: null,
|
|
242
236
|
stackOrder: 2,
|
|
243
237
|
transparency: 80,
|
|
244
238
|
unit: 'ms'
|
|
@@ -248,7 +242,6 @@ describe('timeSeries', () => {
|
|
|
248
242
|
average_value: 1,
|
|
249
243
|
color: 'yellow',
|
|
250
244
|
display: true,
|
|
251
|
-
displayAs: undefined,
|
|
252
245
|
filled: true,
|
|
253
246
|
highlight: undefined,
|
|
254
247
|
invert: '1',
|
|
@@ -259,7 +252,6 @@ describe('timeSeries', () => {
|
|
|
259
252
|
metric_id: 4,
|
|
260
253
|
minimum_value: 0.5,
|
|
261
254
|
name: 'Duration (ms)',
|
|
262
|
-
stackKey: null,
|
|
263
255
|
stackOrder: 1,
|
|
264
256
|
transparency: 80,
|
|
265
257
|
unit: 'ms'
|
|
@@ -269,7 +261,6 @@ describe('timeSeries', () => {
|
|
|
269
261
|
average_value: 1,
|
|
270
262
|
color: 'yellow',
|
|
271
263
|
display: true,
|
|
272
|
-
displayAs: undefined,
|
|
273
264
|
filled: true,
|
|
274
265
|
highlight: undefined,
|
|
275
266
|
invert: null,
|
|
@@ -280,7 +271,6 @@ describe('timeSeries', () => {
|
|
|
280
271
|
metric_id: 5,
|
|
281
272
|
minimum_value: 0.5,
|
|
282
273
|
name: 'Packet Loss (%)',
|
|
283
|
-
stackKey: null,
|
|
284
274
|
stackOrder: null,
|
|
285
275
|
transparency: 80,
|
|
286
276
|
unit: '%'
|
|
@@ -341,7 +331,6 @@ describe('timeSeries', () => {
|
|
|
341
331
|
average_value: 1,
|
|
342
332
|
color: 'black',
|
|
343
333
|
display: true,
|
|
344
|
-
displayAs: undefined,
|
|
345
334
|
filled: false,
|
|
346
335
|
highlight: undefined,
|
|
347
336
|
invert: null,
|
|
@@ -352,7 +341,6 @@ describe('timeSeries', () => {
|
|
|
352
341
|
metric_id: 1,
|
|
353
342
|
minimum_value: 0.5,
|
|
354
343
|
name: 'Round-Trip-Time Average (ms)',
|
|
355
|
-
stackKey: null,
|
|
356
344
|
stackOrder: null,
|
|
357
345
|
transparency: 80,
|
|
358
346
|
unit: 'ms'
|
|
@@ -374,10 +362,10 @@ describe('timeSeries', () => {
|
|
|
374
362
|
describe(formatMetricValue, () => {
|
|
375
363
|
const cases: Array<TestCase> = [
|
|
376
364
|
[218857269, '', 1000, '218.86m'],
|
|
377
|
-
[218857269, '', 1024, '208.72
|
|
365
|
+
[218857269, '', 1024, '208.72 Mi'],
|
|
378
366
|
[0.12232323445, '', 1000, '0.12'],
|
|
379
|
-
[1024, 'B', 1000, '1
|
|
380
|
-
[1024, 'B', 1024, '1
|
|
367
|
+
[1024, 'B', 1000, '1 KiB'],
|
|
368
|
+
[1024, 'B', 1024, '1 KiB'],
|
|
381
369
|
[null, 'B', 1024, null]
|
|
382
370
|
];
|
|
383
371
|
|
|
@@ -401,7 +389,6 @@ describe('timeSeries', () => {
|
|
|
401
389
|
average_value: 1,
|
|
402
390
|
color: 'yellow',
|
|
403
391
|
display: true,
|
|
404
|
-
displayAs: undefined,
|
|
405
392
|
filled: true,
|
|
406
393
|
highlight: undefined,
|
|
407
394
|
invert: '1',
|
|
@@ -412,7 +399,6 @@ describe('timeSeries', () => {
|
|
|
412
399
|
metric_id: 4,
|
|
413
400
|
minimum_value: 0.5,
|
|
414
401
|
name: 'Duration (ms)',
|
|
415
|
-
stackKey: null,
|
|
416
402
|
stackOrder: 1,
|
|
417
403
|
transparency: 80,
|
|
418
404
|
unit: 'ms'
|
|
@@ -422,7 +408,6 @@ describe('timeSeries', () => {
|
|
|
422
408
|
average_value: 1,
|
|
423
409
|
color: 'red',
|
|
424
410
|
display: true,
|
|
425
|
-
displayAs: undefined,
|
|
426
411
|
filled: true,
|
|
427
412
|
highlight: undefined,
|
|
428
413
|
invert: null,
|
|
@@ -433,7 +418,6 @@ describe('timeSeries', () => {
|
|
|
433
418
|
metric_id: 3,
|
|
434
419
|
minimum_value: 0.5,
|
|
435
420
|
name: 'Average duration (ms)',
|
|
436
|
-
stackKey: null,
|
|
437
421
|
stackOrder: 2,
|
|
438
422
|
transparency: 80,
|
|
439
423
|
unit: 'ms'
|
|
@@ -491,7 +475,6 @@ describe('timeSeries', () => {
|
|
|
491
475
|
average_value: 1,
|
|
492
476
|
color: 'yellow',
|
|
493
477
|
display: true,
|
|
494
|
-
displayAs: undefined,
|
|
495
478
|
filled: true,
|
|
496
479
|
highlight: undefined,
|
|
497
480
|
invert: '1',
|
|
@@ -502,7 +485,6 @@ describe('timeSeries', () => {
|
|
|
502
485
|
metric_id: 4,
|
|
503
486
|
minimum_value: 0.5,
|
|
504
487
|
name: 'Duration (ms)',
|
|
505
|
-
stackKey: null,
|
|
506
488
|
stackOrder: 1,
|
|
507
489
|
transparency: 80,
|
|
508
490
|
unit: 'ms'
|
|
@@ -521,7 +503,6 @@ describe('timeSeries', () => {
|
|
|
521
503
|
average_value: 1,
|
|
522
504
|
color: 'red',
|
|
523
505
|
display: true,
|
|
524
|
-
displayAs: undefined,
|
|
525
506
|
filled: true,
|
|
526
507
|
highlight: undefined,
|
|
527
508
|
invert: null,
|
|
@@ -532,7 +513,6 @@ describe('timeSeries', () => {
|
|
|
532
513
|
metric_id: 3,
|
|
533
514
|
minimum_value: 0.5,
|
|
534
515
|
name: 'Average duration (ms)',
|
|
535
|
-
stackKey: null,
|
|
536
516
|
stackOrder: 2,
|
|
537
517
|
transparency: 80,
|
|
538
518
|
unit: 'ms'
|
|
@@ -573,7 +553,7 @@ describe('Format value with unit', () => {
|
|
|
573
553
|
return '324.23m';
|
|
574
554
|
}
|
|
575
555
|
|
|
576
|
-
return `309.21
|
|
556
|
+
return `309.21 Mi${unit}`;
|
|
577
557
|
};
|
|
578
558
|
|
|
579
559
|
const humanReadableTestCases = units.map((unit) => {
|