mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
fix(Gauge): clearing previously set min and max values in a gauge chart sets the data labels to 0 (#36425)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
This commit is contained in:
@@ -281,6 +281,411 @@ describe('Echarts Gauge transformProps', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Min/Max calculation and axis labels', () => {
|
||||
const baseFormData: SqlaFormData = {
|
||||
datasource: '26__table',
|
||||
viz_type: VizType.Gauge,
|
||||
metric: 'count',
|
||||
adhocFilters: [],
|
||||
rowLimit: 10,
|
||||
startAngle: 225,
|
||||
endAngle: -45,
|
||||
colorScheme: 'SUPERSET_DEFAULT',
|
||||
fontSize: 14,
|
||||
numberFormat: 'SMART_NUMBER',
|
||||
valueFormatter: '{value}',
|
||||
showPointer: true,
|
||||
animation: true,
|
||||
showAxisTick: false,
|
||||
showSplitLine: false,
|
||||
splitNumber: 10,
|
||||
showProgress: true,
|
||||
overlap: true,
|
||||
roundCap: false,
|
||||
groupby: [],
|
||||
};
|
||||
|
||||
it('should use provided minVal and maxVal when valid numbers', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: 10,
|
||||
maxVal: 100,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 50 }, { count: 75 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(10);
|
||||
expect(series.max).toBe(100);
|
||||
});
|
||||
|
||||
it('should calculate min/max from data when minVal is null', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: null,
|
||||
maxVal: 100,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 20 }, { count: 80 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(100);
|
||||
});
|
||||
|
||||
it('should calculate min/max from data when maxVal is null', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: 0,
|
||||
maxVal: null,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 20 }, { count: 80 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(160);
|
||||
});
|
||||
|
||||
it('should calculate min/max from data when both are null', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: null,
|
||||
maxVal: null,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 15 }, { count: 45 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(90);
|
||||
});
|
||||
|
||||
it('should calculate min/max from data when minVal is empty string', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: '' as any,
|
||||
maxVal: 200,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 30 }, { count: 60 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(200);
|
||||
});
|
||||
|
||||
it('should calculate min/max from data when maxVal is invalid string', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: 0,
|
||||
maxVal: 'invalid' as any,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 25 }, { count: 75 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(150);
|
||||
});
|
||||
|
||||
it('should handle negative values in min/max calculation', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: null,
|
||||
maxVal: null,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: -20 }, { count: 40 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(-40);
|
||||
expect(series.max).toBe(80);
|
||||
});
|
||||
|
||||
it('should generate axis labels correctly based on min, max, and splitNumber', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: 0,
|
||||
maxVal: 100,
|
||||
splitNumber: 5,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 50 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(100);
|
||||
expect(series.splitNumber).toBe(5);
|
||||
expect(series.axisLabel).toBeDefined();
|
||||
expect(series.axisLabel.formatter).toBeDefined();
|
||||
});
|
||||
|
||||
it('should calculate axis label length correctly for different number formats', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: 0,
|
||||
maxVal: 1000,
|
||||
splitNumber: 10,
|
||||
numberFormat: ',d',
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 500 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.axisLabel).toBeDefined();
|
||||
expect(series.axisLabel.formatter).toBeDefined();
|
||||
expect(typeof series.axisLabel.formatter).toBe('function');
|
||||
});
|
||||
|
||||
it('should integrate interval bounds and colors with calculated min/max', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: null,
|
||||
maxVal: null,
|
||||
intervals: '20,60',
|
||||
intervalColorIndices: '1,2',
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 10 }, { count: 50 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(100);
|
||||
|
||||
const { axisLine } = series;
|
||||
expect(axisLine.lineStyle.color).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([expect.any(Number), expect.any(String)]),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle zero values in data correctly', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: null,
|
||||
maxVal: null,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 0 }, { count: 0 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(0);
|
||||
expect(series.max).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle string minVal/maxVal that can be converted to numbers', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: '10' as any,
|
||||
maxVal: '200' as any,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 50 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.min).toBe(10);
|
||||
expect(series.max).toBe(200);
|
||||
});
|
||||
|
||||
it('should handle different splitNumber values', () => {
|
||||
const formData: SqlaFormData = {
|
||||
...baseFormData,
|
||||
minVal: 0,
|
||||
maxVal: 100,
|
||||
splitNumber: 20,
|
||||
};
|
||||
const queriesData = [
|
||||
{
|
||||
colnames: ['count'],
|
||||
data: [{ count: 50 }],
|
||||
},
|
||||
];
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData,
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
const result = transformProps(chartProps as EchartsGaugeChartProps);
|
||||
const series = (result.echartOptions as any).series[0];
|
||||
|
||||
expect(series.splitNumber).toBe(20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getIntervalBoundsAndColors', () => {
|
||||
it('should generate correct interval bounds and colors', () => {
|
||||
const colorFn = CategoricalColorNamespace.getScale(
|
||||
|
||||
Reference in New Issue
Block a user