From 1fd26fbda2d0a56be8091def2495a20068f3949f Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Mon, 1 Jun 2020 18:06:06 +0200 Subject: [PATCH 1/8] fix: remove double rendering Use only the ResizeObseerver to handle chart sizing at the initialization. fix #690 --- src/components/chart_resizer.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/chart_resizer.tsx b/src/components/chart_resizer.tsx index 199f9b3d41..eba232e279 100644 --- a/src/components/chart_resizer.tsx +++ b/src/components/chart_resizer.tsx @@ -36,6 +36,8 @@ interface ResizerDispatchProps { type ResizerProps = ResizerStateProps & ResizerDispatchProps; +const DEFAULT_RESIZE_DEBOUNCE = 200; + class Resizer extends React.Component { private initialResizeComplete = false; private containerRef: RefObject; @@ -53,10 +55,8 @@ class Resizer extends React.Component { componentDidMount() { this.onResizeDebounced = debounce(this.onResize, this.props.resizeDebounce); if (this.containerRef.current) { - const { clientWidth, clientHeight } = this.containerRef.current; - this.props.updateParentDimensions({ width: clientWidth, height: clientHeight, top: 0, left: 0 }); + this.ro.observe(this.containerRef.current as Element); } - this.ro.observe(this.containerRef.current as Element); } componentWillUnmount() { @@ -102,11 +102,9 @@ const mapDispatchToProps = (dispatch: Dispatch): ResizerDispatchProps => ); const mapStateToProps = (state: GlobalChartState): ResizerStateProps => { - const settings = getSettingsSpecSelector(state); - const resizeDebounce = - settings.resizeDebounce === undefined || settings.resizeDebounce === null ? 200 : settings.resizeDebounce; + const { resizeDebounce } = getSettingsSpecSelector(state); return { - resizeDebounce, + resizeDebounce: resizeDebounce == null || Number.isNaN(resizeDebounce) ? DEFAULT_RESIZE_DEBOUNCE : resizeDebounce, }; }; From 2b0c4723cc48b2866863084516cfe32f830e417c Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 3 Jun 2020 17:34:36 +0200 Subject: [PATCH 2/8] fix: annotation markers render when parent size is computed --- .playground/playground.tsx | 2 +- .../renderer/dom/annotations/annotations.tsx | 55 ++++++++++--------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/.playground/playground.tsx b/.playground/playground.tsx index 96d9dcfc8c..ff41c14bc5 100644 --- a/.playground/playground.tsx +++ b/.playground/playground.tsx @@ -17,7 +17,7 @@ * under the License. */ import React from 'react'; -import { Example } from '../stories/treemap/6_custom_style'; +import { Example } from '../stories/annotations/lines/3_x_time'; export class Playground extends React.Component { render() { diff --git a/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx b/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx index daa5732fc8..eb069bc0ff 100644 --- a/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx +++ b/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx @@ -55,6 +55,32 @@ interface AnnotationsOwnProps { type AnnotationsProps = AnnotationsDispatchProps & AnnotationsStateProps & AnnotationsOwnProps; +function renderAnnotationLineMarkers( + chartDimensions: Dimensions, + annotationLines: AnnotationLineProps[], + id: AnnotationId, +) { + return annotationLines.reduce((markers, { marker }: AnnotationLineProps, index: number) => { + if (!marker) { + return markers; + } + + const { icon, color, position } = marker; + const style = { + color, + top: chartDimensions.top + position.top, + left: chartDimensions.left + position.left, + }; + + markers.push( +
+ {icon} +
, + ); + + return markers; + }, []); +} const AnnotationsComponent = ({ tooltipState, isChartEmpty, @@ -65,31 +91,6 @@ const AnnotationsComponent = ({ chartId, onPointerMove, }: AnnotationsProps) => { - const renderAnnotationLineMarkers = useCallback( - (annotationLines: AnnotationLineProps[], id: AnnotationId) => - annotationLines.reduce((markers, { marker }: AnnotationLineProps, index: number) => { - if (!marker) { - return markers; - } - - const { icon, color, position } = marker; - const style = { - color, - top: chartDimensions.top + position.top, - left: chartDimensions.left + position.left, - }; - - markers.push( -
- {icon} -
, - ); - - return markers; - }, []), - [], // eslint-disable-line react-hooks/exhaustive-deps - ); - const renderAnnotationMarkers = useCallback((): JSX.Element[] => { const markers: JSX.Element[] = []; @@ -101,13 +102,13 @@ const AnnotationsComponent = ({ if (isLineAnnotation(annotationSpec)) { const annotationLines = dimensions as AnnotationLineProps[]; - const lineMarkers = renderAnnotationLineMarkers(annotationLines, id); + const lineMarkers = renderAnnotationLineMarkers(chartDimensions, annotationLines, id); markers.push(...lineMarkers); } }); return markers; - }, [annotationDimensions, annotationSpecs, renderAnnotationLineMarkers]); + }, [chartDimensions, annotationDimensions, annotationSpecs]); const onScroll = useCallback(() => { onPointerMove({ x: -1, y: -1 }, new Date().getTime()); From 72b6c36e4159a6ad4b1eccd6fc635a63c404ef98 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 3 Jun 2020 17:37:03 +0200 Subject: [PATCH 3/8] refactor: check w/h at chart state level --- .../partition_chart/layout/viewmodel/viewmodel.ts | 7 +++---- .../partition_chart/state/chart_state.tsx | 2 +- .../xy_chart/renderer/canvas/xy_chart.tsx | 13 +++---------- src/chart_types/xy_chart/state/chart_state.tsx | 2 +- src/components/chart_container.tsx | 7 ++++++- src/state/selectors/get_internal_is_intialized.ts | 11 +++++++++-- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/chart_types/partition_chart/layout/viewmodel/viewmodel.ts b/src/chart_types/partition_chart/layout/viewmodel/viewmodel.ts index 66f2790ea9..9e31f4d244 100644 --- a/src/chart_types/partition_chart/layout/viewmodel/viewmodel.ts +++ b/src/chart_types/partition_chart/layout/viewmodel/viewmodel.ts @@ -69,9 +69,9 @@ function topGrooveAccessor(topGroovePx: Pixels) { } export const VerticalAlignments = Object.freeze({ - top: 'top' as 'top', - middle: 'middle' as 'middle', - bottom: 'bottom' as 'bottom', + top: 'top' as const, + middle: 'middle' as const, + bottom: 'bottom' as const, }); // we might add more in the future; also, the intent is to still be of CanvasTextBaseline @@ -207,7 +207,6 @@ export function shapeViewModel( partitionLayout, sectorLineWidth, } = config; - const innerWidth = width * (1 - Math.min(1, margin.left + margin.right)); const innerHeight = height * (1 - Math.min(1, margin.top + margin.bottom)); diff --git a/src/chart_types/partition_chart/state/chart_state.tsx b/src/chart_types/partition_chart/state/chart_state.tsx index 372cc92cf7..cf7bd8ea18 100644 --- a/src/chart_types/partition_chart/state/chart_state.tsx +++ b/src/chart_types/partition_chart/state/chart_state.tsx @@ -47,7 +47,7 @@ export class PartitionState implements InternalChartState { } chartType = ChartTypes.Partition; isInitialized(globalState: GlobalChartState) { - return globalState.specsInitialized && getPieSpec(globalState) !== null; + return getPieSpec(globalState) !== null; } isBrushAvailable() { return false; diff --git a/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx b/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx index 115716b3de..6a398cf6e2 100644 --- a/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx @@ -137,19 +137,12 @@ class XYChartComponent extends React.Component { isChartEmpty, chartContainerDimensions: { width, height }, } = this.props; - if (!initialized || width === 0 || height === 0) { + + if (!initialized || isChartEmpty) { this.ctx = null; return null; } - if (isChartEmpty) { - this.ctx = null; - return ( -
-

No data to display

-
- ); - } return ( 0; + return getSeriesSpecsSelector(globalState).length > 0; } isBrushAvailable(globalState: GlobalChartState) { diff --git a/src/components/chart_container.tsx b/src/components/chart_container.tsx index 4fd72ba329..9a5ab8657f 100644 --- a/src/components/chart_container.tsx +++ b/src/components/chart_container.tsx @@ -137,14 +137,19 @@ class ChartContainerComponent extends React.Component { }; render() { - const { initialized } = this.props; + const { initialized, isChartEmpty } = this.props; if (!initialized) { + return null; + } + + if (isChartEmpty) { return (

No data to display

); } + const { pointerCursor, internalChartRenderer, getChartContainerRef, forwardStageRef } = this.props; return (
{ + const { + parentDimensions: { width, height }, + specsInitialized, + } = state; + + if (width <= 0 || height <= 0 || !specsInitialized) { + return false; + } if (state.internalChartState) { return state.internalChartState.isInitialized(state); - } else { - return false; } + return false; }; From 5c7a317bfdb5039401ffee08c72b02da718cda08 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 3 Jun 2020 17:42:26 +0200 Subject: [PATCH 4/8] refactor: resizeDebounce defined check --- src/components/chart_resizer.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/chart_resizer.tsx b/src/components/chart_resizer.tsx index eba232e279..b70e74ea4c 100644 --- a/src/components/chart_resizer.tsx +++ b/src/components/chart_resizer.tsx @@ -25,6 +25,7 @@ import { Dispatch, bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; import { GlobalChartState } from '../state/chart_state'; +import { isDefined } from '../chart_types/xy_chart/state/utils'; interface ResizerStateProps { resizeDebounce: number; @@ -104,7 +105,8 @@ const mapDispatchToProps = (dispatch: Dispatch): ResizerDispatchProps => const mapStateToProps = (state: GlobalChartState): ResizerStateProps => { const { resizeDebounce } = getSettingsSpecSelector(state); return { - resizeDebounce: resizeDebounce == null || Number.isNaN(resizeDebounce) ? DEFAULT_RESIZE_DEBOUNCE : resizeDebounce, + resizeDebounce: + !isDefined(resizeDebounce) || Number.isNaN(resizeDebounce) ? DEFAULT_RESIZE_DEBOUNCE : resizeDebounce, }; }; From 1c77a00b2ccc898c848d7a3f47d5088434ba90b5 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 10 Jun 2020 01:28:29 +0200 Subject: [PATCH 5/8] fix: double rendering --- .playground/index.html | 8 +++ .playground/playground.tsx | 72 +++++++++++++++++-- package.json | 1 + scripts/setup_enzyme.ts | 30 ++++++++ .../renderer/canvas/connected_component.tsx | 4 +- .../goal_chart/state/chart_state.tsx | 3 +- .../renderer/canvas/partition.tsx | 4 +- .../renderer/dom/highlighter_hover.tsx | 4 +- .../renderer/dom/highlighter_legend.tsx | 4 +- .../partition_chart/state/chart_state.tsx | 3 +- src/chart_types/xy_chart/domains/x_domain.ts | 2 +- .../xy_chart/renderer/canvas/xy_chart.tsx | 4 +- .../renderer/dom/annotations/annotations.tsx | 4 +- .../xy_chart/renderer/dom/brush.tsx | 4 +- .../xy_chart/renderer/dom/crosshair.tsx | 4 +- .../xy_chart/renderer/dom/highlighter.tsx | 4 +- .../xy_chart/state/chart_state.tsx | 3 +- src/components/chart.test.tsx | 28 ++++++-- src/components/chart.tsx | 4 +- src/components/chart_background.tsx | 4 +- src/components/chart_container.tsx | 24 ++++--- src/components/legend/legend.test.tsx | 2 +- src/components/legend/legend.tsx | 4 +- src/components/tooltip/tooltip.tsx | 4 +- src/state/chart_state.ts | 6 +- .../selectors/get_internal_is_intialized.ts | 32 +++++++-- yarn.lock | 19 +++++ 27 files changed, 226 insertions(+), 59 deletions(-) diff --git a/.playground/index.html b/.playground/index.html index 4ac6cbb760..4f0a564770 100644 --- a/.playground/index.html +++ b/.playground/index.html @@ -24,6 +24,11 @@ height: 100%;*/ /* overflow-x: hidden; */ } + + #root { + height: 500px; + } + .chart { background: white; /*display: inline-block; @@ -40,14 +45,17 @@ width: 100%; overflow: auto; } + .page { padding: 100px; } + label { display: block; } +
diff --git a/.playground/playground.tsx b/.playground/playground.tsx index d123c98912..e19342b187 100644 --- a/.playground/playground.tsx +++ b/.playground/playground.tsx @@ -17,16 +17,78 @@ * under the License. */ -import React from 'react'; +import React, { useState } from 'react'; -import { Example } from '../stories/treemap/6_custom_style'; +import { Chart, BarSeries, LegendColorPicker, Settings, ScaleType } from '../src'; +import { SeededDataGenerator } from '../src/mocks/utils'; + +const dg = new SeededDataGenerator(); + +type SetColorFn = (color: string) => void; +const legendColorPickerFn = (setColors: SetColorFn, customColor: string): LegendColorPicker => ({ onClose }) => ( +
+ Custom Color Picker + + +
+); +function LegendColorPickerMock(props: { onLegendItemClick: () => void; customColor: string }) { + const data = dg.generateGroupedSeries(10, 4, 'split'); + const [color, setColor] = useState('red'); + + return ( + <> + + + + + + + ); +} export class Playground extends React.Component { render() { return ( -
-
{Example()}
-
+ { + // npo + }} + /> ); } } diff --git a/package.json b/package.json index 32ff10f206..e3d778a62a 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "@types/jest": "^25.2.1", "@types/jest-environment-puppeteer": "^4.3.1", "@types/jest-image-snapshot": "^2.12.0", + "@types/jsdom": "^16.2.3", "@types/lodash": "^4.14.121", "@types/luxon": "^1.11.1", "@types/moment-timezone": "^0.5.12", diff --git a/scripts/setup_enzyme.ts b/scripts/setup_enzyme.ts index 2d7f0276b1..424ac7dab6 100644 --- a/scripts/setup_enzyme.ts +++ b/scripts/setup_enzyme.ts @@ -23,3 +23,33 @@ import Adapter from 'enzyme-adapter-react-16'; configure({ adapter: new Adapter() }); process.env.RNG_SEED = 'jest-unit-tests'; + +jest.useFakeTimers(); + +window.requestAnimationFrame = function(callback) { + callback(0); + return 0; +}; + +type ResizeObserverMockCallback = (entries: Array<{ contentRect: { width: number; height: number } }>) => void; +class ResizeObserverMock { + callback: ResizeObserverMockCallback; + constructor(callback: ResizeObserverMockCallback) { + this.callback = callback; + } + + observe() { + this.callback([{ contentRect: { width: 200, height: 200 } }]); + } + + unobserve() { + // do nothing + } + + disconnect() { + // do nothing + } +} + +// @ts-ignore +window.ResizeObserver = ResizeObserverMock; diff --git a/src/chart_types/goal_chart/renderer/canvas/connected_component.tsx b/src/chart_types/goal_chart/renderer/canvas/connected_component.tsx index 88849ea4c7..b65b7a18b1 100644 --- a/src/chart_types/goal_chart/renderer/canvas/connected_component.tsx +++ b/src/chart_types/goal_chart/renderer/canvas/connected_component.tsx @@ -23,7 +23,7 @@ import { bindActionCreators, Dispatch } from 'redux'; import { onChartRendered } from '../../../../state/actions/chart'; import { GlobalChartState } from '../../../../state/chart_state'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { Dimensions } from '../../../../utils/dimensions'; import { BulletViewModel, nullShapeViewModel, ShapeViewModel } from '../../layout/types/viewmodel_types'; import { geometries } from '../../state/selectors/geometries'; @@ -154,7 +154,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = { }; const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return DEFAULT_PROPS; } return { diff --git a/src/chart_types/goal_chart/state/chart_state.tsx b/src/chart_types/goal_chart/state/chart_state.tsx index eb974a9881..09e633e18d 100644 --- a/src/chart_types/goal_chart/state/chart_state.tsx +++ b/src/chart_types/goal_chart/state/chart_state.tsx @@ -23,6 +23,7 @@ import { ChartTypes } from '../..'; import { LegendItem } from '../../../commons/legend'; import { Tooltip } from '../../../components/tooltip'; import { InternalChartState, GlobalChartState, BackwardRef } from '../../../state/chart_state'; +import { InitStatus } from '../../../state/selectors/get_internal_is_intialized'; import { LegendItemLabel } from '../../../state/selectors/get_legend_items_labels'; import { Goal } from '../renderer/canvas/connected_component'; import { getSpecOrNull } from './selectors/goal_spec'; @@ -51,7 +52,7 @@ export class GoalState implements InternalChartState { } isInitialized(globalState: GlobalChartState) { - return globalState.specsInitialized && getSpecOrNull(globalState) !== null; + return getSpecOrNull(globalState) !== null ? InitStatus.Initialized : InitStatus.ChartNotInitialized; } isBrushAvailable() { diff --git a/src/chart_types/partition_chart/renderer/canvas/partition.tsx b/src/chart_types/partition_chart/renderer/canvas/partition.tsx index 8283695e2c..f7b9c9731e 100644 --- a/src/chart_types/partition_chart/renderer/canvas/partition.tsx +++ b/src/chart_types/partition_chart/renderer/canvas/partition.tsx @@ -24,7 +24,7 @@ import { bindActionCreators, Dispatch } from 'redux'; import { onChartRendered } from '../../../../state/actions/chart'; import { GlobalChartState } from '../../../../state/chart_state'; import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { Dimensions } from '../../../../utils/dimensions'; import { nullShapeViewModel, QuadViewModel, ShapeViewModel } from '../../layout/types/viewmodel_types'; import { INPUT_KEY } from '../../layout/utils/group_by_rollup'; @@ -172,7 +172,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = { }; const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return DEFAULT_PROPS; } return { diff --git a/src/chart_types/partition_chart/renderer/dom/highlighter_hover.tsx b/src/chart_types/partition_chart/renderer/dom/highlighter_hover.tsx index c446c9c957..246c193197 100644 --- a/src/chart_types/partition_chart/renderer/dom/highlighter_hover.tsx +++ b/src/chart_types/partition_chart/renderer/dom/highlighter_hover.tsx @@ -21,13 +21,13 @@ import { connect } from 'react-redux'; import { GlobalChartState } from '../../../../state/chart_state'; import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { partitionGeometries } from '../../state/selectors/geometries'; import { getPickedShapes } from '../../state/selectors/picked_shapes'; import { HighlighterComponent, HighlighterProps, DEFAULT_PROPS } from './highlighter'; const hoverMapStateToProps = (state: GlobalChartState): HighlighterProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return DEFAULT_PROPS; } diff --git a/src/chart_types/partition_chart/renderer/dom/highlighter_legend.tsx b/src/chart_types/partition_chart/renderer/dom/highlighter_legend.tsx index 19bed6569c..76dc11b118 100644 --- a/src/chart_types/partition_chart/renderer/dom/highlighter_legend.tsx +++ b/src/chart_types/partition_chart/renderer/dom/highlighter_legend.tsx @@ -21,13 +21,13 @@ import { connect } from 'react-redux'; import { GlobalChartState } from '../../../../state/chart_state'; import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { partitionGeometries } from '../../state/selectors/geometries'; import { getHighlightedSectorsSelector } from '../../state/selectors/get_highlighted_shapes'; import { HighlighterComponent, HighlighterProps, DEFAULT_PROPS } from './highlighter'; const legendMapStateToProps = (state: GlobalChartState): HighlighterProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return DEFAULT_PROPS; } diff --git a/src/chart_types/partition_chart/state/chart_state.tsx b/src/chart_types/partition_chart/state/chart_state.tsx index c2559497b8..5b609a3df3 100644 --- a/src/chart_types/partition_chart/state/chart_state.tsx +++ b/src/chart_types/partition_chart/state/chart_state.tsx @@ -22,6 +22,7 @@ import React from 'react'; import { ChartTypes } from '../..'; import { Tooltip } from '../../../components/tooltip'; import { InternalChartState, GlobalChartState, BackwardRef } from '../../../state/chart_state'; +import { InitStatus } from '../../../state/selectors/get_internal_is_intialized'; import { Partition } from '../renderer/canvas/partition'; import { HighlighterFromHover } from '../renderer/dom/highlighter_hover'; import { HighlighterFromLegend } from '../renderer/dom/highlighter_legend'; @@ -51,7 +52,7 @@ export class PartitionState implements InternalChartState { } isInitialized(globalState: GlobalChartState) { - return getPieSpec(globalState) !== null; + return getPieSpec(globalState) !== null ? InitStatus.Initialized : InitStatus.SpecNotInitialized; } isBrushAvailable() { diff --git a/src/chart_types/xy_chart/domains/x_domain.ts b/src/chart_types/xy_chart/domains/x_domain.ts index 667a847b44..e66cfb86ad 100644 --- a/src/chart_types/xy_chart/domains/x_domain.ts +++ b/src/chart_types/xy_chart/domains/x_domain.ts @@ -47,7 +47,7 @@ export function mergeXDomain( ): XDomain { const mainXScaleType = convertXScaleTypes(specs); if (!mainXScaleType) { - throw new Error('Cannot merge the domain. Missing X scale types'); + throw new Error(`Cannot merge the domain. Missing X scale types ${JSON.stringify(specs)}`); } const values = [...xValues.values()]; diff --git a/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx b/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx index 46c4670648..8a30aa1929 100644 --- a/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx @@ -27,7 +27,7 @@ import { GlobalChartState } from '../../../../state/chart_state'; import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; import { Rotation } from '../../../../utils/commons'; import { Dimensions } from '../../../../utils/dimensions'; @@ -219,7 +219,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = { }; const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return DEFAULT_PROPS; } diff --git a/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx b/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx index 47f9e30640..5b490ce8f7 100644 --- a/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx +++ b/src/chart_types/xy_chart/renderer/dom/annotations/annotations.tsx @@ -23,7 +23,7 @@ import { bindActionCreators, Dispatch } from 'redux'; import { onPointerMove as onPointerMoveAction } from '../../../../../state/actions/mouse'; import { GlobalChartState, BackwardRef } from '../../../../../state/chart_state'; -import { getInternalIsInitializedSelector } from '../../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../../state/selectors/get_internal_is_intialized'; import { Dimensions } from '../../../../../utils/dimensions'; import { AnnotationId } from '../../../../../utils/ids'; import { AnnotationLineProps } from '../../../annotations/line/types'; @@ -139,7 +139,7 @@ const mapDispatchToProps = (dispatch: Dispatch): AnnotationsDispatchProps => bindActionCreators({ onPointerMove: onPointerMoveAction }, dispatch); const mapStateToProps = (state: GlobalChartState): AnnotationsStateProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return { isChartEmpty: true, chartDimensions: { top: 0, left: 0, width: 0, height: 0 }, diff --git a/src/chart_types/xy_chart/renderer/dom/brush.tsx b/src/chart_types/xy_chart/renderer/dom/brush.tsx index 129fa9a5a9..d803115920 100644 --- a/src/chart_types/xy_chart/renderer/dom/brush.tsx +++ b/src/chart_types/xy_chart/renderer/dom/brush.tsx @@ -23,7 +23,7 @@ import { connect } from 'react-redux'; import { clearCanvas, withContext, withClip } from '../../../../renderers/canvas'; import { GlobalChartState } from '../../../../state/chart_state'; import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { Dimensions } from '../../../../utils/dimensions'; import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; import { getBrushAreaSelector } from '../../state/selectors/get_brush_area'; @@ -141,7 +141,7 @@ class BrushToolComponent extends React.Component { } const mapStateToProps = (state: GlobalChartState): Props => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return { initialized: false, isBrushing: false, diff --git a/src/chart_types/xy_chart/renderer/dom/crosshair.tsx b/src/chart_types/xy_chart/renderer/dom/crosshair.tsx index 0db4204fc9..7ee917ddad 100644 --- a/src/chart_types/xy_chart/renderer/dom/crosshair.tsx +++ b/src/chart_types/xy_chart/renderer/dom/crosshair.tsx @@ -24,7 +24,7 @@ import { TooltipType } from '../../../../specs'; import { GlobalChartState } from '../../../../state/chart_state'; import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized'; import { Rotation } from '../../../../utils/commons'; import { Dimensions } from '../../../../utils/dimensions'; import { LIGHT_THEME } from '../../../../utils/themes/light_theme'; @@ -116,7 +116,7 @@ class CrosshairComponent extends React.Component { } const mapStateToProps = (state: GlobalChartState): CrosshairProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return { theme: LIGHT_THEME, chartRotation: 0, diff --git a/src/chart_types/xy_chart/renderer/dom/highlighter.tsx b/src/chart_types/xy_chart/renderer/dom/highlighter.tsx index cc6fdb9ef4..a72e9b391c 100644 --- a/src/chart_types/xy_chart/renderer/dom/highlighter.tsx +++ b/src/chart_types/xy_chart/renderer/dom/highlighter.tsx @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import { GlobalChartState } from '../../../../state/chart_state'; import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; -import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; +import { InitStatus, getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized'; import { Rotation } from '../../../../utils/commons'; import { Dimensions } from '../../../../utils/dimensions'; import { isPointGeometry, IndexedGeometry } from '../../../../utils/geometry'; @@ -94,7 +94,7 @@ class HighlighterComponent extends React.Component { } const mapStateToProps = (state: GlobalChartState): HighlighterProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return { initialized: false, chartId: state.chartId, diff --git a/src/chart_types/xy_chart/state/chart_state.tsx b/src/chart_types/xy_chart/state/chart_state.tsx index 6671681f0c..33b2c07008 100644 --- a/src/chart_types/xy_chart/state/chart_state.tsx +++ b/src/chart_types/xy_chart/state/chart_state.tsx @@ -24,6 +24,7 @@ import { LegendItemExtraValues } from '../../../commons/legend'; import { SeriesKey } from '../../../commons/series_id'; import { Tooltip } from '../../../components/tooltip'; import { InternalChartState, GlobalChartState, BackwardRef } from '../../../state/chart_state'; +import { InitStatus } from '../../../state/selectors/get_internal_is_intialized'; import { htmlIdGenerator } from '../../../utils/commons'; import { XYChart } from '../renderer/canvas/xy_chart'; import { Annotations } from '../renderer/dom/annotations'; @@ -69,7 +70,7 @@ export class XYAxisChartState implements InternalChartState { } isInitialized(globalState: GlobalChartState) { - return getSeriesSpecsSelector(globalState).length > 0; + return getSeriesSpecsSelector(globalState).length > 0 ? InitStatus.Initialized : InitStatus.SpecNotInitialized; } isBrushAvailable(globalState: GlobalChartState) { diff --git a/src/components/chart.test.tsx b/src/components/chart.test.tsx index f131857ee3..1f34962836 100644 --- a/src/components/chart.test.tsx +++ b/src/components/chart.test.tsx @@ -17,24 +17,44 @@ * under the License. */ -import { render } from 'enzyme'; +import { mount } from 'enzyme'; import React from 'react'; -import { Settings } from '../specs'; +import { Settings, BarSeries } from '../specs'; import { Chart } from './chart'; describe('Chart', () => { it('should render \'No data to display\' without series', () => { - const wrapper = render(); + const wrapper = mount(); expect(wrapper.text()).toContain('No data to display'); }); it('should render \'No data to display\' with settings but without series', () => { - const wrapper = render( + const wrapper = mount( , ); expect(wrapper.text()).toContain('No data to display'); }); + + it('should render \'No data to display\' with an empty dataset', () => { + const wrapper = mount( + + + + , + ); + expect(wrapper.text()).toContain('No data to display'); + }); + + it('should render the legend name test', () => { + const wrapper = mount( + + + + , + ); + expect(wrapper.html()).toMatchSnapshot(); + }); }); diff --git a/src/components/chart.tsx b/src/components/chart.tsx index 7fe2ae72ff..94fcf7b43b 100644 --- a/src/components/chart.tsx +++ b/src/components/chart.tsx @@ -28,7 +28,7 @@ import { PointerEvent } from '../specs'; import { SpecsParser } from '../specs/specs_parser'; import { onExternalPointerEvent } from '../state/actions/events'; import { chartStoreReducer, GlobalChartState } from '../state/chart_state'; -import { getInternalIsInitializedSelector } from '../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../state/selectors/get_internal_is_intialized'; import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; import { ChartSize, getChartSize } from '../utils/chart_size'; import { Position } from '../utils/commons'; @@ -80,7 +80,7 @@ export class Chart extends React.Component { }; this.unsubscribeToStore = this.chartStore.subscribe(() => { const state = this.chartStore.getState(); - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return; } diff --git a/src/components/chart_background.tsx b/src/components/chart_background.tsx index 3598592488..d6157dd3e2 100644 --- a/src/components/chart_background.tsx +++ b/src/components/chart_background.tsx @@ -21,7 +21,7 @@ import { connect } from 'react-redux'; import { GlobalChartState } from '../state/chart_state'; import { getChartThemeSelector } from '../state/selectors/get_chart_theme'; -import { getInternalIsInitializedSelector } from '../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../state/selectors/get_internal_is_intialized'; interface ChartBackgroundProps { backgroundColor: string; @@ -37,7 +37,7 @@ export class ChartBackgroundComponent extends React.Component { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return { backgroundColor: 'transparent', }; diff --git a/src/components/chart_container.tsx b/src/components/chart_container.tsx index 2d8a58e18d..6a87992484 100644 --- a/src/components/chart_container.tsx +++ b/src/components/chart_container.tsx @@ -28,13 +28,13 @@ import { getInternalChartRendererSelector } from '../state/selectors/get_chart_t import { getInternalPointerCursor } from '../state/selectors/get_internal_cursor_pointer'; import { getInternalIsBrushingSelector } from '../state/selectors/get_internal_is_brushing'; import { getInternalIsBrushingAvailableSelector } from '../state/selectors/get_internal_is_brushing_available'; -import { getInternalIsInitializedSelector } from '../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../state/selectors/get_internal_is_intialized'; import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; import { isInternalChartEmptySelector } from '../state/selectors/is_chart_empty'; import { deepEqual } from '../utils/fast_deep_equal'; interface ChartContainerComponentStateProps { - initialized: boolean; + initialized: InitStatus; isChartEmpty?: boolean; pointerCursor: string; isBrushing: boolean; @@ -144,18 +144,20 @@ class ChartContainerComponent extends React.Component { render() { const { initialized, isChartEmpty } = this.props; - if (!initialized) { + if ( + initialized === InitStatus.ParentSizeInvalid + || initialized === InitStatus.SpecNotInitialized + || initialized === InitStatus.ChartNotInitialized + ) { return null; } - - if (isChartEmpty) { + if (initialized === InitStatus.MissingChartType || isChartEmpty === true) { return (

No data to display

); } - const { pointerCursor, internalChartRenderer, getChartContainerRef, forwardStageRef } = this.props; return (
{ - if (!getInternalIsInitializedSelector(state)) { + const status = getInternalIsInitializedSelector(state); + + if (status !== InitStatus.Initialized) { return { - initialized: false, - isChartEmpty: true, + initialized: status, + isChartEmpty: undefined, pointerCursor: 'default', isBrushingAvailable: false, isBrushing: false, @@ -196,7 +200,7 @@ const mapStateToProps = (state: GlobalChartState): ChartContainerComponentStateP } return { - initialized: true, + initialized: status, isChartEmpty: isInternalChartEmptySelector(state), pointerCursor: getInternalPointerCursor(state), isBrushingAvailable: getInternalIsBrushingAvailableSelector(state), diff --git a/src/components/legend/legend.test.tsx b/src/components/legend/legend.test.tsx index 68e98ebb6a..b3eedfeef8 100644 --- a/src/components/legend/legend.test.tsx +++ b/src/components/legend/legend.test.tsx @@ -156,7 +156,7 @@ describe('Legend', () => { class LegendColorPickerMock extends Component< { onLegendItemClick: () => void; customColor: string }, { colors: string[] } - > { + > { state = { colors: ['red'], }; diff --git a/src/components/legend/legend.tsx b/src/components/legend/legend.tsx index 364655b795..c5a0340921 100644 --- a/src/components/legend/legend.tsx +++ b/src/components/legend/legend.tsx @@ -33,7 +33,7 @@ import { } from '../../state/actions/legend'; import { GlobalChartState } from '../../state/chart_state'; import { getChartThemeSelector } from '../../state/selectors/get_chart_theme'; -import { getInternalIsInitializedSelector } from '../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../state/selectors/get_internal_is_intialized'; import { getLegendItemsSelector } from '../../state/selectors/get_legend_items'; import { getLegendExtraValuesSelector } from '../../state/selectors/get_legend_items_values'; import { getLegendSizeSelector } from '../../state/selectors/get_legend_size'; @@ -146,7 +146,7 @@ const EMPTY_DEFAULT_STATE = { showExtra: false, }; const mapStateToProps = (state: GlobalChartState): LegendStateProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return EMPTY_DEFAULT_STATE; } const { diff --git a/src/components/tooltip/tooltip.tsx b/src/components/tooltip/tooltip.tsx index 8b776b6dbd..ce46bf1d0a 100644 --- a/src/components/tooltip/tooltip.tsx +++ b/src/components/tooltip/tooltip.tsx @@ -26,7 +26,7 @@ import { TooltipValueFormatter, TooltipSettings, TooltipValue } from '../../spec import { onPointerMove } from '../../state/actions/mouse'; import { GlobalChartState, BackwardRef } from '../../state/chart_state'; import { getChartRotationSelector } from '../../state/selectors/get_chart_rotation'; -import { getInternalIsInitializedSelector } from '../../state/selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from '../../state/selectors/get_internal_is_intialized'; import { getInternalIsTooltipVisibleSelector } from '../../state/selectors/get_internal_is_tooltip_visible'; import { getInternalTooltipAnchorPositionSelector } from '../../state/selectors/get_internal_tooltip_anchor_position'; import { getInternalTooltipInfoSelector } from '../../state/selectors/get_internal_tooltip_info'; @@ -210,7 +210,7 @@ const mapDispatchToProps = (dispatch: Dispatch): TooltipDispatchProps => bindActionCreators({ onPointerMove }, dispatch); const mapStateToProps = (state: GlobalChartState): TooltipStateProps => { - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return HIDDEN_TOOLTIP_PROPS; } return { diff --git a/src/state/chart_state.ts b/src/state/chart_state.ts index 4024e2f402..d66c0dc1ce 100644 --- a/src/state/chart_state.ts +++ b/src/state/chart_state.ts @@ -38,7 +38,7 @@ import { SET_PERSISTED_COLOR, SET_TEMPORARY_COLOR, CLEAR_TEMPORARY_COLORS } from import { EXTERNAL_POINTER_EVENT } from './actions/events'; import { SPEC_PARSED, SPEC_UNMOUNTED, UPSERT_SPEC, REMOVE_SPEC, SPEC_PARSING } from './actions/specs'; import { interactionsReducer } from './reducers/interactions'; -import { getInternalIsInitializedSelector } from './selectors/get_internal_is_intialized'; +import { getInternalIsInitializedSelector, InitStatus } from './selectors/get_internal_is_intialized'; import { getLegendItemsSelector } from './selectors/get_legend_items'; import { LegendItemLabel } from './selectors/get_legend_items_labels'; @@ -53,7 +53,7 @@ export interface InternalChartState { * The chart type */ chartType: ChartTypes; - isInitialized(globalState: GlobalChartState): boolean; + isInitialized(globalState: GlobalChartState): InitStatus; /** * Returns a JSX element with the chart rendered (lenged excluded) * @param containerRef @@ -379,7 +379,7 @@ export const chartStoreReducer = (chartId: string) => { }, }; default: - if (!getInternalIsInitializedSelector(state)) { + if (getInternalIsInitializedSelector(state) !== InitStatus.Initialized) { return state; } return { diff --git a/src/state/selectors/get_internal_is_intialized.ts b/src/state/selectors/get_internal_is_intialized.ts index 1fab85da6e..45055b5d9f 100644 --- a/src/state/selectors/get_internal_is_intialized.ts +++ b/src/state/selectors/get_internal_is_intialized.ts @@ -17,20 +17,40 @@ * under the License. */ +import { $Values } from 'utility-types'; + import { GlobalChartState } from '../chart_state'; + +export const InitStatus = Object.freeze({ + ParentSizeInvalid: 'ParentSizeInvalid' as const, + SpecNotInitialized: 'SpecNotInitialized' as const, + MissingChartType: 'MissingChartType' as const, + ChartNotInitialized: 'ChartNotInitialized' as const, + Initialized: 'Initialized' as const, +}); + +export type InitStatus = $Values; + /** @internal */ -export const getInternalIsInitializedSelector = (state: GlobalChartState): boolean => { +export const getInternalIsInitializedSelector = (state: GlobalChartState): InitStatus => { const { parentDimensions: { width, height }, specsInitialized, + internalChartState, } = state; - if (width <= 0 || height <= 0 || !specsInitialized) { - return false; + if (!specsInitialized) { + return InitStatus.SpecNotInitialized; } - if (state.internalChartState) { - return state.internalChartState.isInitialized(state); + + if (!internalChartState) { + return InitStatus.MissingChartType; + } + + if (width <= 0 || height <= 0) { + return InitStatus.ParentSizeInvalid; } - return false; + + return internalChartState.isInitialized(state); }; diff --git a/yarn.lock b/yarn.lock index 13eea8d14d..1012cc28a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4989,6 +4989,15 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" +"@types/jsdom@^16.2.3": + version "16.2.3" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.3.tgz#c6feadfe0836389b27f9c911cde82cd32e91c537" + integrity sha512-BREatezSn74rmLIDksuqGNFUTi9HNAWWQXYpFBFLK9U6wlMCO4M0QCa8CMpDsZQuqxSO9XifVLT5Q1P0vgKLqw== + dependencies: + "@types/node" "*" + "@types/parse5" "*" + "@types/tough-cookie" "*" + "@types/json-schema@^7.0.3": version "7.0.3" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" @@ -5046,6 +5055,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/parse5@*": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" + integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + "@types/prettier@^1.19.0": version "1.19.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" @@ -5170,6 +5184,11 @@ "@storybook/react" "^5.2.0" "@types/react" "*" +"@types/tough-cookie@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d" + integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== + "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" From 582a58a55a8b9eb7d625277bf09d678cec9e62aa Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 10 Jun 2020 02:32:01 +0200 Subject: [PATCH 6/8] test: fix --- scripts/setup_enzyme.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/setup_enzyme.ts b/scripts/setup_enzyme.ts index 424ac7dab6..916f7291a1 100644 --- a/scripts/setup_enzyme.ts +++ b/scripts/setup_enzyme.ts @@ -24,9 +24,11 @@ configure({ adapter: new Adapter() }); process.env.RNG_SEED = 'jest-unit-tests'; -jest.useFakeTimers(); +/** + * Mocking RAF and ResizeObserver to missing RAF and RO in jsdom + */ -window.requestAnimationFrame = function(callback) { +window.requestAnimationFrame = (callback) => { callback(0); return 0; }; @@ -42,13 +44,9 @@ class ResizeObserverMock { this.callback([{ contentRect: { width: 200, height: 200 } }]); } - unobserve() { - // do nothing - } + unobserve() { } - disconnect() { - // do nothing - } + disconnect() { } } // @ts-ignore From 387fecce918fd04c1fbeb47494f01c85e53ee272 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 10 Jun 2020 02:40:53 +0200 Subject: [PATCH 7/8] test: add missing snapshot --- src/components/__snapshots__/chart.test.tsx.snap | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/components/__snapshots__/chart.test.tsx.snap diff --git a/src/components/__snapshots__/chart.test.tsx.snap b/src/components/__snapshots__/chart.test.tsx.snap new file mode 100644 index 0000000000..7e1ddf2da4 --- /dev/null +++ b/src/components/__snapshots__/chart.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Chart should render the legend name test 1`] = `"
  • test
"`; From d77ba15e6e9ca7cf9112efbc61c580e0407eabf4 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 10 Jun 2020 14:42:16 +0200 Subject: [PATCH 8/8] fix: add chart id to test --- src/components/__snapshots__/chart.test.tsx.snap | 2 +- src/components/chart.test.tsx | 2 +- src/components/chart.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/__snapshots__/chart.test.tsx.snap b/src/components/__snapshots__/chart.test.tsx.snap index 7e1ddf2da4..00df8cd9ad 100644 --- a/src/components/__snapshots__/chart.test.tsx.snap +++ b/src/components/__snapshots__/chart.test.tsx.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Chart should render the legend name test 1`] = `"
  • test
"`; +exports[`Chart should render the legend name test 1`] = `"
  • test
"`; diff --git a/src/components/chart.test.tsx b/src/components/chart.test.tsx index 1f34962836..182e73244d 100644 --- a/src/components/chart.test.tsx +++ b/src/components/chart.test.tsx @@ -50,7 +50,7 @@ describe('Chart', () => { it('should render the legend name test', () => { const wrapper = mount( - + , diff --git a/src/components/chart.tsx b/src/components/chart.tsx index 94fcf7b43b..d144d70ea5 100644 --- a/src/components/chart.tsx +++ b/src/components/chart.tsx @@ -68,7 +68,7 @@ export class Chart extends React.Component { this.chartContainerRef = createRef(); this.chartStageRef = createRef(); - const id = uuid.v4(); + const id = props.id ?? uuid.v4(); const storeReducer = chartStoreReducer(id); const enhancers = typeof window !== 'undefined' && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true, name: `@elastic/charts (id: ${id})` })()