You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2023/12/08 13:40:16 UTC

(superset) branch master updated: fix(plugin-chart-echarts): support truncated numeric x-axis (#26215)

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

michaelsmolina pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 07e5fe8a66 fix(plugin-chart-echarts): support truncated numeric x-axis (#26215)
07e5fe8a66 is described below

commit 07e5fe8a66fcce6baf1974de9ff3aaab4ad30884
Author: Ville Brofeldt <33...@users.noreply.github.com>
AuthorDate: Fri Dec 8 05:40:09 2023 -0800

    fix(plugin-chart-echarts): support truncated numeric x-axis (#26215)
    
    Co-authored-by: Michael S. Molina <mi...@gmail.com>
---
 .../plugin-chart-echarts/src/Bubble/constants.ts   |  1 +
 .../src/Bubble/controlPanel.tsx                    |  4 ++-
 .../src/Bubble/transformProps.ts                   | 17 +++++++-----
 .../src/MixedTimeseries/transformProps.ts          |  6 ++---
 .../src/Timeseries/Area/controlPanel.tsx           |  4 +++
 .../src/Timeseries/Regular/Bar/controlPanel.tsx    |  4 +++
 .../src/Timeseries/Regular/Line/controlPanel.tsx   |  4 +++
 .../Timeseries/Regular/Scatter/controlPanel.tsx    |  4 +++
 .../Timeseries/Regular/SmoothLine/controlPanel.tsx |  4 +++
 .../src/Timeseries/Step/controlPanel.tsx           |  4 +++
 .../src/Timeseries/constants.ts                    |  1 +
 .../src/Timeseries/transformProps.ts               | 28 ++++++++++++-------
 .../plugin-chart-echarts/src/Timeseries/types.ts   |  2 ++
 .../plugins/plugin-chart-echarts/src/controls.tsx  | 31 ++++++++++++++++++++++
 .../plugin-chart-echarts/src/utils/controls.ts     |  2 +-
 .../plugin-chart-echarts/src/utils/series.ts       | 14 ++++++++++
 .../test/Bubble/transformProps.test.ts             |  1 +
 .../test/utils/controls.test.ts                    | 22 +++++++--------
 .../plugin-chart-echarts/test/utils/series.test.ts | 28 +++++++++++++++++++
 19 files changed, 150 insertions(+), 31 deletions(-)

diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/constants.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/constants.ts
index 0f9bc0f305..9c157d33ac 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/constants.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/constants.ts
@@ -26,6 +26,7 @@ export const DEFAULT_FORM_DATA: Partial<EchartsBubbleFormData> = {
   logYAxis: false,
   xAxisTitleMargin: 30,
   yAxisTitleMargin: 30,
+  truncateXAxis: false,
   truncateYAxis: false,
   yAxisBounds: [null, null],
   xAxisLabelRotation: 0,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/controlPanel.tsx
index 50f42eda23..532888b485 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/controlPanel.tsx
@@ -26,7 +26,7 @@ import {
 } from '@superset-ui/chart-controls';
 
 import { DEFAULT_FORM_DATA } from './constants';
-import { legendSection } from '../controls';
+import { legendSection, truncateXAxis, xAxisBounds } from '../controls';
 
 const { logAxis, truncateYAxis, yAxisBounds, xAxisLabelRotation, opacity } =
   DEFAULT_FORM_DATA;
@@ -247,6 +247,8 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [truncateXAxis],
+        [xAxisBounds],
         [
           {
             name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts
index ce53fdf266..01d9ed3c53 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts
@@ -28,9 +28,9 @@ import {
 import { EchartsBubbleChartProps, EchartsBubbleFormData } from './types';
 import { DEFAULT_FORM_DATA, MINIMUM_BUBBLE_SIZE } from './constants';
 import { defaultGrid } from '../defaults';
-import { getLegendProps } from '../utils/series';
+import { getLegendProps, getMinAndMaxFromBounds } from '../utils/series';
 import { Refs } from '../types';
-import { parseYAxisBound } from '../utils/controls';
+import { parseAxisBound } from '../utils/controls';
 import { getDefaultTooltip } from '../utils/tooltip';
 import { getPadding } from '../Timeseries/transformers';
 import { convertInteger } from '../utils/convertInteger';
@@ -84,6 +84,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
     series: bubbleSeries,
     xAxisLabel: bubbleXAxisTitle,
     yAxisLabel: bubbleYAxisTitle,
+    xAxisBounds,
     xAxisFormat,
     yAxisFormat,
     yAxisBounds,
@@ -91,6 +92,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
     logYAxis,
     xAxisTitleMargin,
     yAxisTitleMargin,
+    truncateXAxis,
     truncateYAxis,
     xAxisLabelRotation,
     yAxisLabelRotation,
@@ -141,7 +143,8 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
   const yAxisFormatter = getNumberFormatter(yAxisFormat);
   const tooltipSizeFormatter = getNumberFormatter(tooltipSizeFormat);
 
-  const [min, max] = yAxisBounds.map(parseYAxisBound);
+  const [xAxisMin, xAxisMax] = xAxisBounds.map(parseAxisBound);
+  const [yAxisMin, yAxisMax] = yAxisBounds.map(parseAxisBound);
 
   const padding = getPadding(
     showLegend,
@@ -155,6 +158,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
     convertInteger(xAxisTitleMargin),
   );
 
+  const xAxisType = logXAxis ? AxisType.log : AxisType.value;
   const echartOptions: EChartsCoreOption = {
     series,
     xAxis: {
@@ -172,7 +176,8 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
         fontWight: 'bolder',
       },
       nameGap: convertInteger(xAxisTitleMargin),
-      type: logXAxis ? AxisType.log : AxisType.value,
+      type: xAxisType,
+      ...getMinAndMaxFromBounds(xAxisType, truncateXAxis, xAxisMin, xAxisMax),
     },
     yAxis: {
       axisLabel: { formatter: yAxisFormatter },
@@ -189,8 +194,8 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
         fontWight: 'bolder',
       },
       nameGap: convertInteger(yAxisTitleMargin),
-      min,
-      max,
+      min: yAxisMin,
+      max: yAxisMax,
       type: logYAxis ? AxisType.log : AxisType.value,
     },
     legend: {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
index 47411e2477..8bc01582af 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -53,7 +53,7 @@ import {
   ForecastSeriesEnum,
   Refs,
 } from '../types';
-import { parseYAxisBound } from '../utils/controls';
+import { parseAxisBound } from '../utils/controls';
 import {
   getOverMaxHiddenFormatter,
   dedupSeries,
@@ -345,9 +345,9 @@ export default function transformProps(
     });
 
   // yAxisBounds need to be parsed to replace incompatible values with undefined
-  let [min, max] = (yAxisBounds || []).map(parseYAxisBound);
+  let [min, max] = (yAxisBounds || []).map(parseAxisBound);
   let [minSecondary, maxSecondary] = (yAxisBoundsSecondary || []).map(
-    parseYAxisBound,
+    parseAxisBound,
   );
 
   const array = ensureIsArray(chartProps.rawFormData?.time_compare);
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx
index 5a5975c66b..018038772c 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx
@@ -37,6 +37,8 @@ import {
   richTooltipSection,
   seriesOrderSection,
   percentageThresholdControl,
+  truncateXAxis,
+  xAxisBounds,
 } from '../../controls';
 import { AreaChartStackControlOptions } from '../../constants';
 
@@ -241,6 +243,8 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [truncateXAxis],
+        [xAxisBounds],
         [
           {
             name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
index af482da1b4..c3002a2498 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
@@ -35,6 +35,8 @@ import {
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
+  truncateXAxis,
+  xAxisBounds,
 } from '../../../controls';
 
 import { OrientationType } from '../../types';
@@ -224,6 +226,8 @@ function createAxisControl(axis: 'x' | 'y'): ControlSetRow[] {
         },
       },
     ],
+    [truncateXAxis],
+    [xAxisBounds],
     [
       {
         name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx
index 124ab1e935..5c5f7a0ab1 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx
@@ -38,6 +38,8 @@ import {
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
+  truncateXAxis,
+  xAxisBounds,
 } from '../../../controls';
 
 const {
@@ -229,6 +231,8 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [truncateXAxis],
+        [xAxisBounds],
         [
           {
             name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx
index bc813127ca..6701647694 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx
@@ -37,6 +37,8 @@ import {
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
+  truncateXAxis,
+  xAxisBounds,
 } from '../../../controls';
 
 const {
@@ -173,6 +175,8 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [truncateXAxis],
+        [xAxisBounds],
         [
           {
             name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx
index 2a8fbfb0af..0c6623f216 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx
@@ -37,6 +37,8 @@ import {
   richTooltipSection,
   seriesOrderSection,
   showValueSectionWithoutStack,
+  truncateXAxis,
+  xAxisBounds,
 } from '../../../controls';
 
 const {
@@ -173,6 +175,8 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [truncateXAxis],
+        [xAxisBounds],
         [
           {
             name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx
index 9333cb48a1..021c306d05 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx
@@ -35,6 +35,8 @@ import {
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
+  truncateXAxis,
+  xAxisBounds,
 } from '../../controls';
 
 const {
@@ -223,6 +225,8 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [truncateXAxis],
+        [xAxisBounds],
         [
           {
             name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts
index 17629c0996..a95a14077d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts
@@ -57,6 +57,7 @@ export const DEFAULT_FORM_DATA: EchartsTimeseriesFormData = {
   seriesType: EchartsTimeseriesSeriesType.Line,
   stack: false,
   tooltipTimeFormat: 'smart_date',
+  truncateXAxis: true,
   truncateYAxis: false,
   yAxisBounds: [null, null],
   zoomable: false,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
index c85dc8db00..e42ac183b6 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
@@ -54,7 +54,7 @@ import {
 } from './types';
 import { DEFAULT_FORM_DATA } from './constants';
 import { ForecastSeriesEnum, ForecastValue, Refs } from '../types';
-import { parseYAxisBound } from '../utils/controls';
+import { parseAxisBound } from '../utils/controls';
 import {
   calculateLowerLogTick,
   dedupSeries,
@@ -64,6 +64,7 @@ import {
   getAxisType,
   getColtypesMapping,
   getLegendProps,
+  getMinAndMaxFromBounds,
 } from '../utils/series';
 import {
   extractAnnotationLabels,
@@ -161,8 +162,10 @@ export default function transformProps(
     stack,
     tooltipTimeFormat,
     tooltipSortByMetric,
+    truncateXAxis,
     truncateYAxis,
     xAxis: xAxisOrig,
+    xAxisBounds,
     xAxisLabelRotation,
     xAxisSortSeries,
     xAxisSortSeriesAscending,
@@ -388,15 +391,20 @@ export default function transformProps(
       }
     });
 
-  // yAxisBounds need to be parsed to replace incompatible values with undefined
-  let [min, max] = (yAxisBounds || []).map(parseYAxisBound);
+  // axis bounds need to be parsed to replace incompatible values with undefined
+  const [xAxisMin, xAxisMax] = (xAxisBounds || []).map(parseAxisBound);
+  let [yAxisMin, yAxisMax] = (yAxisBounds || []).map(parseAxisBound);
 
   // default to 0-100% range when doing row-level contribution chart
   if ((contributionMode === 'row' || isAreaExpand) && stack) {
-    if (min === undefined) min = 0;
-    if (max === undefined) max = 1;
-  } else if (logAxis && min === undefined && minPositiveValue !== undefined) {
-    min = calculateLowerLogTick(minPositiveValue);
+    if (yAxisMin === undefined) yAxisMin = 0;
+    if (yAxisMax === undefined) yAxisMax = 1;
+  } else if (
+    logAxis &&
+    yAxisMin === undefined &&
+    minPositiveValue !== undefined
+  ) {
+    yAxisMin = calculateLowerLogTick(minPositiveValue);
   }
 
   const tooltipFormatter =
@@ -452,12 +460,14 @@ export default function transformProps(
       xAxisType === AxisType.time && timeGrainSqla
         ? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla]
         : 0,
+    ...getMinAndMaxFromBounds(xAxisType, truncateXAxis, xAxisMin, xAxisMax),
   };
+
   let yAxis: any = {
     ...defaultYAxis,
     type: logAxis ? AxisType.log : AxisType.value,
-    min,
-    max,
+    min: yAxisMin,
+    max: yAxisMax,
     minorTick: { show: true },
     minorSplitLine: { show: minorSplitLine },
     axisLabel: {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts
index 1873086d99..65da981e49 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts
@@ -75,10 +75,12 @@ export type EchartsTimeseriesFormData = QueryFormData & {
   stack: StackType;
   timeCompare?: string[];
   tooltipTimeFormat?: string;
+  truncateXAxis: boolean;
   truncateYAxis: boolean;
   yAxisFormat?: string;
   xAxisTimeFormat?: string;
   timeGrainSqla?: TimeGranularity;
+  xAxisBounds: [number | undefined | null, number | undefined | null];
   yAxisBounds: [number | undefined | null, number | undefined | null];
   zoomable: boolean;
   richTooltip: boolean;
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
index 8f311e47e5..093617446a 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
@@ -248,3 +248,34 @@ export const seriesOrderSection: ControlSetRow[] = [
   [sortSeriesType],
   [sortSeriesAscending],
 ];
+
+export const truncateXAxis: ControlSetItem = {
+  name: 'truncateXAxis',
+  config: {
+    type: 'CheckboxControl',
+    label: t('Truncate X Axis'),
+    default: DEFAULT_FORM_DATA.truncateXAxis,
+    renderTrigger: true,
+    description: t(
+      'Truncate X Axis. Can be overridden by specifying a min or max bound. Only applicable for numercal X axis.',
+    ),
+  },
+};
+
+export const xAxisBounds: ControlSetItem = {
+  name: 'xAxisBounds',
+  config: {
+    type: 'BoundsControl',
+    label: t('X Axis Bounds'),
+    renderTrigger: true,
+    default: DEFAULT_FORM_DATA.xAxisBounds,
+    description: t(
+      'Bounds for numerical X axis. Not applicable for temporal or categorical axes. ' +
+        'When left empty, the bounds are dynamically defined based on the min/max of the data. ' +
+        "Note that this feature will only expand the axis range. It won't " +
+        "narrow the data's extent.",
+    ),
+    visibility: ({ controls }: ControlPanelsContainerProps) =>
+      Boolean(controls?.truncateXAxis?.value),
+  },
+};
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts
index 27f8fb1447..67a5414112 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts
@@ -20,7 +20,7 @@
 import { validateNumber } from '@superset-ui/core';
 
 // eslint-disable-next-line import/prefer-default-export
-export function parseYAxisBound(
+export function parseAxisBound(
   bound?: string | number | null,
 ): number | undefined {
   if (bound === undefined || bound === null || Number.isNaN(Number(bound))) {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
index bd4e329d0b..aa353f66d1 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
@@ -543,3 +543,17 @@ export function calculateLowerLogTick(minPositiveValue: number) {
   const logBase10 = Math.floor(Math.log10(minPositiveValue));
   return Math.pow(10, logBase10);
 }
+
+export function getMinAndMaxFromBounds(
+  axisType: AxisType,
+  truncateAxis: boolean,
+  min?: number,
+  max?: number,
+): { min: number | 'dataMin'; max: number | 'dataMax' } | {} {
+  return truncateAxis && axisType === AxisType.value
+    ? {
+        min: min === undefined ? 'dataMin' : min,
+        max: max === undefined ? 'dataMax' : max,
+      }
+    : {};
+}
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Bubble/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Bubble/transformProps.test.ts
index 2bb4ae0fc6..1a92a43257 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/Bubble/transformProps.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/Bubble/transformProps.test.ts
@@ -48,6 +48,7 @@ describe('Bubble transformProps', () => {
       expressionType: 'simple',
       label: 'SUM(sales)',
     },
+    xAxisBounds: [null, null],
     yAxisBounds: [null, null],
   };
   const chartProps = new ChartProps({
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts
index 60ced57739..cb0faac595 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts
@@ -16,22 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { parseYAxisBound } from '../../src/utils/controls';
+import { parseAxisBound } from '../../src/utils/controls';
 
 describe('parseYAxisBound', () => {
   it('should return undefined for invalid values', () => {
-    expect(parseYAxisBound(null)).toBeUndefined();
-    expect(parseYAxisBound(undefined)).toBeUndefined();
-    expect(parseYAxisBound(NaN)).toBeUndefined();
-    expect(parseYAxisBound('abc')).toBeUndefined();
+    expect(parseAxisBound(null)).toBeUndefined();
+    expect(parseAxisBound(undefined)).toBeUndefined();
+    expect(parseAxisBound(NaN)).toBeUndefined();
+    expect(parseAxisBound('abc')).toBeUndefined();
   });
 
   it('should return numeric value for valid values', () => {
-    expect(parseYAxisBound(0)).toEqual(0);
-    expect(parseYAxisBound('0')).toEqual(0);
-    expect(parseYAxisBound(1)).toEqual(1);
-    expect(parseYAxisBound('1')).toEqual(1);
-    expect(parseYAxisBound(10.1)).toEqual(10.1);
-    expect(parseYAxisBound('10.1')).toEqual(10.1);
+    expect(parseAxisBound(0)).toEqual(0);
+    expect(parseAxisBound('0')).toEqual(0);
+    expect(parseAxisBound(1)).toEqual(1);
+    expect(parseAxisBound('1')).toEqual(1);
+    expect(parseAxisBound(10.1)).toEqual(10.1);
+    expect(parseAxisBound('10.1')).toEqual(10.1);
   });
 });
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
index 927ee49e8c..b445dceabb 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
@@ -36,6 +36,7 @@ import {
   getChartPadding,
   getLegendProps,
   getOverMaxHiddenFormatter,
+  getMinAndMaxFromBounds,
   sanitizeHtml,
   sortAndFilterSeries,
   sortRows,
@@ -879,3 +880,30 @@ test('getAxisType', () => {
   expect(getAxisType(GenericDataType.BOOLEAN)).toEqual(AxisType.category);
   expect(getAxisType(GenericDataType.STRING)).toEqual(AxisType.category);
 });
+
+test('getMinAndMaxFromBounds returns empty object when not truncating', () => {
+  expect(getMinAndMaxFromBounds(AxisType.value, false, 10, 100)).toEqual({});
+});
+
+test('getMinAndMaxFromBounds returns automatic bounds when truncating', () => {
+  expect(
+    getMinAndMaxFromBounds(AxisType.value, true, undefined, undefined),
+  ).toEqual({
+    min: 'dataMin',
+    max: 'dataMax',
+  });
+});
+
+test('getMinAndMaxFromBounds returns automatic upper bound when truncating', () => {
+  expect(getMinAndMaxFromBounds(AxisType.value, true, 10, undefined)).toEqual({
+    min: 10,
+    max: 'dataMax',
+  });
+});
+
+test('getMinAndMaxFromBounds returns automatic lower bound when truncating', () => {
+  expect(getMinAndMaxFromBounds(AxisType.value, true, undefined, 100)).toEqual({
+    min: 'dataMin',
+    max: 100,
+  });
+});