Skip to content

Commit 076f85d

Browse files
kgabryjeclaude
andcommitted
test(heatmap): add tests for tooltip displaying actual axis values
Add comprehensive tests to ensure the tooltip formatter correctly displays actual axis values instead of numeric indices. This prevents regression of the bug fixed in the previous commit where tooltips showed "0 (1)" instead of actual labels like "Monday (Morning)". Tests cover: - Tooltip displays actual axis values with alphabetical sorting - Tooltip works correctly with different sort orders (asc/desc) - Tooltip works correctly with value-based sorting - Percentage calculations use actual values when normalizeAcross is enabled - Tooltip handles numeric axes correctly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ffe60bd commit 076f85d

2 files changed

Lines changed: 175 additions & 11 deletions

File tree

superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
*/
1919
import {
2020
NumberFormats,
21-
QueryFormColumn,
22-
getColumnLabel,
2321
getMetricLabel,
2422
getSequentialSchemeRegistry,
2523
getTimeFormatter,
@@ -180,8 +178,6 @@ export default function transformProps(
180178
chartProps;
181179
const {
182180
bottomMargin,
183-
xAxis,
184-
groupby,
185181
linearColorScheme,
186182
leftMargin,
187183
legendType = 'continuous',
@@ -204,9 +200,6 @@ export default function transformProps(
204200
sortYAxis,
205201
} = formData;
206202
const metricLabel = getMetricLabel(metric);
207-
const xAxisLabel = getColumnLabel(xAxis);
208-
// groupby is overridden to be a single value
209-
const yAxisLabel = getColumnLabel(groupby as unknown as QueryFormColumn);
210203
const {
211204
data,
212205
colnames,
@@ -365,8 +358,8 @@ export default function transformProps(
365358
formatter: (params: CallbackDataParams) => {
366359
const totals = calculateTotals(
367360
data,
368-
xAxisLabel,
369-
yAxisLabel,
361+
xAxisColumnName,
362+
yAxisColumnName,
370363
metricLabel,
371364
);
372365
const paramsValue = params.value as (string | number)[];
@@ -392,10 +385,14 @@ export default function transformProps(
392385
let suffix = 'heatmap';
393386
if (typeof value === 'number') {
394387
if (normalizeAcross === 'x') {
395-
percentage = value / totals.x[String(xValue)];
388+
// Convert xValue to a key type (string or number) for totals lookup
389+
const xKey = xValue as string | number;
390+
percentage = value / totals.x[xKey];
396391
suffix = formattedX;
397392
} else if (normalizeAcross === 'y') {
398-
percentage = value / totals.y[String(yValue)];
393+
// Convert yValue to a key type (string or number) for totals lookup
394+
const yKey = yValue as string | number;
395+
percentage = value / totals.y[yKey];
399396
suffix = formattedY;
400397
} else {
401398
percentage = value / totals.total;

superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,4 +359,171 @@ describe('Heatmap transformProps', () => {
359359
);
360360
expect((resultWithoutLegend.echartOptions.legend as any).show).toBe(false);
361361
});
362+
363+
test('tooltip formatter should display actual axis values, not indices', () => {
364+
const chartProps = createChartProps({
365+
sortXAxis: 'alpha_asc',
366+
sortYAxis: 'alpha_asc',
367+
});
368+
const result = transformProps(chartProps as HeatmapChartProps);
369+
370+
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;
371+
expect(typeof tooltipFormatter).toBe('function');
372+
373+
// Simulate tooltip data: [xIndex, yIndex, value]
374+
// With alpha_asc sorting: xAxis = ['Friday', 'Monday', 'Thursday', 'Tuesday', 'Wednesday']
375+
// yAxis = [9, 10, 11, 14, 15, 16]
376+
// So index [1, 2, 15] should map to 'Monday' and hour 11
377+
const mockParams = {
378+
value: [1, 2, 15],
379+
};
380+
381+
const tooltipHtml = tooltipFormatter(mockParams);
382+
383+
// Tooltip should contain the actual day name 'Monday', not the index '1'
384+
expect(tooltipHtml).toContain('Monday');
385+
// Tooltip should contain the actual hour '11', not the index '2'
386+
expect(tooltipHtml).toContain('11');
387+
// Should not contain raw indices
388+
expect(tooltipHtml).not.toMatch(/\b1\s*\(/);
389+
expect(tooltipHtml).not.toMatch(/\(\s*2\b/);
390+
});
391+
392+
test('tooltip formatter should work with different sort orders', () => {
393+
// Test with descending sort
394+
const chartProps = createChartProps({
395+
sortXAxis: 'alpha_desc',
396+
sortYAxis: 'alpha_desc',
397+
});
398+
const result = transformProps(chartProps as HeatmapChartProps);
399+
400+
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;
401+
402+
// With alpha_desc sorting: xAxis = ['Wednesday', 'Tuesday', 'Thursday', 'Monday', 'Friday']
403+
// yAxis = [16, 15, 14, 11, 10, 9]
404+
// So index [4, 5, 20] should map to 'Friday' and hour 9
405+
const mockParams = {
406+
value: [4, 5, 20],
407+
};
408+
409+
const tooltipHtml = tooltipFormatter(mockParams);
410+
411+
expect(tooltipHtml).toContain('Friday');
412+
expect(tooltipHtml).toContain('9');
413+
});
414+
415+
test('tooltip formatter should work with value-based sorting', () => {
416+
const chartProps = createChartProps({
417+
sortXAxis: 'value_asc',
418+
sortYAxis: 'value_asc',
419+
});
420+
const result = transformProps(chartProps as HeatmapChartProps);
421+
422+
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;
423+
424+
// With value_asc sorting on X: ['Wednesday', 'Tuesday', 'Thursday', 'Friday', 'Monday']
425+
// With value_asc sorting on Y: [11, 9, 10, 14, 15, 16]
426+
// So index [0, 0, 8] should map to 'Wednesday' and hour 11
427+
const mockParams = {
428+
value: [0, 0, 8],
429+
};
430+
431+
const tooltipHtml = tooltipFormatter(mockParams);
432+
433+
expect(tooltipHtml).toContain('Wednesday');
434+
expect(tooltipHtml).toContain('11');
435+
});
436+
437+
test('tooltip percentage calculation should use actual values, not indices', () => {
438+
const testData = [
439+
{ day_of_week: 'Monday', hour: 9, count: 10 },
440+
{ day_of_week: 'Monday', hour: 10, count: 20 },
441+
{ day_of_week: 'Tuesday', hour: 9, count: 30 },
442+
];
443+
444+
// Test normalizeAcross: 'x'
445+
const chartPropsX = createChartProps(
446+
{
447+
sortXAxis: 'alpha_asc',
448+
showPercentage: true,
449+
normalizeAcross: 'x',
450+
},
451+
testData,
452+
);
453+
const resultX = transformProps(chartPropsX as HeatmapChartProps);
454+
const tooltipFormatterX = (resultX.echartOptions.tooltip as any).formatter;
455+
456+
// With alpha_asc: xAxis = ['Monday', 'Tuesday'], yAxis = [9, 10]
457+
// Monday total = 30, Tuesday total = 30
458+
// Point [0, 0, 10] = Monday/9 with value 10
459+
// Percentage should be 10/30 = 33.33%, not based on index
460+
const mockParamsX = {
461+
value: [0, 0, 10],
462+
};
463+
464+
const tooltipHtmlX = tooltipFormatterX(mockParamsX);
465+
expect(tooltipHtmlX).toContain('33');
466+
expect(tooltipHtmlX).toContain('%');
467+
468+
// Test normalizeAcross: 'y'
469+
const chartPropsY = createChartProps(
470+
{
471+
sortXAxis: 'alpha_asc',
472+
showPercentage: true,
473+
normalizeAcross: 'y',
474+
},
475+
testData,
476+
);
477+
const resultY = transformProps(chartPropsY as HeatmapChartProps);
478+
const tooltipFormatterY = (resultY.echartOptions.tooltip as any).formatter;
479+
480+
// Hour 9 total = 40 (10 + 30)
481+
// Point [0, 0, 10] = Monday/9 with value 10
482+
// Percentage should be 10/40 = 25%
483+
const mockParamsY = {
484+
value: [0, 0, 10],
485+
};
486+
487+
const tooltipHtmlY = tooltipFormatterY(mockParamsY);
488+
expect(tooltipHtmlY).toContain('25');
489+
expect(tooltipHtmlY).toContain('%');
490+
});
491+
492+
test('tooltip formatter should handle numeric axes correctly', () => {
493+
const numericData = [
494+
{ year: 2020, quarter: 1, revenue: 100 },
495+
{ year: 2021, quarter: 2, revenue: 150 },
496+
{ year: 2022, quarter: 3, revenue: 200 },
497+
];
498+
499+
const chartProps = createChartProps(
500+
{
501+
sortXAxis: 'alpha_asc',
502+
sortYAxis: 'alpha_asc',
503+
xAxis: 'year',
504+
groupby: ['quarter'],
505+
},
506+
numericData,
507+
);
508+
509+
(chartProps as any).queriesData[0].colnames = [
510+
'year',
511+
'quarter',
512+
'revenue',
513+
];
514+
515+
const result = transformProps(chartProps as HeatmapChartProps);
516+
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;
517+
518+
// With alpha_asc: xAxis = [2020, 2021, 2022], yAxis = [1, 2, 3]
519+
// Index [1, 1, 150] should map to year 2021 and quarter 2
520+
const mockParams = {
521+
value: [1, 1, 150],
522+
};
523+
524+
const tooltipHtml = tooltipFormatter(mockParams);
525+
526+
expect(tooltipHtml).toContain('2021');
527+
expect(tooltipHtml).toContain('2');
528+
});
362529
});

0 commit comments

Comments
 (0)