@scality/core-ui 0.186.0 → 0.187.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.
- package/dist/components/{linetemporalchart/MetricTimespanProvider.d.ts → charts/MetricsTimeSpanProvider.d.ts} +1 -1
- package/dist/components/charts/MetricsTimeSpanProvider.d.ts.map +1 -0
- package/dist/components/{barchartv2/Barchart.component.d.ts → charts/barchart/Barchart.d.ts} +2 -33
- package/dist/components/charts/barchart/Barchart.d.ts.map +1 -0
- package/dist/components/charts/barchart/Barchart.js +56 -0
- package/dist/components/{barchartv2/utils.d.ts → charts/barchart/Barchart.utils.d.ts} +8 -35
- package/dist/components/charts/barchart/Barchart.utils.d.ts.map +1 -0
- package/dist/components/{barchartv2/utils.js → charts/barchart/Barchart.utils.js} +7 -88
- package/dist/components/{barchartv2 → charts/barchart}/BarchartTooltip.d.ts +2 -1
- package/dist/components/charts/barchart/BarchartTooltip.d.ts.map +1 -0
- package/dist/components/{barchartv2 → charts/barchart}/BarchartTooltip.js +3 -3
- package/dist/components/{charttooltip → charts/common}/ChartTooltip.d.ts +9 -2
- package/dist/components/charts/common/ChartTooltip.d.ts.map +1 -0
- package/dist/components/{charttooltip → charts/common}/ChartTooltip.js +11 -15
- package/dist/components/charts/common/SharedComponents.d.ts +47 -0
- package/dist/components/charts/common/SharedComponents.d.ts.map +1 -0
- package/dist/components/charts/common/SharedComponents.js +73 -0
- package/dist/components/charts/common/chartUtils.d.ts +91 -0
- package/dist/components/charts/common/chartUtils.d.ts.map +1 -0
- package/dist/components/charts/common/chartUtils.js +243 -0
- package/dist/components/{globalhealthbar/GlobalHealthBarRecharts.component.d.ts → charts/globalhealthbar/GlobalHealthBar.d.ts} +2 -2
- package/dist/components/charts/globalhealthbar/GlobalHealthBar.d.ts.map +1 -0
- package/dist/components/{globalhealthbar/useHealthBarData.d.ts → charts/globalhealthbar/GlobalHealthBar.hooks.d.ts} +1 -1
- package/dist/components/charts/globalhealthbar/GlobalHealthBar.hooks.d.ts.map +1 -0
- package/dist/components/{globalhealthbar/GlobalHealthBarRecharts.component.js → charts/globalhealthbar/GlobalHealthBar.js} +4 -4
- package/dist/components/{globalhealthbar/healthBarUtils.d.ts → charts/globalhealthbar/GlobalHealthBar.utils.d.ts} +1 -1
- package/dist/components/charts/globalhealthbar/GlobalHealthBar.utils.d.ts.map +1 -0
- package/dist/components/{globalhealthbar/healthBarUtils.js → charts/globalhealthbar/GlobalHealthBar.utils.js} +1 -1
- package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/GlobalHealthBarTooltip.d.ts +1 -1
- package/dist/components/charts/globalhealthbar/GlobalHealthBarTooltip.d.ts.map +1 -0
- package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/GlobalHealthBarTooltip.js +7 -3
- package/dist/components/charts/globalhealthbar/HealthBarXAxis.d.ts.map +1 -0
- package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/HealthBarXAxis.js +1 -1
- package/dist/components/charts/index.d.ts +16 -0
- package/dist/components/charts/index.d.ts.map +1 -0
- package/dist/components/charts/index.js +15 -0
- package/dist/components/{chartlegend → charts/legend}/ChartLegend.d.ts +1 -1
- package/dist/components/charts/legend/ChartLegend.d.ts.map +1 -0
- package/dist/components/{chartlegend → charts/legend}/ChartLegend.js +2 -2
- package/dist/components/{chartlegend → charts/legend}/ChartLegendWrapper.d.ts +1 -1
- package/dist/components/charts/legend/ChartLegendWrapper.d.ts.map +1 -0
- package/dist/components/{linetimeseriechart/linetimeseriechart.component.d.ts → charts/linetimeseries/LineTimeSerieChart.d.ts} +12 -2
- package/dist/components/charts/linetimeseries/LineTimeSerieChart.d.ts.map +1 -0
- package/dist/components/{linetimeseriechart/linetimeseriechart.component.js → charts/linetimeseries/LineTimeSerieChart.js} +34 -35
- package/dist/components/charts/linetimeseries/LineTimeSerieChart.utils.d.ts +14 -0
- package/dist/components/charts/linetimeseries/LineTimeSerieChart.utils.d.ts.map +1 -0
- package/dist/components/{linetimeseriechart/utils.js → charts/linetimeseries/LineTimeSerieChart.utils.js} +4 -6
- package/dist/components/charts/sparkline/Sparkline.d.ts +23 -0
- package/dist/components/charts/sparkline/Sparkline.d.ts.map +1 -0
- package/dist/components/{sparkline/sparkline.component.js → charts/sparkline/Sparkline.js} +12 -6
- package/dist/components/charts/types.d.ts +34 -0
- package/dist/components/charts/types.d.ts.map +1 -0
- package/dist/components/charts/types.js +4 -0
- package/dist/components/icon/Icon.component.d.ts +1 -0
- package/dist/components/icon/Icon.component.d.ts.map +1 -1
- package/dist/components/icon/Icon.component.js +2 -2
- package/dist/components/textbadge/TextBadge.component.d.ts +1 -1
- package/dist/components/textbadge/TextBadge.component.d.ts.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/next.d.ts +3 -11
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +4 -11
- package/package.json +2 -6
- package/src/lib/components/{barchartv2/Barchart.component.test.tsx → charts/barchart/Barchart.test.tsx} +35 -10
- package/src/lib/components/{barchartv2/Barchart.component.tsx → charts/barchart/Barchart.tsx} +42 -207
- package/src/lib/components/{barchartv2/utils.test.ts → charts/barchart/Barchart.utils.test.ts} +2 -141
- package/src/lib/components/{barchartv2/utils.ts → charts/barchart/Barchart.utils.ts} +17 -143
- package/src/lib/components/{barchartv2 → charts/barchart}/BarchartTooltip.tsx +5 -9
- package/src/lib/components/{charttooltip → charts/common}/ChartTooltip.tsx +13 -20
- package/src/lib/components/charts/common/SharedComponents.tsx +180 -0
- package/src/lib/components/charts/common/chartUtils.test.ts +402 -0
- package/src/lib/components/charts/common/chartUtils.ts +334 -0
- package/src/lib/components/{globalhealthbar/useHealthBarData.spec.tsx → charts/globalhealthbar/GlobalHealthBar.hooks.test.tsx} +1 -1
- package/src/lib/components/{globalhealthbar/GlobalHealthBarRecharts.component.tsx → charts/globalhealthbar/GlobalHealthBar.tsx} +4 -4
- package/src/lib/components/{globalhealthbar/healthBarUtils.spec.ts → charts/globalhealthbar/GlobalHealthBar.utils.test.ts} +1 -1
- package/src/lib/components/{globalhealthbar/healthBarUtils.ts → charts/globalhealthbar/GlobalHealthBar.utils.ts} +1 -1
- package/src/lib/components/{globalhealthbar/components → charts/globalhealthbar}/GlobalHealthBarTooltip.tsx +8 -4
- package/src/lib/components/{globalhealthbar/components → charts/globalhealthbar}/HealthBarXAxis.tsx +1 -1
- package/src/lib/components/charts/index.ts +59 -0
- package/src/lib/components/{chartlegend → charts/legend}/ChartLegend.tsx +2 -2
- package/src/lib/components/{chartlegend → charts/legend}/ChartLegendWrapper.tsx +1 -1
- package/src/lib/components/{linetimeseriechart/linetimeseriechart.test.tsx → charts/linetimeseries/LineTimeSerieChart.test.tsx} +3 -6
- package/src/lib/components/{linetimeseriechart/linetimeseriechart.component.tsx → charts/linetimeseries/LineTimeSerieChart.tsx} +48 -44
- package/src/lib/components/{linetimeseriechart/utils.test.ts → charts/linetimeseries/LineTimeSerieChart.utils.test.ts} +1 -1
- package/src/lib/components/{linetimeseriechart/utils.ts → charts/linetimeseries/LineTimeSerieChart.utils.ts} +4 -6
- package/src/lib/components/charts/sparkline/Sparkline.tsx +80 -0
- package/src/lib/components/charts/types.ts +36 -0
- package/src/lib/components/icon/Icon.component.tsx +12 -8
- package/src/lib/components/textbadge/TextBadge.component.tsx +1 -1
- package/src/lib/index.ts +4 -2
- package/src/lib/next.ts +26 -13
- package/stories/BarChart/barchart.stories.tsx +10 -9
- package/stories/GlobalHealthBar/{globalhealthbarRecharts.stories.tsx → globalhealthbar.stories.tsx} +3 -21
- package/stories/GlobalHealthBar/globalheathbarrecharts.guideline.mdx +2 -2
- package/stories/guideline/chart-guideline.mdx +1 -38
- package/stories/linetimeseriechart.stories.tsx +4 -6
- package/stories/sparkline.stories.tsx +13 -11
- package/stories/textbadge.stories.tsx +15 -0
- package/dist/components/barchart/BarChart.component.d.ts +0 -17
- package/dist/components/barchart/BarChart.component.d.ts.map +0 -1
- package/dist/components/barchart/BarChart.component.js +0 -27
- package/dist/components/barchartv2/Barchart.component.d.ts.map +0 -1
- package/dist/components/barchartv2/Barchart.component.js +0 -122
- package/dist/components/barchartv2/BarchartTooltip.d.ts.map +0 -1
- package/dist/components/barchartv2/utils.d.ts.map +0 -1
- package/dist/components/chartlegend/ChartLegend.d.ts.map +0 -1
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts.map +0 -1
- package/dist/components/charttooltip/ChartTooltip.d.ts.map +0 -1
- package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts +0 -23
- package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map +0 -1
- package/dist/components/globalhealthbar/GlobalHealthBar.component.js +0 -173
- package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts.map +0 -1
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts.map +0 -1
- package/dist/components/globalhealthbar/components/HealthBarXAxis.d.ts.map +0 -1
- package/dist/components/globalhealthbar/healthBarUtils.d.ts.map +0 -1
- package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts +0 -2
- package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts.map +0 -1
- package/dist/components/globalhealthbar/healthBarUtils.spec.js +0 -391
- package/dist/components/globalhealthbar/tooltip/index.d.ts +0 -8
- package/dist/components/globalhealthbar/tooltip/index.d.ts.map +0 -1
- package/dist/components/globalhealthbar/tooltip/index.js +0 -55
- package/dist/components/globalhealthbar/useHealthBarData.d.ts.map +0 -1
- package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts +0 -2
- package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts.map +0 -1
- package/dist/components/globalhealthbar/useHealthBarData.spec.js +0 -209
- package/dist/components/linetemporalchart/ChartUtil.d.ts +0 -41
- package/dist/components/linetemporalchart/ChartUtil.d.ts.map +0 -1
- package/dist/components/linetemporalchart/ChartUtil.js +0 -148
- package/dist/components/linetemporalchart/LineTemporalChart.component.d.ts +0 -46
- package/dist/components/linetemporalchart/LineTemporalChart.component.d.ts.map +0 -1
- package/dist/components/linetemporalchart/LineTemporalChart.component.js +0 -579
- package/dist/components/linetemporalchart/MetricTimespanProvider.d.ts.map +0 -1
- package/dist/components/linetemporalchart/tooltip/index.d.ts +0 -30
- package/dist/components/linetemporalchart/tooltip/index.d.ts.map +0 -1
- package/dist/components/linetemporalchart/tooltip/index.js +0 -104
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +0 -1
- package/dist/components/linetimeseriechart/utils.d.ts +0 -16
- package/dist/components/linetimeseriechart/utils.d.ts.map +0 -1
- package/dist/components/sparkline/sparkline.component.d.ts +0 -17
- package/dist/components/sparkline/sparkline.component.d.ts.map +0 -1
- package/dist/components/vegachartv2/SyncedCursorCharts.d.ts +0 -12
- package/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map +0 -1
- package/dist/components/vegachartv2/SyncedCursorCharts.js +0 -15
- package/dist/components/vegachartv2/VegaChartV2.component.d.ts +0 -15
- package/dist/components/vegachartv2/VegaChartV2.component.d.ts.map +0 -1
- package/dist/components/vegachartv2/VegaChartV2.component.js +0 -218
- package/src/lib/components/barchart/BarChart.component.tsx +0 -51
- package/src/lib/components/globalhealthbar/GlobalHealthBar.component.tsx +0 -204
- package/src/lib/components/globalhealthbar/tooltip/index.ts +0 -72
- package/src/lib/components/linetemporalchart/ChartUtil.test.ts +0 -250
- package/src/lib/components/linetemporalchart/ChartUtil.ts +0 -225
- package/src/lib/components/linetemporalchart/LineTemporalChart.component.tsx +0 -800
- package/src/lib/components/linetemporalchart/tooltip/index.ts +0 -178
- package/src/lib/components/sparkline/sparkline.component.tsx +0 -56
- package/src/lib/components/vegachartv2/SyncedCursorCharts.tsx +0 -28
- package/src/lib/components/vegachartv2/VegaChartV2.component.tsx +0 -276
- package/stories/barchart.stories.tsx +0 -142
- package/stories/globalhealthbar.stories.tsx +0 -191
- package/stories/guideline/mdxExampleComponents.tsx +0 -57
- package/stories/linecharttemporal.stories.tsx +0 -88
- /package/dist/components/{linetemporalchart/MetricTimespanProvider.js → charts/MetricsTimeSpanProvider.js} +0 -0
- /package/dist/components/{globalhealthbar/useHealthBarData.js → charts/globalhealthbar/GlobalHealthBar.hooks.js} +0 -0
- /package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/HealthBarXAxis.d.ts +0 -0
- /package/dist/components/{chartlegend → charts/legend}/ChartLegendWrapper.js +0 -0
- /package/src/lib/components/{linetemporalchart/MetricTimespanProvider.tsx → charts/MetricsTimeSpanProvider.tsx} +0 -0
- /package/src/lib/components/{barchartv2 → charts/barchart}/BarchartTooltip.test.tsx +0 -0
- /package/src/lib/components/{globalhealthbar/useHealthBarData.ts → charts/globalhealthbar/GlobalHealthBar.hooks.ts} +0 -0
- /package/src/lib/components/{chartlegend → charts/legend}/ChartLegend.test.tsx +0 -0
- /package/src/lib/components/{chartlegend → charts/legend}/ChartLegendWrapper.test.tsx +0 -0
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
Middleware,
|
|
11
11
|
} from '@floating-ui/react';
|
|
12
12
|
import styled from 'styled-components';
|
|
13
|
-
import { spacing } from '
|
|
14
|
-
import { fontSize, fontWeight } from '
|
|
15
|
-
import { FormattedDateTime } from '
|
|
13
|
+
import { spacing } from '../../../spacing';
|
|
14
|
+
import { fontSize, fontWeight } from '../../../style/theme';
|
|
15
|
+
import { FormattedDateTime } from '../../date/FormattedDateTime';
|
|
16
|
+
import { getTooltipDateFormat } from './chartUtils';
|
|
16
17
|
|
|
17
18
|
export const ChartTooltipContainer = styled.div`
|
|
18
19
|
border: 1px solid ${({ theme }) => theme.border};
|
|
@@ -106,25 +107,17 @@ export type TooltipDateFormat =
|
|
|
106
107
|
| 'day-month-abbreviated-hour-minute-second'
|
|
107
108
|
| 'day-month-abbreviated-hour-minute';
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
duration: number,
|
|
111
|
-
) => {
|
|
112
|
-
if (duration <= 60 * 60) {
|
|
113
|
-
return 'day-month-abbreviated-hour-minute-second';
|
|
114
|
-
} else if (duration <= 7 * 24 * 60 * 60) {
|
|
115
|
-
return 'day-month-abbreviated-hour-minute';
|
|
116
|
-
} else {
|
|
117
|
-
return 'day-month-abbreviated-year-hour-minute';
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export const TooltipHeader = ({
|
|
122
|
-
duration,
|
|
123
|
-
value,
|
|
124
|
-
}: {
|
|
110
|
+
export type TooltipHeaderProps = {
|
|
125
111
|
duration: number;
|
|
126
112
|
value: string | number;
|
|
127
|
-
}
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Tooltip header component
|
|
116
|
+
* @param duration - Duration in seconds
|
|
117
|
+
* @param value - Value to format
|
|
118
|
+
* @returns Formatted string type
|
|
119
|
+
*/
|
|
120
|
+
export const TooltipHeader = ({ duration, value }: TooltipHeaderProps) => {
|
|
128
121
|
const timeFormat = getTooltipDateFormat(duration);
|
|
129
122
|
return (
|
|
130
123
|
<ChartTooltipHeader>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { ResponsiveContainer } from 'recharts';
|
|
2
|
+
import styled, { useTheme } from 'styled-components';
|
|
3
|
+
import { spacing, Stack, Wrap } from '../../../spacing';
|
|
4
|
+
import { Box } from '../../box/Box';
|
|
5
|
+
import { ConstrainedText } from '../../constrainedtext/Constrainedtext.component';
|
|
6
|
+
import { FormattedDateTime } from '../../date/FormattedDateTime';
|
|
7
|
+
import { IconHelp } from '../../iconhelper/IconHelper';
|
|
8
|
+
import { Loader } from '../../loader/Loader.component';
|
|
9
|
+
import { Text } from '../../text/Text.component';
|
|
10
|
+
import { formatXAxisDate, maxWidthTooltip } from './chartUtils';
|
|
11
|
+
import { TimeType } from '../types';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Styled ResponsiveContainer for charts
|
|
15
|
+
* Shared by Barchart and LineTimeSerieChart
|
|
16
|
+
* Ensures tooltip overflow is visible and removes outline
|
|
17
|
+
*/
|
|
18
|
+
export const StyledResponsiveContainer = styled(ResponsiveContainer)`
|
|
19
|
+
// Avoid tooltip over constrained text to be cut off
|
|
20
|
+
& .recharts-surface {
|
|
21
|
+
outline: none;
|
|
22
|
+
overflow: visible;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
interface ChartLoadingOrErrorProps {
|
|
27
|
+
height: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Error state component for charts
|
|
32
|
+
*/
|
|
33
|
+
export const ChartError = ({ height }: ChartLoadingOrErrorProps) => {
|
|
34
|
+
return (
|
|
35
|
+
<Box
|
|
36
|
+
height={height}
|
|
37
|
+
style={{
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
justifyContent: 'center',
|
|
40
|
+
display: 'flex',
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
<Text>Chart data is not available</Text>
|
|
44
|
+
</Box>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Loading state component for charts
|
|
50
|
+
*/
|
|
51
|
+
export const ChartLoading = ({ height }: ChartLoadingOrErrorProps) => {
|
|
52
|
+
return (
|
|
53
|
+
<Box
|
|
54
|
+
height={height}
|
|
55
|
+
style={{
|
|
56
|
+
alignItems: 'center',
|
|
57
|
+
justifyContent: 'center',
|
|
58
|
+
display: 'flex',
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<Loader size="larger" children={<Text>Loading Chart Data...</Text>} />
|
|
62
|
+
</Box>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
interface ChartHeaderProps {
|
|
67
|
+
title?: string;
|
|
68
|
+
secondaryTitle?: string;
|
|
69
|
+
helpTooltip?: React.ReactNode;
|
|
70
|
+
rightTitle?: React.ReactNode;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Shared chart header component
|
|
75
|
+
* Used by Barchart and can be used by other charts
|
|
76
|
+
*/
|
|
77
|
+
export const ChartHeader = ({
|
|
78
|
+
title,
|
|
79
|
+
secondaryTitle,
|
|
80
|
+
helpTooltip,
|
|
81
|
+
rightTitle,
|
|
82
|
+
}: ChartHeaderProps) => {
|
|
83
|
+
return (
|
|
84
|
+
<Wrap>
|
|
85
|
+
<Stack gap="r4">
|
|
86
|
+
<Text variant="ChartTitle">{title}</Text>
|
|
87
|
+
{helpTooltip && (
|
|
88
|
+
<IconHelp
|
|
89
|
+
tooltipMessage={helpTooltip}
|
|
90
|
+
overlayStyle={maxWidthTooltip}
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
{secondaryTitle && (
|
|
95
|
+
<Text
|
|
96
|
+
color="textSecondary"
|
|
97
|
+
style={{
|
|
98
|
+
marginLeft: spacing.r8,
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
{secondaryTitle}
|
|
102
|
+
</Text>
|
|
103
|
+
)}
|
|
104
|
+
</Stack>
|
|
105
|
+
|
|
106
|
+
{rightTitle && <Text>{rightTitle}</Text>}
|
|
107
|
+
</Wrap>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
interface CustomTickProps {
|
|
112
|
+
x: number;
|
|
113
|
+
y: number;
|
|
114
|
+
payload: {
|
|
115
|
+
value: number;
|
|
116
|
+
};
|
|
117
|
+
visibleTicksCount: number;
|
|
118
|
+
width: number;
|
|
119
|
+
type: TimeType;
|
|
120
|
+
tickWidthOffset?: number;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Custom tick component for charts
|
|
125
|
+
* Used by Barchart for time-based x-axis ticks
|
|
126
|
+
*/
|
|
127
|
+
export const CustomTick = ({
|
|
128
|
+
x,
|
|
129
|
+
y,
|
|
130
|
+
payload,
|
|
131
|
+
visibleTicksCount,
|
|
132
|
+
width,
|
|
133
|
+
type,
|
|
134
|
+
tickWidthOffset = 4,
|
|
135
|
+
}: CustomTickProps) => {
|
|
136
|
+
const theme = useTheme();
|
|
137
|
+
const tickWidth = width / visibleTicksCount - tickWidthOffset;
|
|
138
|
+
const centerX = x - tickWidth / 2;
|
|
139
|
+
|
|
140
|
+
const duration =
|
|
141
|
+
type.type === 'time'
|
|
142
|
+
? (type.timeRange.endDate.getTime() -
|
|
143
|
+
type.timeRange.startDate.getTime()) /
|
|
144
|
+
1000
|
|
145
|
+
: 0;
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<foreignObject
|
|
149
|
+
x={centerX}
|
|
150
|
+
y={y - 10}
|
|
151
|
+
width={tickWidth}
|
|
152
|
+
color={theme.textSecondary}
|
|
153
|
+
overflow="visible"
|
|
154
|
+
>
|
|
155
|
+
<ConstrainedText
|
|
156
|
+
color="textSecondary"
|
|
157
|
+
text={
|
|
158
|
+
<Text variant="Smaller">
|
|
159
|
+
{type.type === 'time' ? (
|
|
160
|
+
<FormattedDateTime
|
|
161
|
+
format={formatXAxisDate(duration)}
|
|
162
|
+
value={new Date(payload.value)}
|
|
163
|
+
/>
|
|
164
|
+
) : (
|
|
165
|
+
String(payload.value)
|
|
166
|
+
)}
|
|
167
|
+
</Text>
|
|
168
|
+
}
|
|
169
|
+
centered
|
|
170
|
+
tooltipStyle={{
|
|
171
|
+
backgroundColor: theme.backgroundLevel1,
|
|
172
|
+
padding: spacing.r10,
|
|
173
|
+
borderRadius: spacing.r8,
|
|
174
|
+
border: `1px solid ${theme.border}`,
|
|
175
|
+
position: 'absolute',
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</foreignObject>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getRoundReferenceValue,
|
|
3
|
+
getTicks,
|
|
4
|
+
getUnitLabel,
|
|
5
|
+
addMissingDataPoint,
|
|
6
|
+
formatXAxisDate,
|
|
7
|
+
normalizeChartDataWithUnits,
|
|
8
|
+
getTooltipDateFormat,
|
|
9
|
+
} from './chartUtils';
|
|
10
|
+
import { NAN_STRING } from '../../constants';
|
|
11
|
+
import { UnitRange } from '../types';
|
|
12
|
+
|
|
13
|
+
describe('getRoundReferenceValue', () => {
|
|
14
|
+
it('should return appropriate rounded values with 10% buffer', () => {
|
|
15
|
+
// Small values (< 10)
|
|
16
|
+
expect(getRoundReferenceValue(0.1)).toBe(0.1); // 0.1 → 0.11 → 0.1 (magnitude 0.1, remainder 0.01)
|
|
17
|
+
expect(getRoundReferenceValue(1)).toBe(1); // 1 → 1.1 → 1 (magnitude 1, remainder 0.1)
|
|
18
|
+
expect(getRoundReferenceValue(2)).toBe(2); // 2 → 2.2 → 2 (magnitude 1, remainder 0.2)
|
|
19
|
+
expect(getRoundReferenceValue(3)).toBe(3); // 3 → 3.3 → 3 (magnitude 1, remainder 0.3)
|
|
20
|
+
|
|
21
|
+
// Values 5-10 range
|
|
22
|
+
expect(getRoundReferenceValue(6)).toBe(6); // 6 → 6.6 → 6 (magnitude 1, remainder 0.6)
|
|
23
|
+
expect(getRoundReferenceValue(9)).toBe(9); // 9 → 9.9 → 9 (magnitude 1, remainder 0.9)
|
|
24
|
+
|
|
25
|
+
// Larger values get 10% buffer applied
|
|
26
|
+
expect(getRoundReferenceValue(15)).toBe(10); // 15 → 16.5, remainder 5, incremented 20 > 16.5, so round down to 10
|
|
27
|
+
expect(getRoundReferenceValue(35)).toBe(30); // 35 → 38.5, remainder 5, incremented 40 > 38.5, so round down to 30
|
|
28
|
+
expect(getRoundReferenceValue(75)).toBe(80); // 75 → 82.5, remainder 5, incremented 80 <= 82.5, so round up to 80
|
|
29
|
+
expect(getRoundReferenceValue(150)).toBe(150); // 150 → 165, remainder 0, so return 150
|
|
30
|
+
expect(getRoundReferenceValue(350)).toBe(350); // 350 → 385, remainder 0, so return 350
|
|
31
|
+
expect(getRoundReferenceValue(750)).toBe(750); // 750 → 825, remainder 0, so return 750
|
|
32
|
+
expect(getRoundReferenceValue(1500)).toBe(1500); // 1500 → 1650, remainder 0, so return 1500
|
|
33
|
+
expect(getRoundReferenceValue(3500)).toBe(3500); // 3500 → 3850, remainder 0, so return 3500
|
|
34
|
+
expect(getRoundReferenceValue(7500)).toBe(7500); // 7500 → 8250, remainder 0, so return 7500
|
|
35
|
+
expect(getRoundReferenceValue(15000)).toBe(15000); // 15000 → 16500, remainder 0, so return 15000
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('getTicks', () => {
|
|
40
|
+
it('should return ticks for small values < 10', () => {
|
|
41
|
+
// Non-symmetrical ticks
|
|
42
|
+
expect(getTicks(1, false)).toEqual([0, 0.5, 1]); // 1 % 2 != 0, defaults to 3 ticks
|
|
43
|
+
expect(getTicks(2, false)).toEqual([0, 1, 2]); // 2 % (3-1) == 0, uses 3 ticks
|
|
44
|
+
expect(getTicks(5, false)).toEqual([0, 2.5, 5]); // 5 % 2 != 0 and 5 % 3 != 0, defaults to 3 ticks
|
|
45
|
+
expect(getTicks(10, false)).toEqual([0, 5, 10]); // 10 % 2 == 0, uses 3 ticks
|
|
46
|
+
expect(getTicks(15, false)).toEqual([0, 5, 10, 15]); // 15 % 3= 0, uses 4 ticks
|
|
47
|
+
expect(getTicks(20, false)).toEqual([0, 10, 20]); // 20 % 2 == 0, uses 3 ticks
|
|
48
|
+
expect(getTicks(250, false)).toEqual([0, 125, 250]); // 250 % 3 = 0, uses 3 ticks
|
|
49
|
+
// Symmetrical ticks
|
|
50
|
+
expect(getTicks(1, true)).toEqual([-1, -0.5, 0, 0.5, 1]); // 1 % 2 != 0, defaults to 3 ticks, symmetrical adds negatives
|
|
51
|
+
expect(getTicks(2, true)).toEqual([-2, -1, 0, 1, 2]); // 2 % (3-1) == 0, uses 3 ticks, symmetrical adds negatives
|
|
52
|
+
expect(getTicks(5, true)).toEqual([-5, -2.5, 0, 2.5, 5]); // 5 % 2 != 0 and 5 % 3 != 0, defaults to 3 ticks, symmetrical adds negatives
|
|
53
|
+
expect(getTicks(10, true)).toEqual([-10, -5, 0, 5, 10]); // 10 % 2 == 0, uses 3 ticks, symmetrical adds negatives
|
|
54
|
+
expect(getTicks(15, true)).toEqual([-15, -10, -5, 0, 5, 10, 15]); // 15 % 3 = 0, uses 4 ticks, symmetrical adds negatives
|
|
55
|
+
expect(getTicks(20, true)).toEqual([-20, -10, 0, 10, 20]); // 20 % 2 == 0, uses 3 ticks, symmetrical adds negatives
|
|
56
|
+
expect(getTicks(250, true)).toEqual([-250, -125, 0, 125, 250]); // 250 % 3 = 0, uses 3 ticks, symmetrical adds negatives
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should generate evenly spaced ticks for larger values', () => {
|
|
60
|
+
const ticks = getTicks(100, false);
|
|
61
|
+
expect(ticks).toHaveLength(3);
|
|
62
|
+
expect(ticks[0]).toBe(0);
|
|
63
|
+
expect(ticks[ticks.length - 1]).toBe(100);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('getUnitLabel', () => {
|
|
68
|
+
const unitRange: UnitRange = [
|
|
69
|
+
{ threshold: 1, label: 'B' },
|
|
70
|
+
{ threshold: 1000, label: 'KB' },
|
|
71
|
+
{ threshold: 1000000, label: 'MB' },
|
|
72
|
+
{ threshold: 1000000000, label: 'GB' },
|
|
73
|
+
];
|
|
74
|
+
it('should return correct unit label and threshold', () => {
|
|
75
|
+
const result = getUnitLabel(unitRange, 500);
|
|
76
|
+
expect(result).toEqual({ valueBase: 1, unitLabel: 'B' });
|
|
77
|
+
const result2 = getUnitLabel(unitRange, 500000);
|
|
78
|
+
expect(result2).toEqual({ valueBase: 1000, unitLabel: 'KB' });
|
|
79
|
+
const result3 = getUnitLabel(unitRange, 500000000);
|
|
80
|
+
expect(result3).toEqual({ valueBase: 1000000, unitLabel: 'MB' });
|
|
81
|
+
const result4 = getUnitLabel(unitRange, 500000000000);
|
|
82
|
+
expect(result4).toEqual({ valueBase: 1000000000, unitLabel: 'GB' });
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should return correct unit for medium values even if range is disordered', () => {
|
|
86
|
+
const unsortedRange = [
|
|
87
|
+
{ threshold: 1000000, label: 'MB' },
|
|
88
|
+
{ threshold: 1000, label: 'KB' },
|
|
89
|
+
{ threshold: 1000000000, label: 'GB' },
|
|
90
|
+
{ threshold: 1, label: 'B' },
|
|
91
|
+
];
|
|
92
|
+
const result = getUnitLabel(unsortedRange, 50000);
|
|
93
|
+
expect(result).toEqual({ valueBase: 1000, unitLabel: 'KB' });
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('addMissingDataPoint', () => {
|
|
98
|
+
it('should return empty array for invalid inputs', () => {
|
|
99
|
+
expect(addMissingDataPoint([], 0, 100, 10)).toEqual([]);
|
|
100
|
+
expect(addMissingDataPoint([[10, 5]], undefined, 100, 10)).toEqual([]);
|
|
101
|
+
expect(addMissingDataPoint([[10, 5]], 0, 0, 10)).toEqual([]);
|
|
102
|
+
expect(addMissingDataPoint([[10, 5]], -1, 100, 10)).toEqual([]);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should add missing data points at the beginning', () => {
|
|
106
|
+
const original: [number, number][] = [
|
|
107
|
+
[20, 5],
|
|
108
|
+
[30, 10],
|
|
109
|
+
];
|
|
110
|
+
const result = addMissingDataPoint(original, 0, 100, 10);
|
|
111
|
+
|
|
112
|
+
expect(result[0]).toEqual([0, NAN_STRING]);
|
|
113
|
+
expect(result[1]).toEqual([10, NAN_STRING]);
|
|
114
|
+
expect(result[2]).toEqual([20, 5]);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should add missing data points in the middle', () => {
|
|
118
|
+
const original: [number, number][] = [
|
|
119
|
+
[0, 5],
|
|
120
|
+
[30, 10],
|
|
121
|
+
];
|
|
122
|
+
const result = addMissingDataPoint(original, 0, 100, 10);
|
|
123
|
+
|
|
124
|
+
expect(result[0]).toEqual([0, 5]);
|
|
125
|
+
expect(result[1]).toEqual([10, NAN_STRING]);
|
|
126
|
+
expect(result[2]).toEqual([20, NAN_STRING]);
|
|
127
|
+
expect(result[3]).toEqual([30, 10]);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should add missing data points at the end', () => {
|
|
131
|
+
const original: [number, number][] = [
|
|
132
|
+
[0, 5],
|
|
133
|
+
[10, 10],
|
|
134
|
+
];
|
|
135
|
+
const result = addMissingDataPoint(original, 0, 40, 10);
|
|
136
|
+
|
|
137
|
+
expect(result[result.length - 3]).toEqual([10, 10]);
|
|
138
|
+
expect(result[result.length - 2]).toEqual([20, NAN_STRING]);
|
|
139
|
+
expect(result[result.length - 1]).toEqual([30, NAN_STRING]);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle data points with null values', () => {
|
|
143
|
+
const original: [number, number | null][] = [
|
|
144
|
+
[0, 5],
|
|
145
|
+
[10, null],
|
|
146
|
+
[20, 10],
|
|
147
|
+
];
|
|
148
|
+
const result = addMissingDataPoint(original, 0, 30, 10);
|
|
149
|
+
|
|
150
|
+
expect(result).toEqual([
|
|
151
|
+
[0, 5],
|
|
152
|
+
[10, null],
|
|
153
|
+
[20, 10],
|
|
154
|
+
]);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should handle string values', () => {
|
|
158
|
+
const original: [number, string][] = [
|
|
159
|
+
[0, '5'],
|
|
160
|
+
[10, '10'],
|
|
161
|
+
];
|
|
162
|
+
const result = addMissingDataPoint(original, 0, 30, 10);
|
|
163
|
+
|
|
164
|
+
expect(result[0]).toEqual([0, '5']);
|
|
165
|
+
expect(result[1]).toEqual([10, '10']);
|
|
166
|
+
expect(result[2]).toEqual([20, NAN_STRING]);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('formatXAxisDate', () => {
|
|
171
|
+
const ONE_DAY = 24 * 60 * 60;
|
|
172
|
+
const ONE_WEEK = 7 * ONE_DAY;
|
|
173
|
+
|
|
174
|
+
it('should return "time" for durations <= 1 day', () => {
|
|
175
|
+
expect(formatXAxisDate(ONE_DAY)).toBe('time');
|
|
176
|
+
expect(formatXAxisDate(ONE_DAY / 2)).toBe('time');
|
|
177
|
+
expect(formatXAxisDate(1000)).toBe('time');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should return "day-month-abbreviated" for durations <= 1 week', () => {
|
|
181
|
+
expect(formatXAxisDate(ONE_DAY * 2)).toBe('day-month-abbreviated');
|
|
182
|
+
expect(formatXAxisDate(ONE_WEEK - 1000)).toBe('day-month-abbreviated');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should return "chart-long-term-date" for durations > 1 week', () => {
|
|
186
|
+
expect(formatXAxisDate(ONE_WEEK + 1000)).toBe('chart-long-term-date');
|
|
187
|
+
expect(formatXAxisDate(ONE_DAY * 30)).toBe('chart-long-term-date');
|
|
188
|
+
expect(formatXAxisDate(ONE_DAY * 365)).toBe('chart-long-term-date');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('getTooltipDateFormat', () => {
|
|
193
|
+
it('should return "day-month-abbreviated-hour-minute-second" for durations <= 1 hour', () => {
|
|
194
|
+
expect(getTooltipDateFormat(60)).toBe(
|
|
195
|
+
'day-month-abbreviated-hour-minute-second',
|
|
196
|
+
);
|
|
197
|
+
expect(getTooltipDateFormat(60 * 40)).toBe(
|
|
198
|
+
'day-month-abbreviated-hour-minute-second',
|
|
199
|
+
);
|
|
200
|
+
expect(getTooltipDateFormat(60 * 60)).toBe(
|
|
201
|
+
'day-month-abbreviated-hour-minute-second',
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
it('should return "day-month-abbreviated-hour-minute" for durations <= 7 days', () => {
|
|
205
|
+
expect(getTooltipDateFormat(60 * 60 * 2)).toBe(
|
|
206
|
+
'day-month-abbreviated-hour-minute',
|
|
207
|
+
);
|
|
208
|
+
expect(getTooltipDateFormat(60 * 60 * 24)).toBe(
|
|
209
|
+
'day-month-abbreviated-hour-minute',
|
|
210
|
+
);
|
|
211
|
+
expect(getTooltipDateFormat(60 * 60 * 24 * 7)).toBe(
|
|
212
|
+
'day-month-abbreviated-hour-minute',
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
it('should return "day-month-abbreviated-year-hour-minute" for durations > 7 days', () => {
|
|
216
|
+
expect(getTooltipDateFormat(60 * 60 * 24 * 7.1)).toBe(
|
|
217
|
+
'day-month-abbreviated-year-hour-minute',
|
|
218
|
+
);
|
|
219
|
+
expect(getTooltipDateFormat(60 * 60 * 24 * 30)).toBe(
|
|
220
|
+
'day-month-abbreviated-year-hour-minute',
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('normalizeChartDataWithUnits', () => {
|
|
226
|
+
describe('with Barchart (category as excludeKey)', () => {
|
|
227
|
+
it('should compute unit label and normalize data when unit range is provided', () => {
|
|
228
|
+
const data = [
|
|
229
|
+
{ category: 'category1', success: 1680 },
|
|
230
|
+
{ category: 'category2', success: 2000 },
|
|
231
|
+
];
|
|
232
|
+
const maxValue = 2000;
|
|
233
|
+
const unitRange: UnitRange = [{ threshold: 1000, label: 'kB' }];
|
|
234
|
+
|
|
235
|
+
const result = normalizeChartDataWithUnits(
|
|
236
|
+
data,
|
|
237
|
+
maxValue,
|
|
238
|
+
unitRange,
|
|
239
|
+
'category',
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
expect(result.unitLabel).toBe('kB');
|
|
243
|
+
// 2000 / 1000 = 2 → getRoundReferenceValue(2) = 2
|
|
244
|
+
expect(result.topValue).toBe(2);
|
|
245
|
+
expect(result.rechartsData).toEqual([
|
|
246
|
+
{ category: 'category1', success: 1.68 },
|
|
247
|
+
{ category: 'category2', success: 2 },
|
|
248
|
+
]);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should handle threshold of 0 (bytes)', () => {
|
|
252
|
+
const data = [{ category: 'category1', success: 680 }];
|
|
253
|
+
const maxValue = 680;
|
|
254
|
+
const unitRange: UnitRange = [
|
|
255
|
+
{ threshold: 0, label: 'B' },
|
|
256
|
+
{ threshold: 1000, label: 'kB' },
|
|
257
|
+
];
|
|
258
|
+
|
|
259
|
+
const result = normalizeChartDataWithUnits(
|
|
260
|
+
data,
|
|
261
|
+
maxValue,
|
|
262
|
+
unitRange,
|
|
263
|
+
'category',
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
expect(result.unitLabel).toBe('B');
|
|
267
|
+
// 680 / 1 = 680 → getRoundReferenceValue(680) = 680
|
|
268
|
+
expect(result.topValue).toBe(680);
|
|
269
|
+
expect(result.rechartsData).toEqual([
|
|
270
|
+
{ category: 'category1', success: 680 },
|
|
271
|
+
]);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should not normalize when no unit range provided', () => {
|
|
275
|
+
const data = [
|
|
276
|
+
{ category: 'A', value: 100 },
|
|
277
|
+
{ category: 'B', value: 200 },
|
|
278
|
+
];
|
|
279
|
+
const maxValue = 200;
|
|
280
|
+
|
|
281
|
+
const result = normalizeChartDataWithUnits(
|
|
282
|
+
data,
|
|
283
|
+
maxValue,
|
|
284
|
+
undefined,
|
|
285
|
+
'category',
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
expect(result.unitLabel).toBeUndefined();
|
|
289
|
+
// 200 → getRoundReferenceValue(200) = 200
|
|
290
|
+
expect(result.topValue).toBe(200);
|
|
291
|
+
expect(result.rechartsData).toEqual(data);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('should exclude category key from normalization', () => {
|
|
295
|
+
const data = [{ category: 1000, value: 1000 }];
|
|
296
|
+
const maxValue = 1000;
|
|
297
|
+
const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
|
|
298
|
+
|
|
299
|
+
const result = normalizeChartDataWithUnits(
|
|
300
|
+
data,
|
|
301
|
+
maxValue,
|
|
302
|
+
unitRange,
|
|
303
|
+
'category',
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
// category should remain unchanged (1000, not normalized to 1)
|
|
307
|
+
expect(result.rechartsData[0].category).toBe(1000);
|
|
308
|
+
// value should be normalized
|
|
309
|
+
expect(result.rechartsData[0].value).toBe(1);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
describe('with LineTimeSerieChart (timestamp as excludeKey)', () => {
|
|
314
|
+
it('should normalize data and exclude timestamp', () => {
|
|
315
|
+
const data = [
|
|
316
|
+
{ timestamp: 1634567890000, metric1: 5000, metric2: 3000 },
|
|
317
|
+
{ timestamp: 1634567900000, metric1: 6000, metric2: 4000 },
|
|
318
|
+
];
|
|
319
|
+
const maxValue = 6000;
|
|
320
|
+
const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
|
|
321
|
+
|
|
322
|
+
const result = normalizeChartDataWithUnits(
|
|
323
|
+
data,
|
|
324
|
+
maxValue,
|
|
325
|
+
unitRange,
|
|
326
|
+
'timestamp',
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
expect(result.unitLabel).toBe('k');
|
|
330
|
+
// 6000 / 1000 = 6 → getRoundReferenceValue(6) = 6
|
|
331
|
+
expect(result.topValue).toBe(6);
|
|
332
|
+
expect(result.rechartsData).toEqual([
|
|
333
|
+
{ timestamp: 1634567890000, metric1: 5, metric2: 3 },
|
|
334
|
+
{ timestamp: 1634567900000, metric1: 6, metric2: 4 },
|
|
335
|
+
]);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should handle multiple metrics with timestamp', () => {
|
|
339
|
+
const data = [{ timestamp: 100, cpu: 2500, memory: 1500 }];
|
|
340
|
+
const maxValue = 2500;
|
|
341
|
+
const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
|
|
342
|
+
|
|
343
|
+
const result = normalizeChartDataWithUnits(
|
|
344
|
+
data,
|
|
345
|
+
maxValue,
|
|
346
|
+
unitRange,
|
|
347
|
+
'timestamp',
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
expect(result.rechartsData[0].timestamp).toBe(100); // unchanged
|
|
351
|
+
expect(result.rechartsData[0].cpu).toBe(2.5); // normalized
|
|
352
|
+
expect(result.rechartsData[0].memory).toBe(1.5); // normalized
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
describe('edge cases', () => {
|
|
357
|
+
it('should handle empty data array', () => {
|
|
358
|
+
const result = normalizeChartDataWithUnits([], 0, undefined, 'category');
|
|
359
|
+
|
|
360
|
+
expect(result.unitLabel).toBeUndefined();
|
|
361
|
+
expect(result.topValue).toBe(1); // Default for 0
|
|
362
|
+
expect(result.rechartsData).toEqual([]);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should handle data with only exclude key', () => {
|
|
366
|
+
const data = [{ category: 'A' }, { category: 'B' }];
|
|
367
|
+
const result = normalizeChartDataWithUnits(
|
|
368
|
+
data,
|
|
369
|
+
10,
|
|
370
|
+
undefined,
|
|
371
|
+
'category',
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
expect(result.rechartsData).toEqual(data);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('should handle mixed string and number values', () => {
|
|
378
|
+
const data = [{ category: 'test', value1: 1000, value2: 'text' }];
|
|
379
|
+
const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
|
|
380
|
+
|
|
381
|
+
const result = normalizeChartDataWithUnits(
|
|
382
|
+
data,
|
|
383
|
+
1000,
|
|
384
|
+
unitRange,
|
|
385
|
+
'category',
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
expect(result.rechartsData[0].value1).toBe(1); // normalized
|
|
389
|
+
expect(result.rechartsData[0].value2).toBe('text'); // unchanged
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should handle empty unit range array', () => {
|
|
393
|
+
const data = [{ category: 'A', value: 100 }];
|
|
394
|
+
const result = normalizeChartDataWithUnits(data, 100, [], 'category');
|
|
395
|
+
|
|
396
|
+
expect(result.unitLabel).toBeUndefined();
|
|
397
|
+
// 100 → getRoundReferenceValue(100) = 100
|
|
398
|
+
expect(result.topValue).toBe(100);
|
|
399
|
+
expect(result.rechartsData).toEqual(data);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
});
|