You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by vi...@apache.org on 2022/04/28 13:38:34 UTC

[superset] branch master updated: fix(plugin-chart-handlebars): fix overflow, debounce and control reset (#19879)

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

villebro 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 d5ea537b0e fix(plugin-chart-handlebars): fix overflow, debounce and control reset (#19879)
d5ea537b0e is described below

commit d5ea537b0eb3e102677d63811b99cf2c4b31a3ab
Author: Ville Brofeldt <33...@users.noreply.github.com>
AuthorDate: Thu Apr 28 16:38:23 2022 +0300

    fix(plugin-chart-handlebars): fix overflow, debounce and control reset (#19879)
    
    * fix(plugin-chart-handlebars): fix overflow
    
    * add debounce, fix reset controls
    
    * fix deps
    
    * remove redundant code
    
    * improve examples
    
    * add last missing resetOnHides
    
    * fix test
    
    * use isPlainObject
---
 .../plugins/plugin-chart-handlebars/package.json   | 13 ++--
 .../plugin-chart-handlebars/src/Handlebars.tsx     | 32 ++-------
 .../src/components/Handlebars/HandlebarsViewer.tsx |  9 +++
 .../plugins/plugin-chart-handlebars/src/consts.ts  |  8 ++-
 .../src/plugin/controlPanel.tsx                    | 75 ----------------------
 .../src/plugin/controls/columns.tsx                |  4 +-
 .../src/plugin/controls/groupBy.tsx                |  2 +-
 .../src/plugin/controls/handlebarTemplate.tsx      | 16 ++---
 .../src/plugin/controls/includeTime.ts             |  1 +
 .../src/plugin/controls/limits.ts                  |  1 +
 .../src/plugin/controls/metrics.tsx                |  3 +
 .../src/plugin/controls/orderBy.tsx                |  2 +
 .../src/plugin/controls/style.tsx                  | 12 ++--
 .../src/plugin/transformProps.ts                   | 38 +----------
 .../test/plugin/transformProps.test.ts             | 11 +---
 15 files changed, 56 insertions(+), 171 deletions(-)

diff --git a/superset-frontend/plugins/plugin-chart-handlebars/package.json b/superset-frontend/plugins/plugin-chart-handlebars/package.json
index c83be8bfdd..da88ada90b 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/package.json
+++ b/superset-frontend/plugins/plugin-chart-handlebars/package.json
@@ -26,19 +26,20 @@
     "access": "public"
   },
   "dependencies": {
-    "@superset-ui/chart-controls": "0.18.25",
-    "@superset-ui/core": "0.18.25",
-    "ace-builds": "^1.4.13",
-    "emotion": "^11.0.0",
-    "handlebars": "^4.7.7",
-    "react-ace": "^9.4.4"
+    "handlebars": "^4.7.7"
   },
   "peerDependencies": {
+    "@superset-ui/chart-controls": "*",
+    "@superset-ui/core": "*",
+    "ace-builds": "^1.4.14",
+    "lodash": "^4.17.11",
     "moment": "^2.26.0",
     "react": "^16.13.1",
+    "react-ace": "^9.4.4",
     "react-dom": "^16.13.1"
   },
   "devDependencies": {
+    "@types/lodash": "^4.14.149",
     "@types/jest": "^26.0.0",
     "jest": "^26.0.1"
   }
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/Handlebars.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/Handlebars.tsx
index c14e925056..c219e4256e 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/Handlebars.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/Handlebars.tsx
@@ -17,36 +17,19 @@
  * under the License.
  */
 import { styled } from '@superset-ui/core';
-import React, { createRef, useEffect } from 'react';
+import React, { createRef } from 'react';
 import { HandlebarsViewer } from './components/Handlebars/HandlebarsViewer';
 import { HandlebarsProps, HandlebarsStylesProps } from './types';
 
-// The following Styles component is a <div> element, which has been styled using Emotion
-// For docs, visit https://emotion.sh/docs/styled
-
-// Theming variables are provided for your use via a ThemeProvider
-// imported from @superset-ui/core. For variables available, please visit
-// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts
-
 const Styles = styled.div<HandlebarsStylesProps>`
   padding: ${({ theme }) => theme.gridUnit * 4}px;
   border-radius: ${({ theme }) => theme.gridUnit * 2}px;
-  height: ${({ height }) => height};
-  width: ${({ width }) => width};
-  overflow-y: scroll;
+  height: ${({ height }) => height}px;
+  width: ${({ width }) => width}px;
+  overflow: auto;
 `;
 
-/**
- * ******************* WHAT YOU CAN BUILD HERE *******************
- *  In essence, a chart is given a few key ingredients to work with:
- *  * Data: provided via `props.data`
- *  * A DOM element
- *  * FormData (your controls!) provided as props by transformProps.ts
- */
-
 export default function Handlebars(props: HandlebarsProps) {
-  // height and width are the height and width of the DOM element as it exists in the dashboard.
-  // There is also a `data` prop, which is, of course, your DATA 🎉
   const { data, height, width, formData } = props;
   const styleTemplateSource = formData.styleTemplate
     ? `<style>${formData.styleTemplate}</style>`
@@ -58,13 +41,6 @@ export default function Handlebars(props: HandlebarsProps) {
 
   const rootElem = createRef<HTMLDivElement>();
 
-  // Often, you just want to get a hold of the DOM and go nuts.
-  // Here, you can do that with createRef, and the useEffect hook.
-  useEffect(() => {
-    // const root = rootElem.current as HTMLElement;
-    // console.log('Plugin element', root);
-  });
-
   return (
     <Styles ref={rootElem} height={height} width={width}>
       <HandlebarsViewer data={{ data }} templateSource={templateSource} />
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx
index 6b3a69b0c7..67ddb83439 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx
@@ -20,6 +20,7 @@ import { SafeMarkdown, styled } from '@superset-ui/core';
 import Handlebars from 'handlebars';
 import moment from 'moment';
 import React, { useMemo, useState } from 'react';
+import { isPlainObject } from 'lodash';
 
 export interface HandlebarsViewerProps {
   templateSource: string;
@@ -64,3 +65,11 @@ Handlebars.registerHelper('dateFormat', function (context, block) {
   const f = block.hash.format || 'YYYY-MM-DD';
   return moment(context).format(f);
 });
+
+// usage: {{  }}
+Handlebars.registerHelper('stringify', (obj: any, obj2: any) => {
+  // calling without an argument
+  if (obj2 === undefined)
+    throw Error('Please call with an object. Example: `stringify myObj`');
+  return isPlainObject(obj) ? JSON.stringify(obj) : String(obj);
+});
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts b/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts
index e6b215ede3..562f654431 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts
@@ -16,8 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import { debounce } from 'lodash';
 import { formatSelectOptions } from '@superset-ui/chart-controls';
-import { addLocaleData, t } from '@superset-ui/core';
+import { addLocaleData, SLOW_DEBOUNCE, t } from '@superset-ui/core';
 import i18n from './i18n';
 
 addLocaleData(i18n);
@@ -35,3 +36,8 @@ export const PAGE_SIZE_OPTIONS = formatSelectOptions<number>([
   100,
   200,
 ]);
+
+export const debounceFunc = debounce(
+  (func: (val: string) => void, source: string) => func(source),
+  SLOW_DEBOUNCE,
+);
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controlPanel.tsx
index 32b3a55a79..da0ba7d589 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controlPanel.tsx
@@ -50,81 +50,6 @@ import { styleControlSetItem } from './controls/style';
 addLocaleData(i18n);
 
 const config: ControlPanelConfig = {
-  /**
-   * The control panel is split into two tabs: "Query" and
-   * "Chart Options". The controls that define the inputs to
-   * the chart data request, such as columns and metrics, usually
-   * reside within "Query", while controls that affect the visual
-   * appearance or functionality of the chart are under the
-   * "Chart Options" section.
-   *
-   * There are several predefined controls that can be used.
-   * Some examples:
-   * - groupby: columns to group by (tranlated to GROUP BY statement)
-   * - series: same as groupby, but single selection.
-   * - metrics: multiple metrics (translated to aggregate expression)
-   * - metric: sane as metrics, but single selection
-   * - adhoc_filters: filters (translated to WHERE or HAVING
-   *   depending on filter type)
-   * - row_limit: maximum number of rows (translated to LIMIT statement)
-   *
-   * If a control panel has both a `series` and `groupby` control, and
-   * the user has chosen `col1` as the value for the `series` control,
-   * and `col2` and `col3` as values for the `groupby` control,
-   * the resulting query will contain three `groupby` columns. This is because
-   * we considered `series` control a `groupby` query field and its value
-   * will automatically append the `groupby` field when the query is generated.
-   *
-   * It is also possible to define custom controls by importing the
-   * necessary dependencies and overriding the default parameters, which
-   * can then be placed in the `controlSetRows` section
-   * of the `Query` section instead of a predefined control.
-   *
-   * import { validateNonEmpty } from '@superset-ui/core';
-   * import {
-   *   sharedControls,
-   *   ControlConfig,
-   *   ControlPanelConfig,
-   * } from '@superset-ui/chart-controls';
-   *
-   * const myControl: ControlConfig<'SelectControl'> = {
-   *   name: 'secondary_entity',
-   *   config: {
-   *     ...sharedControls.entity,
-   *     type: 'SelectControl',
-   *     label: t('Secondary Entity'),
-   *     mapStateToProps: state => ({
-   *       sharedControls.columnChoices(state.datasource)
-   *       .columns.filter(c => c.groupby)
-   *     })
-   *     validators: [validateNonEmpty],
-   *   },
-   * }
-   *
-   * In addition to the basic drop down control, there are several predefined
-   * control types (can be set via the `type` property) that can be used. Some
-   * commonly used examples:
-   * - SelectControl: Dropdown to select single or multiple values,
-       usually columns
-   * - MetricsControl: Dropdown to select metrics, triggering a modal
-       to define Metric details
-   * - AdhocFilterControl: Control to choose filters
-   * - CheckboxControl: A checkbox for choosing true/false values
-   * - SliderControl: A slider with min/max values
-   * - TextControl: Control for text data
-   *
-   * For more control input types, check out the `incubator-superset` repo
-   * and open this file: superset-frontend/src/explore/components/controls/index.js
-   *
-   * To ensure all controls have been filled out correctly, the following
-   * validators are provided
-   * by the `@superset-ui/core/lib/validator`:
-   * - validateNonEmpty: must have at least one value
-   * - validateInteger: must be an integer value
-   * - validateNumber: must be an intger or decimal value
-   */
-
-  // For control input types, see: superset-frontend/src/explore/components/controls/index.js
   controlPanelSections: [
     sections.legacyTimeseriesTime,
     {
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/columns.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/columns.tsx
index 0582bfc23f..fd24bb75fb 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/columns.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/columns.tsx
@@ -31,7 +31,7 @@ import {
 import React from 'react';
 import { getQueryMode, isRawMode } from './shared';
 
-export const allColumns: typeof sharedControls.groupby = {
+const allColumns: typeof sharedControls.groupby = {
   type: 'SelectControl',
   label: t('Columns'),
   description: t('Columns to display'),
@@ -52,6 +52,7 @@ export const allColumns: typeof sharedControls.groupby = {
         : [],
   }),
   visibility: isRawMode,
+  resetOnHide: false,
 };
 
 const dndAllColumns: typeof sharedControls.groupby = {
@@ -75,6 +76,7 @@ const dndAllColumns: typeof sharedControls.groupby = {
     return newState;
   },
   visibility: isRawMode,
+  resetOnHide: false,
 };
 
 export const allColumnsControlSetItem: ControlSetItem = {
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/groupBy.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/groupBy.tsx
index 0df08bc1d4..e3bea44b64 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/groupBy.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/groupBy.tsx
@@ -28,6 +28,7 @@ export const groupByControlSetItem: ControlSetItem = {
   name: 'groupby',
   override: {
     visibility: isAggMode,
+    resetOnHide: false,
     mapStateToProps: (state: ControlPanelState, controlState: ControlState) => {
       const { controls } = state;
       const originalMapStateToProps = sharedControls?.groupby?.mapStateToProps;
@@ -37,7 +38,6 @@ export const groupByControlSetItem: ControlSetItem = {
         controls.percent_metrics?.value,
         controlState.value,
       ]);
-
       return newState;
     },
     rerender: ['metrics', 'percent_metrics'],
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx
index 4d86cdc928..efe027b86f 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx
@@ -25,6 +25,7 @@ import { t, validateNonEmpty } from '@superset-ui/core';
 import React from 'react';
 import { CodeEditor } from '../../components/CodeEditor/CodeEditor';
 import { ControlHeader } from '../../components/ControlHeader/controlHeader';
+import { debounceFunc } from '../../consts';
 
 interface HandlebarsCustomControlProps {
   value: string;
@@ -37,9 +38,6 @@ const HandlebarsTemplateControl = (
     props?.value ? props?.value : props?.default ? props?.default : '',
   );
 
-  const updateConfig = (source: string) => {
-    props.onChange(source);
-  };
   return (
     <div>
       <ControlHeader>{props.label}</ControlHeader>
@@ -47,7 +45,7 @@ const HandlebarsTemplateControl = (
         theme="dark"
         value={val}
         onChange={source => {
-          updateConfig(source || '');
+          debounceFunc(props.onChange, source || '');
         }}
       />
     </div>
@@ -61,11 +59,11 @@ export const handlebarsTemplateControlSetItem: ControlSetItem = {
     type: HandlebarsTemplateControl,
     label: t('Handlebars Template'),
     description: t('A handlebars template that is applied to the data'),
-    default: `<ul class="data_list">
-      {{#each data}}
-        <li>{{this}}</li>
-      {{/each}}
-    </ul>`,
+    default: `<ul class="data-list">
+  {{#each data}}
+    <li>{{stringify this}}</li>
+  {{/each}}
+</ul>`,
     isInt: false,
     renderTrigger: true,
 
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/includeTime.ts b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/includeTime.ts
index 7004f45fe3..9525cc1acf 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/includeTime.ts
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/includeTime.ts
@@ -30,5 +30,6 @@ export const includeTimeControlSetItem: ControlSetItem = {
     ),
     default: false,
     visibility: isAggMode,
+    resetOnHide: false,
   },
 };
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/limits.ts b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/limits.ts
index 701dc27aae..2c28d92742 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/limits.ts
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/limits.ts
@@ -34,5 +34,6 @@ export const timeSeriesLimitMetricControlSetItem: ControlSetItem = {
   name: 'timeseries_limit_metric',
   override: {
     visibility: isAggMode,
+    resetOnHide: false,
   },
 };
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/metrics.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/metrics.tsx
index 88777c9c31..7df35e6a66 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/metrics.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/metrics.tsx
@@ -33,6 +33,7 @@ const percentMetrics: typeof sharedControls.metrics = {
   ),
   multi: true,
   visibility: isAggMode,
+  resetOnHide: false,
   mapStateToProps: ({ datasource, controls }, controlState) => ({
     columns: datasource?.columns || [],
     savedMetrics: datasource?.metrics || [],
@@ -86,6 +87,7 @@ export const metricsControlSetItem: ControlSetItem = {
       ]),
     }),
     rerender: ['groupby', 'percent_metrics'],
+    resetOnHide: false,
   },
 };
 
@@ -99,5 +101,6 @@ export const showTotalsControlSetItem: ControlSetItem = {
       'Show total aggregations of selected metrics. Note that row limit does not apply to the result.',
     ),
     visibility: isAggMode,
+    resetOnHide: false,
   },
 };
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/orderBy.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/orderBy.tsx
index 728934d719..b7c8f8e240 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/orderBy.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/orderBy.tsx
@@ -32,6 +32,7 @@ export const orderByControlSetItem: ControlSetItem = {
       choices: datasource?.order_by_choices || [],
     }),
     visibility: isRawMode,
+    resetOnHide: false,
   },
 };
 
@@ -43,5 +44,6 @@ export const orderDescendingControlSetItem: ControlSetItem = {
     default: true,
     description: t('Whether to sort descending or ascending'),
     visibility: isAggMode,
+    resetOnHide: false,
   },
 };
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx
index 4d6f259eeb..d3776e7782 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx
@@ -25,6 +25,7 @@ import { t } from '@superset-ui/core';
 import React from 'react';
 import { CodeEditor } from '../../components/CodeEditor/CodeEditor';
 import { ControlHeader } from '../../components/ControlHeader/controlHeader';
+import { debounceFunc } from '../../consts';
 
 interface StyleCustomControlProps {
   value: string;
@@ -35,9 +36,6 @@ const StyleControl = (props: CustomControlConfig<StyleCustomControlProps>) => {
     props?.value ? props?.value : props?.default ? props?.default : '',
   );
 
-  const updateConfig = (source: string) => {
-    props.onChange(source);
-  };
   return (
     <div>
       <ControlHeader>{props.label}</ControlHeader>
@@ -46,7 +44,7 @@ const StyleControl = (props: CustomControlConfig<StyleCustomControlProps>) => {
         mode="css"
         value={val}
         onChange={source => {
-          updateConfig(source || '');
+          debounceFunc(props.onChange, source || '');
         }}
       />
     </div>
@@ -60,7 +58,11 @@ export const styleControlSetItem: ControlSetItem = {
     type: StyleControl,
     label: t('CSS Styles'),
     description: t('CSS applied to the chart'),
-    default: '',
+    default: `/*
+.data-list {
+  background-color: yellow;
+}
+*/`,
     isInt: false,
     renderTrigger: true,
 
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/transformProps.ts b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/transformProps.ts
index cb83e112d8..fe0e5329a7 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/transformProps.ts
@@ -19,49 +19,13 @@
 import { ChartProps, TimeseriesDataRecord } from '@superset-ui/core';
 
 export default function transformProps(chartProps: ChartProps) {
-  /**
-   * This function is called after a successful response has been
-   * received from the chart data endpoint, and is used to transform
-   * the incoming data prior to being sent to the Visualization.
-   *
-   * The transformProps function is also quite useful to return
-   * additional/modified props to your data viz component. The formData
-   * can also be accessed from your Handlebars.tsx file, but
-   * doing supplying custom props here is often handy for integrating third
-   * party libraries that rely on specific props.
-   *
-   * A description of properties in `chartProps`:
-   * - `height`, `width`: the height/width of the DOM element in which
-   *   the chart is located
-   * - `formData`: the chart data request payload that was sent to the
-   *   backend.
-   * - `queriesData`: the chart data response payload that was received
-   *   from the backend. Some notable properties of `queriesData`:
-   *   - `data`: an array with data, each row with an object mapping
-   *     the column/alias to its value. Example:
-   *     `[{ col1: 'abc', metric1: 10 }, { col1: 'xyz', metric1: 20 }]`
-   *   - `rowcount`: the number of rows in `data`
-   *   - `query`: the query that was issued.
-   *
-   * Please note: the transformProps function gets cached when the
-   * application loads. When making changes to the `transformProps`
-   * function during development with hot reloading, changes won't
-   * be seen until restarting the development server.
-   */
   const { width, height, formData, queriesData } = chartProps;
   const data = queriesData[0].data as TimeseriesDataRecord[];
 
   return {
     width,
     height,
-
-    data: data.map(item => ({
-      ...item,
-      // convert epoch to native Date
-      // eslint-disable-next-line no-underscore-dangle
-      __timestamp: new Date(item.__timestamp as number),
-    })),
-    // and now your control data, manipulated as needed, and passed through as props!
+    data,
     formData,
   };
 }
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/test/plugin/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-handlebars/test/plugin/transformProps.test.ts
index 24aa3c3745..f9bab5a91a 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/test/plugin/transformProps.test.ts
+++ b/superset-frontend/plugins/plugin-chart-handlebars/test/plugin/transformProps.test.ts
@@ -31,15 +31,12 @@ describe('Handlebars tranformProps', () => {
     height: 500,
     viz_type: 'handlebars',
   };
+  const data = [{ name: 'Hulk', sum__num: 1, __timestamp: 599616000000 }];
   const chartProps = new ChartProps<QueryFormData>({
     formData,
     width: 800,
     height: 600,
-    queriesData: [
-      {
-        data: [{ name: 'Hulk', sum__num: 1, __timestamp: 599616000000 }],
-      },
-    ],
+    queriesData: [{ data }],
   });
 
   it('should tranform chart props for viz', () => {
@@ -47,9 +44,7 @@ describe('Handlebars tranformProps', () => {
       expect.objectContaining({
         width: 800,
         height: 600,
-        data: [
-          { name: 'Hulk', sum__num: 1, __timestamp: new Date(599616000000) },
-        ],
+        data,
       }),
     );
   });