@scality/core-ui 0.161.0 → 0.163.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/README.md +15 -15
- package/dist/components/accordion/Accordion.component.d.ts +0 -1
- package/dist/components/accordion/Accordion.component.d.ts.map +1 -1
- package/dist/components/barchartv2/Barchart.component.d.ts +53 -0
- package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -0
- package/dist/components/barchartv2/Barchart.component.js +86 -0
- package/dist/components/barchartv2/utils.d.ts +118 -0
- package/dist/components/barchartv2/utils.d.ts.map +1 -0
- package/dist/components/barchartv2/utils.js +337 -0
- package/dist/components/buttonv2/Buttonv2.component.d.ts +1 -1
- package/dist/components/buttonv2/Buttonv2.component.d.ts.map +1 -1
- package/dist/components/chartlegend/ChartLegend.d.ts +8 -0
- package/dist/components/chartlegend/ChartLegend.d.ts.map +1 -0
- package/dist/components/chartlegend/ChartLegend.js +65 -0
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts +17 -0
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts.map +1 -0
- package/dist/components/chartlegend/ChartLegendWrapper.js +50 -0
- package/dist/components/constrainedtext/Constrainedtext.component.d.ts +2 -1
- package/dist/components/constrainedtext/Constrainedtext.component.d.ts.map +1 -1
- package/dist/components/constrainedtext/Constrainedtext.component.js +5 -4
- package/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts +0 -1
- package/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts.map +1 -1
- package/dist/components/date/FormattedDateTime.d.ts +4 -1
- package/dist/components/date/FormattedDateTime.d.ts.map +1 -1
- package/dist/components/date/FormattedDateTime.js +24 -1
- package/dist/components/date/FormattedDateTime.spec.js +12 -0
- package/dist/components/emptytable/Emptytable.component.d.ts +0 -1
- package/dist/components/emptytable/Emptytable.component.d.ts.map +1 -1
- package/dist/components/emptytable/Emptytable.component.js +1 -0
- package/dist/components/error-pages/ErrorPage401.component.d.ts +0 -1
- package/dist/components/error-pages/ErrorPage401.component.d.ts.map +1 -1
- package/dist/components/error-pages/ErrorPage404.component.d.ts +0 -1
- package/dist/components/error-pages/ErrorPage404.component.d.ts.map +1 -1
- package/dist/components/error-pages/ErrorPage500.component.d.ts +0 -1
- package/dist/components/error-pages/ErrorPage500.component.d.ts.map +1 -1
- package/dist/components/error-pages/ErrorPageAuth.component.d.ts.map +1 -1
- package/dist/components/form/Form.component.d.ts +2 -2
- package/dist/components/form/Form.component.d.ts.map +1 -1
- package/dist/components/icon/Icon.component.d.ts +5 -5
- package/dist/components/icon/Icon.component.d.ts.map +1 -1
- package/dist/components/icon/Icon.component.js +33 -31
- package/dist/components/infomessage/InfoMessage.component.d.ts +0 -1
- package/dist/components/infomessage/InfoMessage.component.d.ts.map +1 -1
- package/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts.map +1 -1
- package/dist/components/layout/Layout.component.d.ts.map +1 -1
- package/dist/components/layout/v2/panels.d.ts.map +1 -1
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +33 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.js +249 -0
- package/dist/components/modal/Modal.component.js +2 -2
- package/dist/components/navbar/Navbar.component.js +2 -2
- package/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts +0 -1
- package/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts.map +1 -1
- package/dist/components/searchinput/SearchInput.component.d.ts +1 -2
- package/dist/components/searchinput/SearchInput.component.d.ts.map +1 -1
- package/dist/components/selectv2/Selectv2.component.d.ts +5 -5
- package/dist/components/selectv2/Selectv2.component.d.ts.map +1 -1
- package/dist/components/selectv2/Selectv2.component.js +11 -6
- package/dist/components/statuswrapper/Statuswrapper.component.d.ts +0 -1
- package/dist/components/statuswrapper/Statuswrapper.component.d.ts.map +1 -1
- package/dist/components/steppers/Stepper.component.d.ts.map +1 -1
- package/dist/components/steppers/Stepper.component.js +9 -8
- package/dist/components/tablev2/Search.js +2 -2
- package/dist/components/tablev2/SingleSelectableContent.d.ts +1 -2
- package/dist/components/tablev2/SingleSelectableContent.d.ts.map +1 -1
- package/dist/components/tablev2/TableCommon.d.ts +2 -2
- package/dist/components/tablev2/TableCommon.d.ts.map +1 -1
- package/dist/components/tablev2/TableSync.d.ts +8 -0
- package/dist/components/tablev2/TableSync.d.ts.map +1 -0
- package/dist/components/tablev2/TableSync.js +11 -0
- package/dist/components/tablev2/Tablev2.component.d.ts +2 -1
- package/dist/components/tablev2/Tablev2.component.d.ts.map +1 -1
- package/dist/components/tablev2/Tablev2.component.js +10 -9
- package/dist/components/tabsv2/ScrollButton.d.ts +1 -2
- package/dist/components/tabsv2/ScrollButton.d.ts.map +1 -1
- package/dist/components/tabsv2/ScrollButton.js +2 -2
- package/dist/components/tabsv2/Tabsv2.component.d.ts +2 -2
- package/dist/components/tabsv2/Tabsv2.component.d.ts.map +1 -1
- package/dist/components/tabsv2/Tabsv2.component.js +2 -2
- package/dist/components/text/Text.component.d.ts +0 -1
- package/dist/components/text/Text.component.d.ts.map +1 -1
- package/dist/components/textarea/TextArea.component.d.ts +3 -3
- package/dist/components/textarea/TextArea.component.d.ts.map +1 -1
- package/dist/components/textbadge/TextBadge.component.d.ts +0 -1
- package/dist/components/textbadge/TextBadge.component.d.ts.map +1 -1
- package/dist/components/toast/Toast.component.d.ts +1 -1
- package/dist/components/toast/Toast.component.d.ts.map +1 -1
- package/dist/components/toast/ToastProvider.d.ts.map +1 -1
- package/dist/components/toast/ToastProvider.js +4 -5
- package/dist/components/vegachartv2/SyncedCursorCharts.d.ts +1 -2
- package/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map +1 -1
- package/dist/components/vegachartv2/SyncedCursorCharts.js +3 -5
- package/dist/components/vegachartv2/VegaChartV2.component.d.ts +1 -2
- package/dist/components/vegachartv2/VegaChartV2.component.d.ts.map +1 -1
- package/dist/components/vegachartv2/VegaChartV2.component.js +2 -2
- package/dist/icons/branding.d.ts.map +1 -1
- package/dist/icons/scality-loading.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/next.d.ts +2 -0
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +2 -0
- package/dist/style/theme.d.ts +20 -0
- package/dist/style/theme.d.ts.map +1 -1
- package/dist/style/theme.js +46 -1
- package/package.json +7 -4
- package/setupTests.js +6 -0
- package/src/lib/components/accordion/Accordion.component.tsx +1 -1
- package/src/lib/components/accordion/Accordion.test.tsx +7 -15
- package/src/lib/components/barchartv2/Barchart.component.test.tsx +364 -0
- package/src/lib/components/barchartv2/Barchart.component.tsx +321 -0
- package/src/lib/components/barchartv2/utils.test.ts +899 -0
- package/src/lib/components/barchartv2/utils.ts +534 -0
- package/src/lib/components/buttonv2/Buttonv2.component.tsx +1 -1
- package/src/lib/components/chartlegend/ChartLegend.tsx +113 -0
- package/src/lib/components/chartlegend/ChartLegendWrapper.tsx +85 -0
- package/src/lib/components/constrainedtext/Constrainedtext.component.tsx +22 -3
- package/src/lib/components/coreuithemeprovider/CoreUiThemeProvider.tsx +0 -1
- package/src/lib/components/date/FormattedDateTime.spec.tsx +24 -0
- package/src/lib/components/date/FormattedDateTime.tsx +42 -2
- package/src/lib/components/emptytable/Emptytable.component.tsx +1 -1
- package/src/lib/components/error-pages/ErrorPage401.component.tsx +0 -1
- package/src/lib/components/error-pages/ErrorPage404.component.tsx +0 -1
- package/src/lib/components/error-pages/ErrorPage500.component.tsx +0 -1
- package/src/lib/components/error-pages/ErrorPageAuth.component.tsx +0 -1
- package/src/lib/components/form/Form.component.tsx +1 -1
- package/src/lib/components/healthselectorv2/HealthSelector.component.test.tsx +3 -3
- package/src/lib/components/icon/Icon.component.tsx +48 -60
- package/src/lib/components/infomessage/InfoMessage.component.tsx +0 -1
- package/src/lib/components/inlineinput/InlineInput.test.tsx +22 -19
- package/src/lib/components/inputlist/InputList.test.tsx +21 -19
- package/src/lib/components/lateralnavbarlayout/LateralNavbarLayout.component.tsx +0 -1
- package/src/lib/components/layout/Layout.component.tsx +0 -1
- package/src/lib/components/layout/v2/panels.tsx +1 -1
- package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +502 -0
- package/src/lib/components/modal/Modal.component.tsx +2 -2
- package/src/lib/components/navbar/Navbar.component.tsx +2 -2
- package/src/lib/components/scrollbarwrapper/ScrollbarWrapper.component.tsx +0 -1
- package/src/lib/components/searchinput/SearchInput.component.tsx +0 -1
- package/src/lib/components/searchinput/SearchInput.test.tsx +3 -7
- package/src/lib/components/selectv2/Selectv2.component.tsx +24 -14
- package/src/lib/components/selectv2/selectv2.test.tsx +62 -57
- package/src/lib/components/sidebar/Sidebar.component.tsx +1 -1
- package/src/lib/components/statuswrapper/Statuswrapper.component.tsx +0 -1
- package/src/lib/components/steppers/Stepper.component.tsx +10 -8
- package/src/lib/components/tablev2/Search.tsx +2 -2
- package/src/lib/components/tablev2/SingleSelectableContent.tsx +2 -2
- package/src/lib/components/tablev2/TableCommon.tsx +1 -1
- package/src/lib/components/tablev2/TableSync.test.tsx +28 -0
- package/src/lib/components/tablev2/TableSync.tsx +36 -0
- package/src/lib/components/tablev2/Tablev2.component.tsx +11 -9
- package/src/lib/components/tablev2/Tablev2.test.tsx +36 -37
- package/src/lib/components/tabsv2/ScrollButton.tsx +2 -2
- package/src/lib/components/tabsv2/Tabsv2.component.tsx +6 -6
- package/src/lib/components/text/Text.component.tsx +4 -5
- package/src/lib/components/textarea/TextArea.component.tsx +3 -2
- package/src/lib/components/textbadge/TextBadge.component.tsx +0 -1
- package/src/lib/components/toast/Toast.component.tsx +1 -1
- package/src/lib/components/toast/ToastProvider.tsx +17 -7
- package/src/lib/components/vegachartv2/SyncedCursorCharts.tsx +5 -7
- package/src/lib/components/vegachartv2/VegaChartV2.component.tsx +2 -2
- package/src/lib/icons/branding.tsx +0 -2
- package/src/lib/icons/scality-loading.tsx +0 -2
- package/src/lib/index.ts +1 -0
- package/src/lib/next.ts +6 -0
- package/src/lib/style/theme.ts +53 -1
- package/stories/BarChart/barchart.stories.tsx +822 -0
- package/stories/areachart.stories.tsx +0 -1
- package/stories/format.mdx +4 -2
- package/stories/linetimeseriechart.stories.tsx +485 -0
- package/stories/tablev2.stories.tsx +41 -0
- package/tsconfig.json +5 -2
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
import { coreUIAvailableThemes } from '../../style/theme';
|
|
2
|
+
import {
|
|
3
|
+
applySortingToData,
|
|
4
|
+
computeUnitLabelAndRoundReferenceValue,
|
|
5
|
+
filterChartDataAndBarsByLegendSelection,
|
|
6
|
+
formatPrometheusDataToRechartsDataAndBars,
|
|
7
|
+
getMaxBarValue,
|
|
8
|
+
getRoundReferenceValue,
|
|
9
|
+
renderTooltipContent,
|
|
10
|
+
sortStackedBars,
|
|
11
|
+
transformCategoryData,
|
|
12
|
+
transformTimeData,
|
|
13
|
+
UnitRange,
|
|
14
|
+
} from './utils';
|
|
15
|
+
|
|
16
|
+
// Mock theme object for tests
|
|
17
|
+
const mockTheme = {
|
|
18
|
+
statusHealthy: '#00D100',
|
|
19
|
+
statusHealthyRGB: '0, 209, 0',
|
|
20
|
+
statusCritical: '#D10000',
|
|
21
|
+
statusCriticalRGB: '209, 0, 0',
|
|
22
|
+
statusWarning: '#FFA500',
|
|
23
|
+
statusWarningRGB: '255, 165, 0',
|
|
24
|
+
selectedActive: '#337FBD',
|
|
25
|
+
highlight: '#337FBD',
|
|
26
|
+
border: '#C2C8CC',
|
|
27
|
+
buttonPrimary: '#337FBD',
|
|
28
|
+
buttonSecondary: '#68737D',
|
|
29
|
+
buttonDelete: '#EF3340',
|
|
30
|
+
infoPrimary: '#337FBD',
|
|
31
|
+
infoSecondary: '#68737D',
|
|
32
|
+
backgroundLevel1: '#ffffff',
|
|
33
|
+
backgroundLevel2: '#F9FAFB',
|
|
34
|
+
backgroundLevel3: '#E9EBED',
|
|
35
|
+
backgroundLevel4: '#D8DCDE',
|
|
36
|
+
textPrimary: '#2F3941',
|
|
37
|
+
textSecondary: '#68737D',
|
|
38
|
+
textTertiary: '#87929D',
|
|
39
|
+
textReverse: '#ffffff',
|
|
40
|
+
textLink: '#337FBD',
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
describe('transformTimeData', () => {
|
|
44
|
+
it('should transform time data with daily intervals', () => {
|
|
45
|
+
const bars = [
|
|
46
|
+
{
|
|
47
|
+
label: 'Success',
|
|
48
|
+
data: [
|
|
49
|
+
[new Date('2024-07-05T00:00:00'), 10],
|
|
50
|
+
[new Date('2024-07-06T00:00:00'), 20],
|
|
51
|
+
] as [Date, number][],
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const type = {
|
|
56
|
+
type: 'time' as const,
|
|
57
|
+
timeRange: {
|
|
58
|
+
startDate: new Date('2024-07-05T00:00:00'),
|
|
59
|
+
endDate: new Date('2024-07-06T00:00:00'),
|
|
60
|
+
interval: 24 * 60 * 60 * 1000, // 1 day
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const barDataKeys = ['Success'];
|
|
65
|
+
|
|
66
|
+
const result = transformTimeData(bars, type, barDataKeys);
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual([
|
|
69
|
+
{ category: 'Fri05Jul', Success: 10 },
|
|
70
|
+
{ category: 'Sat06Jul', Success: 20 },
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should create empty time slots when data is missing', () => {
|
|
75
|
+
const bars = [
|
|
76
|
+
{
|
|
77
|
+
label: 'Success',
|
|
78
|
+
data: [
|
|
79
|
+
[new Date('2024-07-05T00:00:00'), 10],
|
|
80
|
+
// Missing July 6th
|
|
81
|
+
[new Date('2024-07-07T00:00:00'), 30],
|
|
82
|
+
] as [Date, number][],
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
const type = {
|
|
87
|
+
type: 'time' as const,
|
|
88
|
+
timeRange: {
|
|
89
|
+
startDate: new Date('2024-07-05T00:00:00'),
|
|
90
|
+
endDate: new Date('2024-07-07T00:00:00'),
|
|
91
|
+
interval: 24 * 60 * 60 * 1000, // 1 day
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const barDataKeys = ['Success'];
|
|
96
|
+
|
|
97
|
+
const result = transformTimeData(bars, type, barDataKeys);
|
|
98
|
+
|
|
99
|
+
expect(result).toEqual([
|
|
100
|
+
{ category: 'Fri05Jul', Success: 10 },
|
|
101
|
+
{ category: 'Sat06Jul', Success: 0 }, // Missing data filled with 0
|
|
102
|
+
{ category: 'Sun07Jul', Success: 30 },
|
|
103
|
+
]);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should handle hourly intervals correctly', () => {
|
|
107
|
+
const bars = [
|
|
108
|
+
{
|
|
109
|
+
label: 'Success',
|
|
110
|
+
data: [
|
|
111
|
+
[new Date('2024-07-05T10:00:00'), 10],
|
|
112
|
+
[new Date('2024-07-05T11:00:00'), 20],
|
|
113
|
+
] as [Date, number][],
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
const type = {
|
|
118
|
+
type: 'time' as const,
|
|
119
|
+
timeRange: {
|
|
120
|
+
startDate: new Date('2024-07-05T10:00:00'),
|
|
121
|
+
endDate: new Date('2024-07-05T11:00:00'),
|
|
122
|
+
interval: 60 * 60 * 1000, // 1 hour
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const barDataKeys = ['Success'];
|
|
127
|
+
|
|
128
|
+
const result = transformTimeData(bars, type, barDataKeys);
|
|
129
|
+
|
|
130
|
+
expect(result).toEqual([
|
|
131
|
+
{ category: '10:00', Success: 10 },
|
|
132
|
+
{ category: '11:00', Success: 20 },
|
|
133
|
+
]);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should use latest value when multiple events occur in same time period', () => {
|
|
137
|
+
const bars = [
|
|
138
|
+
{
|
|
139
|
+
label: 'Success',
|
|
140
|
+
data: [
|
|
141
|
+
[new Date('2024-07-05T08:30:00'), 10], // 8:30 AM
|
|
142
|
+
[new Date('2024-07-05T14:45:00'), 25], // 2:45 PM (should overwrite 8:30 AM)
|
|
143
|
+
[new Date('2024-07-06T09:15:00'), 15], // Next day
|
|
144
|
+
] as [Date, number][],
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
const type = {
|
|
149
|
+
type: 'time' as const,
|
|
150
|
+
timeRange: {
|
|
151
|
+
startDate: new Date('2024-07-05T00:00:00'),
|
|
152
|
+
endDate: new Date('2024-07-06T00:00:00'),
|
|
153
|
+
interval: 24 * 60 * 60 * 1000, // 1 day
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const barDataKeys = ['Success'];
|
|
158
|
+
|
|
159
|
+
const result = transformTimeData(bars, type, barDataKeys);
|
|
160
|
+
|
|
161
|
+
expect(result).toEqual([
|
|
162
|
+
{ category: 'Fri05Jul', Success: 25 }, // Last value for July 5th
|
|
163
|
+
{ category: 'Sat06Jul', Success: 15 }, // July 6th value
|
|
164
|
+
]);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should preserve chronological order regardless of input order', () => {
|
|
168
|
+
const bars = [
|
|
169
|
+
{
|
|
170
|
+
label: 'Success',
|
|
171
|
+
data: [
|
|
172
|
+
[new Date('2024-07-07T10:00:00'), 30], // July 7th (latest)
|
|
173
|
+
[new Date('2024-07-05T08:00:00'), 10], // July 5th (earliest)
|
|
174
|
+
[new Date('2024-07-06T14:00:00'), 20], // July 6th (middle)
|
|
175
|
+
] as [Date, number][],
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
const type = {
|
|
180
|
+
type: 'time' as const,
|
|
181
|
+
timeRange: {
|
|
182
|
+
startDate: new Date('2024-07-05T00:00:00'),
|
|
183
|
+
endDate: new Date('2024-07-07T00:00:00'),
|
|
184
|
+
interval: 24 * 60 * 60 * 1000, // 1 day
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const barDataKeys = ['Success'];
|
|
189
|
+
|
|
190
|
+
const result = transformTimeData(bars, type, barDataKeys);
|
|
191
|
+
|
|
192
|
+
// Should be in chronological order regardless of input order
|
|
193
|
+
expect(result).toEqual([
|
|
194
|
+
{ category: 'Fri05Jul', Success: 10 },
|
|
195
|
+
{ category: 'Sat06Jul', Success: 20 },
|
|
196
|
+
{ category: 'Sun07Jul', Success: 30 },
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should display multiple metrics with different time coverage', () => {
|
|
201
|
+
const bars = [
|
|
202
|
+
{
|
|
203
|
+
label: 'Success',
|
|
204
|
+
data: [[new Date('2024-07-05T00:00:00'), 10]] as [Date, number][],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
label: 'Failed',
|
|
208
|
+
data: [[new Date('2024-07-06T00:00:00'), 5]] as [Date, number][],
|
|
209
|
+
},
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
const type = {
|
|
213
|
+
type: 'time' as const,
|
|
214
|
+
timeRange: {
|
|
215
|
+
startDate: new Date('2024-07-05T00:00:00'),
|
|
216
|
+
endDate: new Date('2024-07-06T00:00:00'),
|
|
217
|
+
interval: 24 * 60 * 60 * 1000, // 1 day
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const barDataKeys = ['Success', 'Failed'];
|
|
222
|
+
|
|
223
|
+
const result = transformTimeData(bars, type, barDataKeys);
|
|
224
|
+
|
|
225
|
+
expect(result).toEqual([
|
|
226
|
+
{ category: 'Fri05Jul', Success: 10, Failed: 0 },
|
|
227
|
+
{ category: 'Sat06Jul', Success: 0, Failed: 5 },
|
|
228
|
+
]);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('transformCategoryData', () => {
|
|
233
|
+
it('should transform basic category data correctly', () => {
|
|
234
|
+
const bars = [
|
|
235
|
+
{
|
|
236
|
+
label: 'Success',
|
|
237
|
+
data: [
|
|
238
|
+
['category1', 10],
|
|
239
|
+
['category2', 20],
|
|
240
|
+
] as [string, number][],
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
label: 'Failed',
|
|
244
|
+
data: [
|
|
245
|
+
['category1', 5],
|
|
246
|
+
['category2', 15],
|
|
247
|
+
] as [string, number][],
|
|
248
|
+
},
|
|
249
|
+
];
|
|
250
|
+
|
|
251
|
+
const barDataKeys = ['Success', 'Failed'];
|
|
252
|
+
|
|
253
|
+
const result = transformCategoryData(bars, barDataKeys);
|
|
254
|
+
|
|
255
|
+
expect(result).toEqual([
|
|
256
|
+
{ category: 'category1', Success: 10, Failed: 5 },
|
|
257
|
+
{ category: 'category2', Success: 20, Failed: 15 },
|
|
258
|
+
]);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('should show zero for categories missing in specific metrics', () => {
|
|
262
|
+
const bars = [
|
|
263
|
+
{
|
|
264
|
+
label: 'Success',
|
|
265
|
+
data: [
|
|
266
|
+
['category1', 10],
|
|
267
|
+
['category3', 30],
|
|
268
|
+
] as [string, number][],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
label: 'Failed',
|
|
272
|
+
data: [
|
|
273
|
+
['category2', 20],
|
|
274
|
+
['category3', 40],
|
|
275
|
+
] as [string, number][],
|
|
276
|
+
},
|
|
277
|
+
];
|
|
278
|
+
|
|
279
|
+
const barDataKeys = ['Success', 'Failed'];
|
|
280
|
+
|
|
281
|
+
const result = transformCategoryData(bars, barDataKeys);
|
|
282
|
+
|
|
283
|
+
expect(result).toEqual([
|
|
284
|
+
{ category: 'category1', Success: 10, Failed: 0 }, // Failed missing, filled with 0
|
|
285
|
+
{ category: 'category3', Success: 30, Failed: 40 }, // Appears in both bars
|
|
286
|
+
{ category: 'category2', Success: 0, Failed: 20 }, // Success missing, filled with 0
|
|
287
|
+
]);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('should handle single bar data', () => {
|
|
291
|
+
const bars = [
|
|
292
|
+
{
|
|
293
|
+
label: 'Metric',
|
|
294
|
+
data: [
|
|
295
|
+
['A', 100],
|
|
296
|
+
['B', 200],
|
|
297
|
+
['C', 300],
|
|
298
|
+
] as [string, number][],
|
|
299
|
+
},
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
const barDataKeys = ['Metric'];
|
|
303
|
+
|
|
304
|
+
const result = transformCategoryData(bars, barDataKeys);
|
|
305
|
+
|
|
306
|
+
expect(result).toEqual([
|
|
307
|
+
{ category: 'A', Metric: 100 },
|
|
308
|
+
{ category: 'B', Metric: 200 },
|
|
309
|
+
{ category: 'C', Metric: 300 },
|
|
310
|
+
]);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('should convert category keys to strings', () => {
|
|
314
|
+
const bars = [
|
|
315
|
+
{
|
|
316
|
+
label: 'Count',
|
|
317
|
+
data: [
|
|
318
|
+
[123, 10], // Number key
|
|
319
|
+
['text', 20], // String key
|
|
320
|
+
[null, 30], // Null key
|
|
321
|
+
] as [any, number][],
|
|
322
|
+
},
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
const barDataKeys = ['Count'];
|
|
326
|
+
|
|
327
|
+
const result = transformCategoryData(bars, barDataKeys);
|
|
328
|
+
|
|
329
|
+
expect(result).toEqual([
|
|
330
|
+
{ category: '123', Count: 10 },
|
|
331
|
+
{ category: 'text', Count: 20 },
|
|
332
|
+
{ category: 'null', Count: 30 },
|
|
333
|
+
]);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('should handle empty data gracefully', () => {
|
|
337
|
+
const bars = [
|
|
338
|
+
{
|
|
339
|
+
label: 'Empty',
|
|
340
|
+
data: [] as [string, number][],
|
|
341
|
+
},
|
|
342
|
+
];
|
|
343
|
+
|
|
344
|
+
const barDataKeys = ['Empty'];
|
|
345
|
+
|
|
346
|
+
const result = transformCategoryData(bars, barDataKeys);
|
|
347
|
+
|
|
348
|
+
expect(result).toEqual([]);
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
describe('applySortingToData', () => {
|
|
353
|
+
it('should apply custom sorting function to data', () => {
|
|
354
|
+
const data = [
|
|
355
|
+
{ category: 'category1', Success: 50 },
|
|
356
|
+
{ category: 'category2', Success: 20 },
|
|
357
|
+
{ category: 'category3', Success: 30 },
|
|
358
|
+
{ category: 'category4', Success: 40 },
|
|
359
|
+
];
|
|
360
|
+
|
|
361
|
+
const barDataKeys = ['Success'];
|
|
362
|
+
|
|
363
|
+
// Sort by Success value ascending
|
|
364
|
+
const defaultSort = (pointA: any, pointB: any) => {
|
|
365
|
+
return pointA.Success - pointB.Success > 0 ? 1 : -1;
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const result = applySortingToData(data, barDataKeys, defaultSort);
|
|
369
|
+
|
|
370
|
+
expect(result).toEqual([
|
|
371
|
+
{ category: 'category2', Success: 20 },
|
|
372
|
+
{ category: 'category3', Success: 30 },
|
|
373
|
+
{ category: 'category4', Success: 40 },
|
|
374
|
+
{ category: 'category1', Success: 50 },
|
|
375
|
+
]);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('should sort categories based on combined metric values', () => {
|
|
379
|
+
const data = [
|
|
380
|
+
{ category: 'A', Bar1: 10, Bar2: 50 },
|
|
381
|
+
{ category: 'B', Bar1: 30, Bar2: 20 },
|
|
382
|
+
{ category: 'C', Bar1: 20, Bar2: 40 },
|
|
383
|
+
];
|
|
384
|
+
|
|
385
|
+
const barDataKeys = ['Bar1', 'Bar2'];
|
|
386
|
+
|
|
387
|
+
// Sort by sum of Bar1 and Bar2
|
|
388
|
+
const defaultSort = (pointA: any, pointB: any) => {
|
|
389
|
+
const sumA = pointA.Bar1 + pointA.Bar2;
|
|
390
|
+
const sumB = pointB.Bar1 + pointB.Bar2;
|
|
391
|
+
return sumA < sumB ? -1 : sumA > sumB ? 1 : 0;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
const result = applySortingToData(data, barDataKeys, defaultSort);
|
|
395
|
+
|
|
396
|
+
expect(result).toEqual([
|
|
397
|
+
{ category: 'B', Bar1: 30, Bar2: 20 }, // Sum: 50
|
|
398
|
+
{ category: 'A', Bar1: 10, Bar2: 50 }, // Sum: 60
|
|
399
|
+
{ category: 'C', Bar1: 20, Bar2: 40 }, // Sum: 60
|
|
400
|
+
]);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('should sort text numbers as numeric values', () => {
|
|
404
|
+
const data = [
|
|
405
|
+
{ category: 'A', Value: '100' },
|
|
406
|
+
{ category: 'B', Value: '50' },
|
|
407
|
+
{ category: 'C', Value: '75' },
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
const barDataKeys = ['Value'];
|
|
411
|
+
|
|
412
|
+
// Sort by numeric value descending
|
|
413
|
+
const defaultSort = (pointA: any, pointB: any) => {
|
|
414
|
+
return pointB.Value > pointA.Value
|
|
415
|
+
? 1
|
|
416
|
+
: pointB.Value < pointA.Value
|
|
417
|
+
? -1
|
|
418
|
+
: 0;
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const result = applySortingToData(data, barDataKeys, defaultSort);
|
|
422
|
+
|
|
423
|
+
expect(result).toEqual([
|
|
424
|
+
{ category: 'A', Value: 100 }, // Converted to number and sorted
|
|
425
|
+
{ category: 'C', Value: 75 },
|
|
426
|
+
{ category: 'B', Value: 50 },
|
|
427
|
+
]);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('should treat invalid data as zero when sorting', () => {
|
|
431
|
+
const data = [
|
|
432
|
+
{ category: 'A', Value: 30 },
|
|
433
|
+
{ category: 'B', Value: 0 }, // Test with 0 value
|
|
434
|
+
{ category: 'C', Value: 'NaN' }, // String that will become NaN
|
|
435
|
+
{ category: 'D', Value: 10 },
|
|
436
|
+
];
|
|
437
|
+
|
|
438
|
+
const barDataKeys = ['Value'];
|
|
439
|
+
|
|
440
|
+
// Sort by value ascending
|
|
441
|
+
const defaultSort = (pointA: any, pointB: any) => {
|
|
442
|
+
return pointA.Value < pointB.Value
|
|
443
|
+
? -1
|
|
444
|
+
: pointA.Value > pointB.Value
|
|
445
|
+
? 1
|
|
446
|
+
: 0;
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const result = applySortingToData(data, barDataKeys, defaultSort);
|
|
450
|
+
|
|
451
|
+
expect(result).toEqual([
|
|
452
|
+
{ category: 'B', Value: 0 }, // 0 value
|
|
453
|
+
{ category: 'C', Value: 0 }, // 'NaN' converted to 0 (NaN becomes 0)
|
|
454
|
+
{ category: 'D', Value: 10 },
|
|
455
|
+
{ category: 'A', Value: 30 },
|
|
456
|
+
]);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it('should preserve category data during sorting', () => {
|
|
460
|
+
const data = [
|
|
461
|
+
{ category: 'Category Z', Metric: 1 },
|
|
462
|
+
{ category: 'Category A', Metric: 3 },
|
|
463
|
+
{ category: 'Category M', Metric: 2 },
|
|
464
|
+
];
|
|
465
|
+
|
|
466
|
+
const barDataKeys = ['Metric'];
|
|
467
|
+
|
|
468
|
+
// Sort by category name alphabetically
|
|
469
|
+
const defaultSort = (pointA: any, pointB: any) => {
|
|
470
|
+
return pointA.category.localeCompare(pointB.category);
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const result = applySortingToData(data, barDataKeys, defaultSort);
|
|
474
|
+
|
|
475
|
+
expect(result).toEqual([
|
|
476
|
+
{ category: 'Category A', Metric: 3 },
|
|
477
|
+
{ category: 'Category M', Metric: 2 },
|
|
478
|
+
{ category: 'Category Z', Metric: 1 },
|
|
479
|
+
]);
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
describe('getRoundReferenceValue', () => {
|
|
484
|
+
it('should return appropriate rounded values', () => {
|
|
485
|
+
expect(getRoundReferenceValue(1)).toBe(1);
|
|
486
|
+
expect(getRoundReferenceValue(2)).toBe(2.5);
|
|
487
|
+
expect(getRoundReferenceValue(3)).toBe(5);
|
|
488
|
+
expect(getRoundReferenceValue(7)).toBe(10);
|
|
489
|
+
expect(getRoundReferenceValue(15)).toBe(25);
|
|
490
|
+
expect(getRoundReferenceValue(35)).toBe(50);
|
|
491
|
+
expect(getRoundReferenceValue(75)).toBe(100);
|
|
492
|
+
expect(getRoundReferenceValue(150)).toBe(250);
|
|
493
|
+
expect(getRoundReferenceValue(350)).toBe(500);
|
|
494
|
+
expect(getRoundReferenceValue(750)).toBe(1000);
|
|
495
|
+
expect(getRoundReferenceValue(1500)).toBe(2500);
|
|
496
|
+
expect(getRoundReferenceValue(3500)).toBe(5000);
|
|
497
|
+
expect(getRoundReferenceValue(7500)).toBe(10000);
|
|
498
|
+
expect(getRoundReferenceValue(15000)).toBe(25000);
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
describe('getMaxBarValue', () => {
|
|
503
|
+
it('should return the maximum value from chart data', () => {
|
|
504
|
+
const data = [
|
|
505
|
+
{ category: 'A', value1: 10, value2: 5 },
|
|
506
|
+
{ category: 'B', value1: 20, value2: 15 },
|
|
507
|
+
{ category: 'C', value1: 8, value2: 25 },
|
|
508
|
+
];
|
|
509
|
+
expect(getMaxBarValue(data)).toBe(25);
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
it('should handle single value data', () => {
|
|
513
|
+
const data = [{ category: 'A', value: 42 }];
|
|
514
|
+
expect(getMaxBarValue(data)).toBe(42);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it('should return the maximum value from stacked data', () => {
|
|
518
|
+
const data = [
|
|
519
|
+
{ category: 'A', value1: 10, value2: 5 },
|
|
520
|
+
{ category: 'B', value1: 20, value2: 15 },
|
|
521
|
+
{ category: 'C', value1: 8, value2: 25 },
|
|
522
|
+
];
|
|
523
|
+
expect(getMaxBarValue(data, true)).toBe(35);
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
describe('formatPrometheusDataToRechartsDataAndBars', () => {
|
|
528
|
+
it('should format category data correctly', () => {
|
|
529
|
+
const bars = [
|
|
530
|
+
{
|
|
531
|
+
label: 'Success',
|
|
532
|
+
data: [
|
|
533
|
+
['A', 10],
|
|
534
|
+
['B', 20],
|
|
535
|
+
] as [string, number][],
|
|
536
|
+
color: 'green',
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
label: 'Failed',
|
|
540
|
+
data: [
|
|
541
|
+
['A', 5],
|
|
542
|
+
['B', 15],
|
|
543
|
+
] as [string, number][],
|
|
544
|
+
color: 'red',
|
|
545
|
+
},
|
|
546
|
+
];
|
|
547
|
+
|
|
548
|
+
const result = formatPrometheusDataToRechartsDataAndBars(
|
|
549
|
+
bars,
|
|
550
|
+
'category',
|
|
551
|
+
{
|
|
552
|
+
Success: coreUIAvailableThemes.darkRebrand.statusHealthy,
|
|
553
|
+
Failed: coreUIAvailableThemes.darkRebrand.statusCritical,
|
|
554
|
+
},
|
|
555
|
+
true, // stacked
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
// Should integrate: data transformation + color formatting + stacked sorting
|
|
559
|
+
expect(result.data).toEqual([
|
|
560
|
+
{ category: 'A', Success: 10, Failed: 5 },
|
|
561
|
+
{ category: 'B', Success: 20, Failed: 15 },
|
|
562
|
+
]);
|
|
563
|
+
expect(result.rechartsBars).toEqual([
|
|
564
|
+
{ dataKey: 'Success', fill: '#0AADA6', stackId: 'stacked' }, // statusHealthy = '#0AADA6'
|
|
565
|
+
{ dataKey: 'Failed', fill: '#E84855', stackId: 'stacked' }, // statusCritical = '#E84855'
|
|
566
|
+
]);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('should format time data correctly', () => {
|
|
570
|
+
const bars = [
|
|
571
|
+
{
|
|
572
|
+
label: 'Success Count',
|
|
573
|
+
data: [[new Date('2024-07-05T00:00:00'), 10]] as [Date, number][],
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
label: 'Failed Count',
|
|
577
|
+
data: [[new Date('2024-07-05T00:00:00'), 5]] as [Date, number][],
|
|
578
|
+
},
|
|
579
|
+
];
|
|
580
|
+
|
|
581
|
+
const result = formatPrometheusDataToRechartsDataAndBars(
|
|
582
|
+
bars,
|
|
583
|
+
{
|
|
584
|
+
type: 'time',
|
|
585
|
+
timeRange: {
|
|
586
|
+
startDate: new Date('2024-07-05T00:00:00'),
|
|
587
|
+
endDate: new Date('2024-07-05T00:00:00'),
|
|
588
|
+
interval: 24 * 60 * 60 * 1000,
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
'Success Count': 'lineColor3',
|
|
593
|
+
'Failed Count': 'blue',
|
|
594
|
+
},
|
|
595
|
+
false,
|
|
596
|
+
undefined,
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
// Should integrate: time transformation + status color assignment
|
|
600
|
+
expect(result.data).toEqual([
|
|
601
|
+
{ category: 'Fri05Jul', 'Success Count': 10, 'Failed Count': 5 },
|
|
602
|
+
]);
|
|
603
|
+
expect(result.rechartsBars).toEqual([
|
|
604
|
+
{ dataKey: 'Success Count', fill: '#4BE4E2' }, // lineColor3
|
|
605
|
+
{ dataKey: 'Failed Count', fill: 'blue' }, // blue
|
|
606
|
+
]);
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
it('should integrate custom sorting with category data', () => {
|
|
610
|
+
const bars = [
|
|
611
|
+
{
|
|
612
|
+
label: 'Value',
|
|
613
|
+
data: [
|
|
614
|
+
['C', 30],
|
|
615
|
+
['A', 10],
|
|
616
|
+
['B', 20],
|
|
617
|
+
] as [string, number][],
|
|
618
|
+
},
|
|
619
|
+
];
|
|
620
|
+
|
|
621
|
+
const result = formatPrometheusDataToRechartsDataAndBars(
|
|
622
|
+
bars,
|
|
623
|
+
'category',
|
|
624
|
+
mockTheme,
|
|
625
|
+
false,
|
|
626
|
+
(pointA, pointB) => {
|
|
627
|
+
// Sort alphabetically by category
|
|
628
|
+
return String(pointA.category).localeCompare(
|
|
629
|
+
String(pointB.category),
|
|
630
|
+
) as -1 | 0 | 1;
|
|
631
|
+
},
|
|
632
|
+
);
|
|
633
|
+
|
|
634
|
+
// Should integrate: category transformation + custom sorting
|
|
635
|
+
expect(result.data.map((item) => item.category)).toEqual(['A', 'B', 'C']);
|
|
636
|
+
});
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
describe('computeUnitLabelAndRoundReferenceValue', () => {
|
|
640
|
+
it('should compute the unit label and round reference value correctly when reaching threshold', () => {
|
|
641
|
+
const data = [
|
|
642
|
+
{
|
|
643
|
+
category: 'category1',
|
|
644
|
+
success: 1680,
|
|
645
|
+
},
|
|
646
|
+
];
|
|
647
|
+
const maxValue = 1680;
|
|
648
|
+
const unitRange: UnitRange = [
|
|
649
|
+
{
|
|
650
|
+
threshold: 1000,
|
|
651
|
+
label: 'kB',
|
|
652
|
+
},
|
|
653
|
+
];
|
|
654
|
+
const result = computeUnitLabelAndRoundReferenceValue(
|
|
655
|
+
data,
|
|
656
|
+
maxValue,
|
|
657
|
+
unitRange,
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
expect(result.unitLabel).toBe('kB');
|
|
661
|
+
expect(result.roundReferenceValue).toBe(10);
|
|
662
|
+
expect(result.rechartsData).toEqual([
|
|
663
|
+
{
|
|
664
|
+
category: 'category1',
|
|
665
|
+
success: 1.68,
|
|
666
|
+
},
|
|
667
|
+
]);
|
|
668
|
+
});
|
|
669
|
+
it('should compute the unit label and round reference value correctly when threshold is 0', () => {
|
|
670
|
+
const data = [
|
|
671
|
+
{
|
|
672
|
+
category: 'category1',
|
|
673
|
+
success: 680,
|
|
674
|
+
},
|
|
675
|
+
];
|
|
676
|
+
const maxValue = 680;
|
|
677
|
+
const unitRange: UnitRange = [
|
|
678
|
+
{
|
|
679
|
+
threshold: 0,
|
|
680
|
+
label: 'B',
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
threshold: 1000,
|
|
684
|
+
label: 'kB',
|
|
685
|
+
},
|
|
686
|
+
];
|
|
687
|
+
const result = computeUnitLabelAndRoundReferenceValue(
|
|
688
|
+
data,
|
|
689
|
+
maxValue,
|
|
690
|
+
unitRange,
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
expect(result.unitLabel).toBe('B');
|
|
694
|
+
expect(result.roundReferenceValue).toBe(1000);
|
|
695
|
+
expect(result.rechartsData).toEqual([
|
|
696
|
+
{ category: 'category1', success: 680 },
|
|
697
|
+
]);
|
|
698
|
+
});
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
describe('sortStackedBars', () => {
|
|
702
|
+
const bars = [
|
|
703
|
+
{ dataKey: 'bar1', fill: 'blue' },
|
|
704
|
+
{ dataKey: 'bar2', fill: 'red' },
|
|
705
|
+
{ dataKey: 'bar3', fill: 'green' },
|
|
706
|
+
];
|
|
707
|
+
const data = [
|
|
708
|
+
{ bar1: 10, bar2: 20, bar3: 30 },
|
|
709
|
+
{ bar1: 40, bar2: 50, bar3: 60 },
|
|
710
|
+
{ bar1: 70, bar2: 80, bar3: 90 },
|
|
711
|
+
];
|
|
712
|
+
it('should sort bars by average values in descending order when stacked is true', () => {
|
|
713
|
+
const result = sortStackedBars(bars, data, true);
|
|
714
|
+
expect(result).toEqual([
|
|
715
|
+
{ dataKey: 'bar3', fill: 'green' },
|
|
716
|
+
{ dataKey: 'bar2', fill: 'red' },
|
|
717
|
+
{ dataKey: 'bar1', fill: 'blue' },
|
|
718
|
+
]);
|
|
719
|
+
});
|
|
720
|
+
it('should not sort bars when stacked is false', () => {
|
|
721
|
+
const result = sortStackedBars(bars, data, false);
|
|
722
|
+
expect(result).toEqual([
|
|
723
|
+
{ dataKey: 'bar1', fill: 'blue' },
|
|
724
|
+
{ dataKey: 'bar2', fill: 'red' },
|
|
725
|
+
{ dataKey: 'bar3', fill: 'green' },
|
|
726
|
+
]);
|
|
727
|
+
});
|
|
728
|
+
it('should not sort bars when stacked is undefined', () => {
|
|
729
|
+
const result = sortStackedBars(bars, data, undefined);
|
|
730
|
+
expect(result).toEqual([
|
|
731
|
+
{ dataKey: 'bar1', fill: 'blue' },
|
|
732
|
+
{ dataKey: 'bar2', fill: 'red' },
|
|
733
|
+
{ dataKey: 'bar3', fill: 'green' },
|
|
734
|
+
]);
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
describe('renderTooltipContent', () => {
|
|
739
|
+
it('should return null when active is false', () => {
|
|
740
|
+
const props = {
|
|
741
|
+
active: false,
|
|
742
|
+
payload: [],
|
|
743
|
+
label: 'test',
|
|
744
|
+
coordinate: { x: 0, y: 0 },
|
|
745
|
+
accessibilityLayer: false,
|
|
746
|
+
};
|
|
747
|
+
const result = renderTooltipContent(props, undefined, undefined);
|
|
748
|
+
expect(result).toBeNull();
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
it('should return null when tooltip is undefined', () => {
|
|
752
|
+
const props = {
|
|
753
|
+
active: true,
|
|
754
|
+
payload: [{ name: 'test', value: 10 }],
|
|
755
|
+
label: 'test',
|
|
756
|
+
coordinate: { x: 0, y: 0 },
|
|
757
|
+
accessibilityLayer: false,
|
|
758
|
+
};
|
|
759
|
+
const result = renderTooltipContent(props, undefined, 'test');
|
|
760
|
+
expect(result).toBeNull();
|
|
761
|
+
});
|
|
762
|
+
it('should call tooltip with the correct props', () => {
|
|
763
|
+
const tooltip = jest.fn();
|
|
764
|
+
const props = {
|
|
765
|
+
active: true,
|
|
766
|
+
payload: [
|
|
767
|
+
{ name: 'Success', value: 10 },
|
|
768
|
+
{ name: 'Failed', value: 20 },
|
|
769
|
+
],
|
|
770
|
+
label: 'Test',
|
|
771
|
+
coordinate: { x: 0, y: 0 },
|
|
772
|
+
accessibilityLayer: false,
|
|
773
|
+
};
|
|
774
|
+
renderTooltipContent(props, tooltip, 'Success');
|
|
775
|
+
expect(tooltip).toHaveBeenCalledWith({
|
|
776
|
+
category: 'Test',
|
|
777
|
+
values: [
|
|
778
|
+
{ label: 'Success', value: 10, isHovered: true },
|
|
779
|
+
{ label: 'Failed', value: 20, isHovered: false },
|
|
780
|
+
],
|
|
781
|
+
});
|
|
782
|
+
});
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
describe('filterChartDataAndBarsByLegendSelection', () => {
|
|
786
|
+
const mockChartData = [
|
|
787
|
+
{ category: 'Jan', Success: 10, Failed: 5, Warning: 3, Pending: 2 },
|
|
788
|
+
{ category: 'Feb', Success: 20, Failed: 8, Warning: 6, Pending: 4 },
|
|
789
|
+
{ category: 'Mar', Success: 15, Failed: 12, Warning: 9, Pending: 7 },
|
|
790
|
+
];
|
|
791
|
+
|
|
792
|
+
const mockRechartsBars = [
|
|
793
|
+
{ dataKey: 'Success', fill: '#00D100', stackId: undefined },
|
|
794
|
+
{ dataKey: 'Failed', fill: '#D10000', stackId: undefined },
|
|
795
|
+
{ dataKey: 'Warning', fill: '#FFA500', stackId: 'stacked' },
|
|
796
|
+
{ dataKey: 'Pending', fill: '#337FBD', stackId: 'stacked' },
|
|
797
|
+
];
|
|
798
|
+
|
|
799
|
+
it('should return all data and bars when no resources are selected (empty array)', () => {
|
|
800
|
+
const result = filterChartDataAndBarsByLegendSelection(
|
|
801
|
+
mockChartData,
|
|
802
|
+
mockRechartsBars,
|
|
803
|
+
[],
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
expect(result.filteredData).toEqual(mockChartData);
|
|
807
|
+
expect(result.filteredRechartsBars).toEqual(mockRechartsBars);
|
|
808
|
+
expect(result.filteredData).toHaveLength(3);
|
|
809
|
+
expect(result.filteredRechartsBars).toHaveLength(4);
|
|
810
|
+
// Verify all properties are preserved
|
|
811
|
+
expect(Object.keys(result.filteredData[0])).toEqual([
|
|
812
|
+
'category',
|
|
813
|
+
'Success',
|
|
814
|
+
'Failed',
|
|
815
|
+
'Warning',
|
|
816
|
+
'Pending',
|
|
817
|
+
]);
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
it('should return only selected resources in both data and bars when resources are selected', () => {
|
|
821
|
+
const selectedResources = ['Success', 'Warning'];
|
|
822
|
+
const result = filterChartDataAndBarsByLegendSelection(
|
|
823
|
+
mockChartData,
|
|
824
|
+
mockRechartsBars,
|
|
825
|
+
selectedResources,
|
|
826
|
+
);
|
|
827
|
+
|
|
828
|
+
expect(result.filteredData).toHaveLength(3);
|
|
829
|
+
expect(result.filteredData).toEqual([
|
|
830
|
+
{ category: 'Jan', Success: 10, Warning: 3 },
|
|
831
|
+
{ category: 'Feb', Success: 20, Warning: 6 },
|
|
832
|
+
{ category: 'Mar', Success: 15, Warning: 9 },
|
|
833
|
+
]);
|
|
834
|
+
|
|
835
|
+
expect(result.filteredRechartsBars).toHaveLength(2);
|
|
836
|
+
expect(result.filteredRechartsBars).toEqual([
|
|
837
|
+
{ dataKey: 'Success', fill: '#00D100', stackId: undefined },
|
|
838
|
+
{ dataKey: 'Warning', fill: '#FFA500', stackId: 'stacked' },
|
|
839
|
+
]);
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it('should return single resource when only one resource is selected', () => {
|
|
843
|
+
const selectedResources = ['Failed'];
|
|
844
|
+
const result = filterChartDataAndBarsByLegendSelection(
|
|
845
|
+
mockChartData,
|
|
846
|
+
mockRechartsBars,
|
|
847
|
+
selectedResources,
|
|
848
|
+
);
|
|
849
|
+
|
|
850
|
+
expect(result.filteredData).toHaveLength(3);
|
|
851
|
+
expect(result.filteredData).toEqual([
|
|
852
|
+
{ category: 'Jan', Failed: 5 },
|
|
853
|
+
{ category: 'Feb', Failed: 8 },
|
|
854
|
+
{ category: 'Mar', Failed: 12 },
|
|
855
|
+
]);
|
|
856
|
+
|
|
857
|
+
expect(result.filteredRechartsBars).toHaveLength(1);
|
|
858
|
+
expect(result.filteredRechartsBars).toEqual([
|
|
859
|
+
{ dataKey: 'Failed', fill: '#D10000', stackId: undefined },
|
|
860
|
+
]);
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
it('should handle empty data array', () => {
|
|
864
|
+
const result = filterChartDataAndBarsByLegendSelection(
|
|
865
|
+
[],
|
|
866
|
+
mockRechartsBars,
|
|
867
|
+
['Success'],
|
|
868
|
+
);
|
|
869
|
+
|
|
870
|
+
expect(result.filteredData).toEqual([]);
|
|
871
|
+
expect(result.filteredRechartsBars).toHaveLength(1);
|
|
872
|
+
expect(result.filteredRechartsBars).toEqual([
|
|
873
|
+
{ dataKey: 'Success', fill: '#00D100', stackId: undefined },
|
|
874
|
+
]);
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
it('should preserve order of selected resources based on data object keys', () => {
|
|
878
|
+
const selectedResources = ['Pending', 'Success', 'Failed']; // Different order
|
|
879
|
+
const result = filterChartDataAndBarsByLegendSelection(
|
|
880
|
+
mockChartData,
|
|
881
|
+
mockRechartsBars,
|
|
882
|
+
selectedResources,
|
|
883
|
+
);
|
|
884
|
+
|
|
885
|
+
// Should maintain the order they appear in selectedResources
|
|
886
|
+
expect(Object.keys(result.filteredData[0])).toEqual([
|
|
887
|
+
'category',
|
|
888
|
+
'Pending',
|
|
889
|
+
'Success',
|
|
890
|
+
'Failed',
|
|
891
|
+
]);
|
|
892
|
+
|
|
893
|
+
// Should maintain original bar order regardless of selection order
|
|
894
|
+
expect(result.filteredRechartsBars).toHaveLength(3);
|
|
895
|
+
expect(result.filteredRechartsBars[0].dataKey).toBe('Success');
|
|
896
|
+
expect(result.filteredRechartsBars[1].dataKey).toBe('Failed');
|
|
897
|
+
expect(result.filteredRechartsBars[2].dataKey).toBe('Pending');
|
|
898
|
+
});
|
|
899
|
+
});
|