UNPKG

@gooddata/react-components

Version:

GoodData.UI - A powerful JavaScript library for building analytical applications

944 lines (851 loc) • 31 kB
// (C) 2007-2019 GoodData Corporation import { shouldFollowPointer, shouldFollowPointerForDualAxes, shouldStartOnTick, shouldEndOnTick, getChartProperties, pointInRange, getStackedMaxValue, getStackedMinValue, shouldXAxisStartOnTickOnBubbleScatter, shouldYAxisStartOnTickOnBubbleScatter, alignChart, } from "../helpers"; import { VisualizationTypes } from "../../../../../constants/visualizationTypes"; import { ChartAlignTypes, IChartConfig } from "../../../../../interfaces/Config"; import { BOTTOM, TOP } from "../../../../../constants/alignments"; describe("helpers", () => { describe("getChartProperties", () => { const config: IChartConfig = { xaxis: { rotation: "60", visible: false, }, yaxis: { labelsEnabled: true, }, }; it("should return properties from config", () => { expect(getChartProperties(config, VisualizationTypes.COLUMN)).toEqual({ xAxisProps: { rotation: "60", visible: false }, yAxisProps: { labelsEnabled: true }, }); }); it("should return properties from config for bar chart with switched axes", () => { expect(getChartProperties(config, VisualizationTypes.BAR)).toEqual({ yAxisProps: { rotation: "60", visible: false }, xAxisProps: { labelsEnabled: true }, }); }); }); describe("shouldStartOnTick, shouldEndOnTick", () => { const nonStackedChartOptions = { hasStackByAttribute: false, data: { series: [ { data: [{ y: 20 }], visible: true, }, ], }, }; const stackedChartOptions = { hasStackByAttribute: true, data: { series: [ { data: [{ y: 20 }, { y: 10 }, { y: 5 }], visible: true, }, ], }, }; describe("shouldStartOnTick", () => { it("should return false when min and max are set", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "5", max: "10" }, }; expect(shouldStartOnTick(chartOptions)).toBeFalsy(); }); it("should return false when min is greater than max", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "10", max: "5" }, }; expect(shouldStartOnTick(chartOptions)).toBeTruthy(); }); it("should return false if max is set but greater than min data value (non stacked)", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { max: "40" }, }; expect(shouldStartOnTick(chartOptions)).toBeFalsy(); }); it("should return false if max is set but greater than min data value (stacked)", () => { const chartOptions = { ...stackedChartOptions, yAxisProps: { max: "40" }, }; expect(shouldStartOnTick(chartOptions)).toBeFalsy(); }); it("should return true when no max or min are set", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: {}, }; expect(shouldStartOnTick(chartOptions)).toBeTruthy(); }); it("should return true if max is set but smaller than min data value (non stacked)", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { max: "-40" }, }; expect(shouldStartOnTick(chartOptions)).toBeTruthy(); }); it("should return true if max is set but smaller than min data value (stacked)", () => { const chartOptions = { ...stackedChartOptions, yAxisProps: { max: "-40" }, }; expect(shouldStartOnTick(chartOptions)).toBeTruthy(); }); }); describe("shouldEndOnTick", () => { it("should return false when min and max are set", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "5", max: "10" }, }; expect(shouldEndOnTick(chartOptions)).toBeFalsy(); }); it("should return false when min is greater than max", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "10", max: "5" }, }; expect(shouldEndOnTick(chartOptions)).toBeTruthy(); }); it("should return false if min is set but smaller than max data value (non stacked)", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "1" }, }; expect(shouldEndOnTick(chartOptions)).toBeFalsy(); }); it("should return false if min is set but smaller than max data value (stacked)", () => { const chartOptions = { ...stackedChartOptions, yAxisProps: { min: "1" }, }; expect(shouldEndOnTick(chartOptions)).toBeFalsy(); }); it("should return true when no max or min are set", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: {}, }; expect(shouldEndOnTick(chartOptions)).toBeTruthy(); }); it("should return true if min is set but bigger than max data value (non stacked)", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "40" }, }; expect(shouldEndOnTick(chartOptions)).toBeTruthy(); }); it("should return true if min is set but bigger than max data value (stacked)", () => { const chartOptions = { ...stackedChartOptions, yAxisProps: { min: "40" }, }; expect(shouldEndOnTick(chartOptions)).toBeTruthy(); }); }); describe("shouldXAxisStartOnTickOnBubbleScatter", () => { it("should return true when min is not set", () => { const chartOptions = { ...nonStackedChartOptions, }; expect(shouldXAxisStartOnTickOnBubbleScatter(chartOptions)).toBeTruthy(); }); it("should return false when min is set", () => { const chartOptions = { ...nonStackedChartOptions, xAxisProps: { min: "40" }, }; expect(shouldXAxisStartOnTickOnBubbleScatter(chartOptions)).toBeFalsy(); }); }); describe("shouldYAxisStartOnTickOnBubbleScatter", () => { it("should return true when min is not set", () => { const chartOptions = { ...nonStackedChartOptions, }; expect(shouldYAxisStartOnTickOnBubbleScatter(chartOptions)).toBeTruthy(); }); it("should return false when min is set", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "10" }, }; expect(shouldYAxisStartOnTickOnBubbleScatter(chartOptions)).toBeFalsy(); }); it("should return true if min is set but bigger than max data value (non stacked)", () => { const chartOptions = { ...nonStackedChartOptions, yAxisProps: { min: "40" }, }; expect(shouldEndOnTick(chartOptions)).toBeTruthy(); }); }); }); describe("shouldFollowPointer", () => { const nonStackedChartOptions = { type: VisualizationTypes.COLUMN, yAxes: [{ title: "atitle" }], xAxes: [{ title: "xtitle" }], data: { series: [ { color: "rgb(0, 0, 0)", name: "<b>aaa</b>", data: [ { name: "data1", y: 50, }, { name: "data2", y: 150, }, { name: "data3", y: -12, }, ], visible: true, }, ], }, }; const stackedChartOptions = { type: VisualizationTypes.COLUMN, hasStackByAttribute: true, yAxes: [{ title: "atitle" }], xAxes: [{ title: "xtitle" }], data: { series: [ { color: "rgb(0, 0, 0)", name: "<b>aaa</b>", data: [ { name: "data1", y: 25, }, { name: "data2", y: 75, }, { name: "data3", y: -12, }, ], visible: true, }, { color: "rgb(0, 0, 0)", name: "<b>bbb</b>", data: [ { name: "data1", y: 25, }, { name: "data2", y: 75, }, { name: "data3", y: -12, }, ], visible: true, }, ], }, }; const stackedChartOptionsPositiveValues = { data: { series: [ { color: "rgb(20,178,226)", data: [ { y: 27, name: "AAAA", }, ], name: "AAAA", }, { color: "rgb(0,193,141)", data: [ { y: 26, name: "BBBB", }, ], name: "BBBB", }, { color: "rgb(229,77,66)", data: [ { y: 26, name: "CCCC", }, ], name: "CCCC", }, { color: "rgb(241,134,0)", data: [ { y: 29, name: "DDDD", }, ], name: "DDDD", }, ], }, }; const stackedChartOptionsNegativeValues = { data: { series: [ { color: "rgb(20,178,226)", data: [ { y: -27, name: "AAAA", }, ], name: "AAAA", }, { color: "rgb(0,193,141)", data: [ { y: -26, name: "BBBB", }, ], name: "BBBB", }, { color: "rgb(229,77,66)", data: [ { y: -26, name: "CCCC", }, ], name: "CCCC", }, { color: "rgb(241,134,0)", data: [ { y: -29, name: "DDDD", }, ], name: "DDDD", }, ], }, }; describe("Non stacked chart", () => { it("should return false when no extremes are defined", () => { const result = shouldFollowPointer({ ...nonStackedChartOptions, xAxisProps: {}, yAxisProps: {}, }); expect(result).toBeFalsy(); }); it("should return false when data values are in axis range", () => { const result = shouldFollowPointer({ ...nonStackedChartOptions, yAxisProps: { min: "-30", max: "200", }, }); expect(result).toBeFalsy(); }); it("should return true when min is in negative value", () => { const result = shouldFollowPointer({ ...nonStackedChartOptions, yAxisProps: { min: "-10", }, }); expect(result).toBeTruthy(); }); it("should return true when min and max are within data values", () => { const result = shouldFollowPointer({ ...nonStackedChartOptions, yAxisProps: { min: "60", max: "100", }, }); expect(result).toBeTruthy(); }); it("should return true when min is bigger than minimal value", () => { const result = shouldFollowPointer({ ...nonStackedChartOptions, yAxisProps: { min: "0", }, }); expect(result).toBeTruthy(); }); it("should return true when min is bigger than minimal value", () => { const result = shouldFollowPointer({ ...nonStackedChartOptions, yAxisProps: { min: "0", }, }); expect(result).toBeTruthy(); }); }); describe("Stacked chart", () => { it("should return false when no extremes are defined", () => { const result = shouldFollowPointer({ ...stackedChartOptions, xAxisProps: {}, yAxisProps: {}, }); expect(result).toBeFalsy(); }); it("should return false when data values are in axis range", () => { const result = shouldFollowPointer({ ...stackedChartOptions, yAxisProps: { min: "-30", max: "200", }, }); expect(result).toBeFalsy(); }); it("should return true when min and max are within data values", () => { const result = shouldFollowPointer({ ...stackedChartOptions, yAxisProps: { min: "60", max: "100", }, }); expect(result).toBeTruthy(); }); it("should return true when min is bigger 0 and less than min seriesValue", () => { const result = shouldFollowPointer({ ...stackedChartOptionsPositiveValues, yAxisProps: { min: "20", }, }); expect(result).toBeTruthy(); }); it("should return true when max is negative and max less than min seriesValue", () => { const result = shouldFollowPointer({ ...stackedChartOptionsNegativeValues, yAxisProps: { max: "-20", }, }); expect(result).toBeTruthy(); }); }); }); describe("shouldFollowPointerForAxes", () => { const dualAxesChartOptions = { type: VisualizationTypes.COLUMN, yAxes: [{ title: "atitle" }, { title: "btitle" }], xAxes: [{ title: "xtitle" }], data: { series: [ { color: "rgb(0, 0, 0)", name: "aaa", data: [ { name: "data1", y: 25, }, { name: "data2", y: 75, }, { name: "data3", y: -12, }, ], visible: true, }, { color: "rgb(0, 0, 0)", name: "bbb", data: [ { name: "data1", y: 25, }, { name: "data2", y: 75, }, { name: "data3", y: -12, }, ], yAxis: 1, visible: true, }, ], }, }; it("should return false when there is one Y axis", () => { const chartOptions = { ...dualAxesChartOptions, yAxes: [{ title: "atitle" }], }; const result = shouldFollowPointerForDualAxes(chartOptions); expect(result).toBeFalsy(); }); it("should return false when min/max is not set", () => { const result = shouldFollowPointerForDualAxes(dualAxesChartOptions); expect(result).toBeFalsy(); }); it("should return true when min/max is set in left Y axis", () => { const chartOptions = { ...dualAxesChartOptions, yAxisProps: { min: "10", max: "20", }, }; const result = shouldFollowPointerForDualAxes(chartOptions); expect(result).toBeTruthy(); }); it("should return true when min/max is set in right Y axis", () => { const chartOptions = { ...dualAxesChartOptions, secondary_yAxisProps: { min: "10", max: "20", }, }; const result = shouldFollowPointerForDualAxes(chartOptions); expect(result).toBeTruthy(); }); it("should return true when min/max is set in both Y axes", () => { const chartOptions = { ...dualAxesChartOptions, yAxisProps: { min: "10", max: "20", }, secondary_yAxisProps: { min: "10", max: "20", }, }; const result = shouldFollowPointerForDualAxes(chartOptions); expect(result).toBeTruthy(); }); }); describe("pointInRange", () => { it("should return true when data point is in the axis range", () => { expect( pointInRange(5, { minAxisValue: 2, maxAxisValue: 8, }), ).toBeTruthy(); }); it("should return true when data point is on the left edge of axis range", () => { expect( pointInRange(5, { minAxisValue: 5, maxAxisValue: 8, }), ).toBeTruthy(); }); it("should return true when data point is on the right edge of axis range", () => { expect( pointInRange(5, { minAxisValue: 2, maxAxisValue: 5, }), ).toBeTruthy(); }); it("should return false when data point is outside of axis range", () => { expect( pointInRange(5, { minAxisValue: -5, maxAxisValue: 2, }), ).toBeFalsy(); }); }); describe("getStackedExtremeValues", () => { const seriesNegativeAndPositiveValues = [ { color: "rgb(0, 0, 0)", name: "<b>aaa</b>", data: [ { name: "data1", y: 25, }, { name: "data2", y: 75, }, { name: "data3", y: 30, }, ], visible: true, }, { color: "rgb(0, 0, 0)", name: "<b>bbb</b>", data: [ { name: "data1", y: -25, }, { name: "data2", y: -75, }, { name: "data3", y: -30, }, ], visible: true, }, { color: "rgb(0, 0, 0)", name: "<b>bbb</b>", data: [ { name: "data1", y: 15, }, { name: "data2", y: 60, }, { name: "data3", y: 20, }, ], visible: true, }, { color: "rgb(0, 0, 0)", name: "<b>bbb</b>", data: [ { name: "data1", y: -15, }, { name: "data2", y: -60, }, { name: "data3", y: -20, }, ], visible: true, }, ]; const negativeValues = [ { color: "rgb(0, 0, 0)", name: "<b>bbb</b>", data: [ { name: "data1", y: -25, }, { name: "data2", y: -75, }, { name: "data3", y: -30, }, ], visible: true, }, { color: "rgb(0, 0, 0)", name: "<b>bbb</b>", data: [ { name: "data1", y: -15, }, { name: "data2", y: -60, }, { name: "data3", y: -20, }, ], visible: true, }, ]; describe("getStackedMaxValue", () => { it("should match output for negative and positive values", () => { const result = getStackedMaxValue(seriesNegativeAndPositiveValues); expect(result).toEqual(135); }); it("should match output for negative values", () => { const result = getStackedMaxValue(negativeValues); expect(result).toEqual(-15); }); }); describe("getStackedMinValue", () => { it("should match output for negative and positive values", () => { const result = getStackedMinValue(seriesNegativeAndPositiveValues); expect(result).toEqual(-135); }); it("should match output for negative values", () => { const result = getStackedMinValue(negativeValues); expect(result).toEqual(-135); }); }); }); describe("getChartAlignmentConfiguration", () => { function getCommonChartOptionsMock(width: number, height: number) { const getBoundingClientRect = jest.fn().mockReturnValue({ width, height }); return { options: { chart: { type: VisualizationTypes.DONUT, }, }, container: { getBoundingClientRect, }, update: jest.fn(), }; } it.each([[TOP, 0, undefined, undefined, 100], [BOTTOM, undefined, 0, 100, undefined]])( "should update chart margin %s", ( verticalAlign: ChartAlignTypes, spacingTop: number, spacingBottom: number, marginTop: number, marginBottom: number, ) => { const chart: any = { ...getCommonChartOptionsMock(200, 300), userOptions: { chart: { verticalAlign, }, }, }; alignChart(chart); expect(chart.update).toBeCalledWith( { chart: { spacingTop, spacingBottom, marginTop, marginBottom, className: `s-highcharts-donut-aligned-to-${verticalAlign}`, }, }, false, false, false, ); }, ); it("should not update when rectangle container is horizontal", () => { const chart: any = { ...getCommonChartOptionsMock(300, 200), }; alignChart(chart); expect(chart.update).toBeCalledWith( { chart: { spacingTop: undefined, spacingBottom: undefined, marginTop: undefined, marginBottom: undefined, className: "s-highcharts-donut-aligned-to-middle", }, }, false, false, false, ); }); it.each([["middle"], [undefined]])( "should not update when verticalAlign is %s", (verticalAlign: ChartAlignTypes) => { const chart: any = { ...getCommonChartOptionsMock(200, 300), userOptions: { chart: { verticalAlign, }, }, }; alignChart(chart); expect(chart.update).toBeCalledWith( { chart: { spacingTop: undefined, spacingBottom: undefined, marginTop: undefined, marginBottom: undefined, className: "s-highcharts-donut-aligned-to-middle", }, }, false, false, false, ); }, ); }); });