Skip to content

test(heatmap): add tests for tooltip displaying actual axis values#38522

Open
yousoph wants to merge 1 commit intoapache:masterfrom
aminghadersohi:heatmap-tooltip-tests
Open

test(heatmap): add tests for tooltip displaying actual axis values#38522
yousoph wants to merge 1 commit intoapache:masterfrom
aminghadersohi:heatmap-tooltip-tests

Conversation

@yousoph
Copy link
Member

@yousoph yousoph commented Mar 9, 2026

User description

SUMMARY

Adds comprehensive regression tests for the heatmap tooltip bug fix where tooltips were displaying numeric indices (0, 1, 2...) instead of actual axis values (e.g., "Monday", "Morning").

Context: After PR #36302 changed the heatmap data structure to use axis indices for proper sorting, the tooltip formatter was not updated to look up actual values from the sorted arrays. This caused tooltips to display raw indices instead of formatted axis labels.

What this PR does:

  • Adds 5 test cases covering different tooltip scenarios
  • Ensures tooltips display actual axis values, not numeric indices
  • Verifies tooltip behavior with different sort orders (alphabetical asc/desc, value-based asc/desc)
  • Tests percentage calculations use actual values when normalizeAcross is enabled
  • Validates tooltip handling of numeric axes

Why these tests matter:
These tests prevent future regressions by verifying the tooltip formatter correctly:

  1. Looks up actual x/y values from sortedXAxisValues and sortedYAxisValues arrays
  2. Uses actual values (not indices) for percentage calculations in totals.x[xValue] and totals.y[yValue]
  3. Handles different data types (strings, numbers) and sort configurations

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A - Test-only changes

TESTING INSTRUCTIONS

  1. Run the heatmap tooltip tests:
    cd superset-frontend
    npm test -- transformProps.test.ts
    
    

CodeAnt-AI Description

Fix heatmap tooltip to show actual axis labels and correct percentage calculations

What Changed

  • Tooltip displays actual x/y axis values (e.g., "Monday", "11") instead of numeric indices
  • Percentage shown in tooltip uses the real axis totals (not indices) when normalization is enabled
  • Added tests covering alphabetical and value-based sorting, numeric axes, and percentage/normalization cases to prevent regressions

Impact

✅ Clearer heatmap tooltips
✅ Correct heatmap percentage values
✅ Fewer tooltip regressions

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai-for-open-source codeant-ai-for-open-source bot added the size:L This PR changes 100-499 lines, ignoring generated files label Mar 9, 2026
@dosubot dosubot bot added plugins viz:charts:heatmap Related to the Heatmap chart labels Mar 9, 2026
Comment on lines 390 to 401
const formattedValue = valueFormatter(value);
let percentage = 0;
let suffix = 'heatmap';
if (typeof value === 'number') {
if (normalizeAcross === 'x') {
percentage = value / totals.x[x];
percentage = value / totals.x[String(xValue)];
suffix = formattedX;
} else if (normalizeAcross === 'y') {
percentage = value / totals.y[y];
percentage = value / totals.y[String(yValue)];
suffix = formattedY;
} else {
percentage = value / totals.total;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: When normalizeAcross is 'x' or 'y' (or the whole heatmap), the code divides by the corresponding total without checking if that total is zero or undefined, so cases where all values for an axis (or the whole heatmap) are 0 will produce NaN percentages in the tooltip. [logic error]

Severity Level: Major ⚠️
- ⚠️ Heatmap tooltips show NaN percentage for zero totals.
- ⚠️ Users misinterpret normalized heatmaps with all-zero categories.
Suggested change
const formattedValue = valueFormatter(value);
let percentage = 0;
let suffix = 'heatmap';
if (typeof value === 'number') {
if (normalizeAcross === 'x') {
percentage = value / totals.x[x];
percentage = value / totals.x[String(xValue)];
suffix = formattedX;
} else if (normalizeAcross === 'y') {
percentage = value / totals.y[y];
percentage = value / totals.y[String(yValue)];
suffix = formattedY;
} else {
percentage = value / totals.total;
const formattedValue = valueFormatter(value);
let percentage = 0;
let suffix = 'heatmap';
if (typeof value === 'number') {
if (normalizeAcross === 'x') {
const xTotal = totals.x[String(xValue)] || 0;
percentage = xTotal ? value / xTotal : 0;
suffix = formattedX;
} else if (normalizeAcross === 'y') {
const yTotal = totals.y[String(yValue)] || 0;
percentage = yTotal ? value / yTotal : 0;
suffix = formattedY;
} else {
const total = totals.total || 0;
percentage = total ? value / total : 0;
suffix = 'heatmap';
}
}
Steps of Reproduction ✅
1. In `superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts`, call
the default-exported `transformProps` with `formData.normalizeAcross` set to `'x'` and a
metric configured in `formData.metric` (function definition and `echartOptions`
construction are in this file; tooltip is configured starting at lines 360–405 in the
diff).

2. Provide `queriesData[0].data` such that for at least one x-axis category all metric
values are `0` (e.g., two rows with the same x value, different y values, and metric
column `metricLabel` equal to `0`), so that in `calculateTotals` (lines ~310–336 in the
same file) the corresponding `totals.x[thatXValue]` and the overall `totals.total` remain
`0`.

3. When `transformProps` builds the series data (lines ~330–359), it encodes each data
point as `[xIndex, yIndex, metricValue]`; then ECharts later calls the tooltip formatter
configured at lines 365–405 with a `params` whose `value` is, for the all-zero cell,
`[xIndex, yIndex, 0]`.

4. Inside the tooltip formatter at lines 390–401, the code executes `percentage = value /
totals.x[String(xValue)]` (or `/ totals.y[...]` or `/ totals.total` depending on
`normalizeAcross`); with `value === 0` and the corresponding total being `0`, this
computes `0 / 0`, producing `NaN`, which is then passed to `percentFormatter` and rendered
as a `NaN%` percentage in the tooltip HTML returned by `tooltipHtml`.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
**Line:** 390:401
**Comment:**
	*Logic Error: When `normalizeAcross` is `'x'` or `'y'` (or the whole heatmap), the code divides by the corresponding total without checking if that total is zero or undefined, so cases where all values for an axis (or the whole heatmap) are 0 will produce NaN percentages in the tooltip.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment on lines +492 to +528
test('tooltip formatter should handle numeric axes correctly', () => {
const numericData = [
{ year: 2020, quarter: 1, revenue: 100 },
{ year: 2021, quarter: 2, revenue: 150 },
{ year: 2022, quarter: 3, revenue: 200 },
];

const chartProps = createChartProps(
{
sortXAxis: 'alpha_asc',
sortYAxis: 'alpha_asc',
xAxis: 'year',
groupby: ['quarter'],
},
numericData,
);

(chartProps as any).queriesData[0].colnames = [
'year',
'quarter',
'revenue',
];

const result = transformProps(chartProps as HeatmapChartProps);
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;

// With alpha_asc: xAxis = [2020, 2021, 2022], yAxis = [1, 2, 3]
// Index [1, 1, 150] should map to year 2021 and quarter 2
const mockParams = {
value: [1, 1, 150],
};

const tooltipHtml = tooltipFormatter(mockParams);

expect(tooltipHtml).toContain('2021');
expect(tooltipHtml).toContain('2');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: In the numeric-axes tooltip test, the formData metric is left as 'count' while the data and colnames use 'revenue', so transformProps reads undefined metric values and computes incorrect totals, making the test setup inconsistent with real usage and potentially hiding issues in percentage logic. [logic error]

Severity Level: Major ⚠️
- ⚠️ Heatmap numeric-axis tooltip test uses inconsistent metric configuration.
- ⚠️ Misconfigured test may miss regressions in metric-based logic.
Suggested change
test('tooltip formatter should handle numeric axes correctly', () => {
const numericData = [
{ year: 2020, quarter: 1, revenue: 100 },
{ year: 2021, quarter: 2, revenue: 150 },
{ year: 2022, quarter: 3, revenue: 200 },
];
const chartProps = createChartProps(
{
sortXAxis: 'alpha_asc',
sortYAxis: 'alpha_asc',
xAxis: 'year',
groupby: ['quarter'],
},
numericData,
);
(chartProps as any).queriesData[0].colnames = [
'year',
'quarter',
'revenue',
];
const result = transformProps(chartProps as HeatmapChartProps);
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;
// With alpha_asc: xAxis = [2020, 2021, 2022], yAxis = [1, 2, 3]
// Index [1, 1, 150] should map to year 2021 and quarter 2
const mockParams = {
value: [1, 1, 150],
};
const tooltipHtml = tooltipFormatter(mockParams);
expect(tooltipHtml).toContain('2021');
expect(tooltipHtml).toContain('2');
});
test('tooltip formatter should handle numeric axes correctly', () => {
const numericData = [
{ year: 2020, quarter: 1, revenue: 100 },
{ year: 2021, quarter: 2, revenue: 150 },
{ year: 2022, quarter: 3, revenue: 200 },
];
const chartProps = createChartProps(
{
sortXAxis: 'alpha_asc',
sortYAxis: 'alpha_asc',
xAxis: 'year',
groupby: ['quarter'],
metric: 'revenue',
},
numericData,
);
(chartProps as any).queriesData[0].colnames = [
'year',
'quarter',
'revenue',
];
const result = transformProps(chartProps as HeatmapChartProps);
const tooltipFormatter = (result.echartOptions.tooltip as any).formatter;
// With alpha_asc: xAxis = [2020, 2021, 2022], yAxis = [1, 2, 3]
// Index [1, 1, 150] should map to year 2021 and quarter 2
const mockParams = {
value: [1, 1, 150],
};
const tooltipHtml = tooltipFormatter(mockParams);
expect(tooltipHtml).toContain('2021');
expect(tooltipHtml).toContain('2');
});
Steps of Reproduction ✅
1. Run the unit tests for the heatmap transform via `npm test -- transformProps.test.ts`
in `superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts`.

2. Observe the test `tooltip formatter should handle numeric axes correctly` starting at
line 492, which calls `createChartProps` without overriding `metric`, so it uses
`baseFormData.metric = 'count'` from the top of the file.

3. In the same test, `numericData` only contains a `revenue` field and
`queriesData[0].colnames` is overridden to `['year', 'quarter', 'revenue']`, so there is
no `count` column for the metric referenced by formData.

4. When `transformProps` is invoked with these `chartProps`, it computes heatmap series
values and any metric-based aggregations using the nonexistent `'count'` metric (reading
undefined/incorrect values), while the test only asserts on axis labels in the tooltip
output, so this inconsistent setup is not detected by the assertions.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts
**Line:** 492:528
**Comment:**
	*Logic Error: In the numeric-axes tooltip test, the formData metric is left as `'count'` while the data and `colnames` use `'revenue'`, so `transformProps` reads undefined metric values and computes incorrect totals, making the test setup inconsistent with real usage and potentially hiding issues in percentage logic.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Copy link
Contributor

@bito-code-review bito-code-review bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #746e1e

Actionable Suggestions - 1
  • superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts - 1
Review Details
  • Files reviewed - 2 · Commit Range: e508645..4d5d74f
    • superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
    • superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts
  • Files skipped - 0
  • Tools
    • Eslint (Linter) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +375 to +376
const xIndex = paramsValue?.[0] as number;
const yIndex = paramsValue?.[1] as number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix index type conversion

The type assertion 'as number' doesn't perform runtime conversion. If params.value[0] is a string (e.g., '1'), xIndex remains a string, causing sortedXAxisValues['1'] to be undefined instead of sortedXAxisValues[1]. This could lead to empty axis labels and NaN percentages in tooltips. Use Number() for proper conversion.

Code suggestion
Check the AI-generated fix before applying
Suggested change
const xIndex = paramsValue?.[0] as number;
const yIndex = paramsValue?.[1] as number;
const xIndex = Number(paramsValue?.[0]);
const yIndex = Number(paramsValue?.[1]);

Code Review Run #746e1e


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

@aminghadersohi aminghadersohi force-pushed the heatmap-tooltip-tests branch from 4d5d74f to 84c2e5d Compare March 9, 2026 17:48
@bito-code-review
Copy link
Contributor

bito-code-review bot commented Mar 9, 2026

Code Review Agent Run #80dbcd

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: e508645..84c2e5d
    • superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
    • superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

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>
@aminghadersohi aminghadersohi force-pushed the heatmap-tooltip-tests branch from 84c2e5d to 076f85d Compare March 11, 2026 21:06
Copy link
Contributor

@bito-code-review bito-code-review bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #e016ae

Actionable Suggestions - 1
  • superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts - 1
Review Details
  • Files reviewed - 2 · Commit Range: 076f85d..076f85d
    • superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
    • superset-frontend/plugins/plugin-chart-echarts/test/Heatmap/transformProps.test.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +499 to +507
const chartProps = createChartProps(
{
sortXAxis: 'alpha_asc',
sortYAxis: 'alpha_asc',
xAxis: 'year',
groupby: ['quarter'],
},
numericData,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test data mismatch

The test uses custom data with 'revenue' as the metric column, but the formData still defaults to metric: 'count'. This mismatch will cause the transformProps to look for 'count' in the data, resulting in empty or incorrect axis values and failing assertions.

Code Review Run #e016ae


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugins size/L size:L This PR changes 100-499 lines, ignoring generated files viz:charts:heatmap Related to the Heatmap chart

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants