You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/06/06 00:04:57 UTC

(superset) branch tdd/issue-28766-gauge-interval-colors created (now 183e2f4c8cc)

This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a change to branch tdd/issue-28766-gauge-interval-colors
in repository https://gitbox.apache.org/repos/asf/superset.git


      at 183e2f4c8cc test(gauge): E2E that gauge paints configured interval colors on a dashboard (#28766)

This branch includes the following new commits:

     new 183e2f4c8cc test(gauge): E2E that gauge paints configured interval colors on a dashboard (#28766)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(superset) 01/01: test(gauge): E2E that gauge paints configured interval colors on a dashboard (#28766)

Posted by ru...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch tdd/issue-28766-gauge-interval-colors
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 183e2f4c8ccdc750441fd91ac03691c2caed4f2d
Author: Claude Code <no...@anthropic.com>
AuthorDate: Fri Jun 5 17:04:39 2026 -0700

    test(gauge): E2E that gauge paints configured interval colors on a dashboard (#28766)
    
    Regression test for #28766: a Gauge with interval bounds + interval colors
    sometimes renders the wrong interval colors when first loaded on a dashboard
    (a refresh fixes it). The gauge draws to a canvas, so this Playwright spec reads
    pixels back and asserts the configured color-scheme indices are painted: with
    supersetColors and interval_color_indices '1,2' it requires the 1st (#1FA8C9)
    and 2nd (#454E7C) palette colors to be present and the 3rd (#5AC189) to be
    absent (a shifted/fallback palette would fail).
    
    Closes #28766
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 .../tests/dashboard/gauge-interval-colors.spec.ts  | 195 +++++++++++++++++++++
 1 file changed, 195 insertions(+)

diff --git a/superset-frontend/playwright/tests/dashboard/gauge-interval-colors.spec.ts b/superset-frontend/playwright/tests/dashboard/gauge-interval-colors.spec.ts
new file mode 100644
index 00000000000..6150ffee7c7
--- /dev/null
+++ b/superset-frontend/playwright/tests/dashboard/gauge-interval-colors.spec.ts
@@ -0,0 +1,195 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Regression for #28766: a Gauge chart configured with interval bounds and
+ * interval colors (mapped to a categorical color scheme) sometimes renders the
+ * wrong interval colors when first loaded on a dashboard — a refresh fixes it.
+ *
+ * The gauge renders to a <canvas>, so this test reads pixels back from the
+ * rendered gauge and asserts the configured interval colors are present in the
+ * correct mapping. With `color_scheme: supersetColors` and
+ * `interval_color_indices: '1,2'`, the gauge axis must paint the scheme's 1st
+ * and 2nd colors (#1FA8C9 and #454E7C) and must NOT paint the 3rd (#5AC189),
+ * which would indicate a shifted / fallback palette.
+ *
+ * CI green => the gauge paints the configured interval colors on first load;
+ *             merging closes #28766 and guards against regressions.
+ * CI red   => the interval colors are wrong on first load; the bug is live in
+ *             plugin-chart-echarts/src/Gauge (color-scheme resolution).
+ */
+import { testWithAssets, expect } from '../../helpers/fixtures';
+import { apiPost, apiPut } from '../../helpers/api/requests';
+import { apiPostDashboard } from '../../helpers/api/dashboard';
+import { DashboardPage } from '../../pages/DashboardPage';
+
+const DATASET_NAME = 'birth_names';
+
+// supersetColors palette: index 1 = #1FA8C9, index 2 = #454E7C, index 3 = #5AC189
+const COLOR_INTERVAL_1: [number, number, number] = [31, 168, 201];
+const COLOR_INTERVAL_2: [number, number, number] = [69, 78, 124];
+const COLOR_UNUSED_3: [number, number, number] = [90, 193, 137];
+
+async function findDatasetIdByName(page: any, name: string): Promise<number> {
+  const query = `(filters:!((col:table_name,opr:eq,value:'${name}')))`;
+  const resp = await page.request.get(`api/v1/dataset/?q=${query}`);
+  const body = await resp.json();
+  if (!body.result?.length) {
+    throw new Error(`Dataset ${name} not found`);
+  }
+  return body.result[0].id;
+}
+
+testWithAssets(
+  'Gauge renders configured interval colors on a dashboard (#28766)',
+  async ({ page, testAssets }) => {
+    const datasetId = await findDatasetIdByName(page, DATASET_NAME);
+
+    const chartParams = {
+      datasource: `${datasetId}__table`,
+      viz_type: 'gauge_chart',
+      metric: 'count',
+      adhoc_filters: [],
+      groupby: [],
+      row_limit: 10,
+      color_scheme: 'supersetColors',
+      min_val: 0,
+      max_val: 100,
+      start_angle: 225,
+      end_angle: -45,
+      intervals: '50,100',
+      interval_color_indices: '1,2',
+      show_pointer: true,
+      number_format: 'SMART_NUMBER',
+      value_formatter: '{value}',
+    };
+    const chartResp = await apiPost(page, 'api/v1/chart/', {
+      slice_name: `gauge_interval_colors_${Date.now()}`,
+      viz_type: 'gauge_chart',
+      datasource_id: datasetId,
+      datasource_type: 'table',
+      params: JSON.stringify(chartParams),
+    });
+    expect(chartResp.ok()).toBe(true);
+    const chartId: number = (await chartResp.json()).id;
+    testAssets.trackChart(chartId);
+
+    const chartLayoutKey = `CHART-${chartId}`;
+    const positionJson = {
+      DASHBOARD_VERSION_KEY: 'v2',
+      ROOT_ID: { type: 'ROOT', id: 'ROOT_ID', children: ['GRID_ID'] },
+      GRID_ID: {
+        type: 'GRID',
+        id: 'GRID_ID',
+        children: ['ROW-1'],
+        parents: ['ROOT_ID'],
+      },
+      'ROW-1': {
+        type: 'ROW',
+        id: 'ROW-1',
+        children: [chartLayoutKey],
+        parents: ['ROOT_ID', 'GRID_ID'],
+        meta: { background: 'BACKGROUND_TRANSPARENT' },
+      },
+      [chartLayoutKey]: {
+        type: 'CHART',
+        id: chartLayoutKey,
+        children: [],
+        parents: ['ROOT_ID', 'GRID_ID', 'ROW-1'],
+        meta: {
+          chartId,
+          width: 6,
+          height: 60,
+          sliceName: 'gauge_interval_colors',
+        },
+      },
+    };
+    const dashResp = await apiPostDashboard(page, {
+      dashboard_title: `gauge_interval_colors_${Date.now()}`,
+      published: true,
+      position_json: JSON.stringify(positionJson),
+      json_metadata: JSON.stringify({ color_scheme: 'supersetColors' }),
+    });
+    expect(dashResp.ok()).toBe(true);
+    const dashBody = await dashResp.json();
+    const dashboardId: number = dashBody.result?.id ?? dashBody.id;
+    testAssets.trackDashboard(dashboardId);
+
+    await apiPut(page, `api/v1/chart/${chartId}`, { dashboards: [dashboardId] });
+
+    const dashboardPage = new DashboardPage(page);
+    await dashboardPage.gotoById(dashboardId);
+    await dashboardPage.waitForLoad();
+    await dashboardPage.waitForChartsToLoad();
+
+    const canvas = page
+      .locator('[data-test="chart-container"] canvas')
+      .first();
+    await canvas.waitFor({ state: 'visible', timeout: 30_000 });
+
+    // Read the configured interval colors back from the rendered canvas.
+    // Poll because the gauge paints shortly after the chart container appears.
+    const countColors = () =>
+      canvas.evaluate(
+        (
+          el: HTMLCanvasElement,
+          targets: Array<[number, number, number]>,
+        ) => {
+          const ctx = el.getContext('2d');
+          if (!ctx) return targets.map(() => 0);
+          const { data } = ctx.getImageData(0, 0, el.width, el.height);
+          const counts = targets.map(() => 0);
+          for (let i = 0; i < data.length; i += 4) {
+            if (data[i + 3] < 200) continue;
+            for (let t = 0; t < targets.length; t += 1) {
+              const [r, g, b] = targets[t];
+              if (
+                Math.abs(data[i] - r) < 12 &&
+                Math.abs(data[i + 1] - g) < 12 &&
+                Math.abs(data[i + 2] - b) < 12
+              ) {
+                counts[t] += 1;
+              }
+            }
+          }
+          return counts;
+        },
+        [COLOR_INTERVAL_1, COLOR_INTERVAL_2, COLOR_UNUSED_3],
+      );
+
+    await expect
+      .poll(async () => (await countColors())[0], { timeout: 20_000 })
+      .toBeGreaterThan(50);
+
+    const [interval1, interval2, unused3] = await countColors();
+
+    expect(
+      interval1,
+      'Gauge should paint the 1st interval color (#1FA8C9)',
+    ).toBeGreaterThan(50);
+    expect(
+      interval2,
+      'Gauge should paint the 2nd interval color (#454E7C)',
+    ).toBeGreaterThan(50);
+    expect(
+      unused3,
+      'Gauge must not paint the 3rd palette color (#5AC189) — indicates a shifted/fallback palette (#28766)',
+    ).toBe(0);
+  },
+);