| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| import { SortSeriesType } from '@superset-ui/chart-controls'; |
| import { |
| AxisType, |
| DataRecord, |
| getNumberFormatter, |
| getTimeFormatter, |
| supersetTheme as theme, |
| } from '@superset-ui/core'; |
| import { GenericDataType } from '@apache-superset/core/api/core'; |
| import { |
| calculateLowerLogTick, |
| dedupSeries, |
| extractGroupbyLabel, |
| extractSeries, |
| extractShowValueIndexes, |
| extractTooltipKeys, |
| formatSeriesName, |
| getAxisType, |
| getChartPadding, |
| getLegendProps, |
| getOverMaxHiddenFormatter, |
| getMinAndMaxFromBounds, |
| sanitizeHtml, |
| sortAndFilterSeries, |
| sortRows, |
| getTimeCompareStackId, |
| } from '../../src/utils/series'; |
| import { |
| EchartsTimeseriesSeriesType, |
| LegendOrientation, |
| LegendType, |
| } from '../../src/types'; |
| import { defaultLegendPadding } from '../../src/defaults'; |
| import { NULL_STRING } from '../../src/constants'; |
| |
| const expectedThemeProps = { |
| selector: ['all', 'inverse'], |
| selected: undefined, |
| selectorLabel: { |
| fontFamily: theme.fontFamily, |
| fontSize: theme.fontSizeSM, |
| color: theme.colorText, |
| borderColor: theme.colorBorder, |
| }, |
| }; |
| |
| const sortData: DataRecord[] = [ |
| { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, |
| { my_x_axis: 'foo', x: null, y: 10, z: 5 }, |
| { my_x_axis: null, x: 4, y: 3, z: 7 }, |
| ]; |
| |
| const sortDataWithNumbers: DataRecord[] = [ |
| { |
| my_x_axis: 'my_axis', |
| '9. September': 6, |
| 6: 1, |
| '11. November': 8, |
| 8: 2, |
| '10. October': 1, |
| 10: 4, |
| '3. March': 2, |
| '8. August': 6, |
| 2: 1, |
| 12: 3, |
| 9: 1, |
| '1. January': 1, |
| '4. April': 12, |
| '2. February': 9, |
| 5: 4, |
| 3: 1, |
| 11: 2, |
| '12. December': 4, |
| 1: 7, |
| '6. June': 1, |
| 4: 5, |
| 7: 2, |
| c: 0, |
| '7. July': 2, |
| d: 0, |
| '5. May': 4, |
| a: 1, |
| }, |
| ]; |
| |
| const totalStackedValues = [3, 15, 14]; |
| |
| test('sortRows by name ascending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Name, |
| true, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| ]); |
| }); |
| |
| test('sortRows by name descending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Name, |
| false, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| ]); |
| }); |
| |
| test('sortRows by sum ascending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Sum, |
| true, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| ]); |
| }); |
| |
| test('sortRows by sum descending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Sum, |
| false, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| ]); |
| }); |
| |
| test('sortRows by avg ascending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Avg, |
| true, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| ]); |
| }); |
| |
| test('sortRows by avg descending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Avg, |
| false, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| ]); |
| }); |
| |
| test('sortRows by min ascending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Min, |
| true, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| ]); |
| }); |
| |
| test('sortRows by min descending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Min, |
| false, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| ]); |
| }); |
| |
| test('sortRows by max ascending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Min, |
| true, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| ]); |
| }); |
| |
| test('sortRows by max descending', () => { |
| expect( |
| sortRows( |
| sortData, |
| totalStackedValues, |
| 'my_x_axis', |
| SortSeriesType.Min, |
| false, |
| ), |
| ).toEqual([ |
| { row: { my_x_axis: 'foo', x: null, y: 10, z: 5 }, totalStackedValue: 15 }, |
| { row: { my_x_axis: null, x: 4, y: 3, z: 7 }, totalStackedValue: 14 }, |
| { row: { my_x_axis: 'abc', x: 1, y: 0, z: 2 }, totalStackedValue: 3 }, |
| ]); |
| }); |
| |
| test('sortAndFilterSeries by min ascending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Min, true), |
| ).toEqual(['y', 'x', 'z']); |
| }); |
| |
| test('sortAndFilterSeries by min descending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Min, false), |
| ).toEqual(['z', 'x', 'y']); |
| }); |
| |
| test('sortAndFilterSeries by max ascending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Max, true), |
| ).toEqual(['x', 'z', 'y']); |
| }); |
| |
| test('sortAndFilterSeries by max descending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Max, false), |
| ).toEqual(['y', 'z', 'x']); |
| }); |
| |
| test('sortAndFilterSeries by avg ascending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Avg, true), |
| ).toEqual(['x', 'y', 'z']); |
| }); |
| |
| test('sortAndFilterSeries by avg descending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Avg, false), |
| ).toEqual(['z', 'y', 'x']); |
| }); |
| |
| test('sortAndFilterSeries by sum ascending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Sum, true), |
| ).toEqual(['x', 'y', 'z']); |
| }); |
| |
| test('sortAndFilterSeries by sum descending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Sum, false), |
| ).toEqual(['z', 'y', 'x']); |
| }); |
| |
| test('sortAndFilterSeries by name ascending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, true), |
| ).toEqual(['x', 'y', 'z']); |
| }); |
| |
| test('sortAndFilterSeries by name descending', () => { |
| expect( |
| sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, false), |
| ).toEqual(['z', 'y', 'x']); |
| }); |
| test('sortAndFilterSeries by name with numbers asc', () => { |
| expect( |
| sortAndFilterSeries( |
| sortDataWithNumbers, |
| 'my_x_axis', |
| [], |
| SortSeriesType.Name, |
| true, |
| ), |
| ).toEqual([ |
| '1', |
| '1. January', |
| '2', |
| '2. February', |
| '3', |
| '3. March', |
| '4', |
| '4. April', |
| '5', |
| '5. May', |
| '6', |
| '6. June', |
| '7', |
| '7. July', |
| '8', |
| '8. August', |
| '9', |
| '9. September', |
| '10', |
| '10. October', |
| '11', |
| '11. November', |
| '12', |
| '12. December', |
| 'a', |
| 'c', |
| 'd', |
| ]); |
| }); |
| test('sortAndFilterSeries by name with numbers desc', () => { |
| expect( |
| sortAndFilterSeries( |
| sortDataWithNumbers, |
| 'my_x_axis', |
| [], |
| SortSeriesType.Name, |
| false, |
| ), |
| ).toEqual([ |
| 'd', |
| 'c', |
| 'a', |
| '12. December', |
| '12', |
| '11. November', |
| '11', |
| '10. October', |
| '10', |
| '9. September', |
| '9', |
| '8. August', |
| '8', |
| '7. July', |
| '7', |
| '6. June', |
| '6', |
| '5. May', |
| '5', |
| '4. April', |
| '4', |
| '3. March', |
| '3', |
| '2. February', |
| '2', |
| '1. January', |
| '1', |
| ]); |
| }); |
| |
| describe('extractSeries', () => { |
| it('should generate a valid ECharts timeseries series object', () => { |
| const data = [ |
| { |
| __timestamp: '2000-01-01', |
| Hulk: null, |
| abc: 2, |
| }, |
| { |
| __timestamp: '2000-02-01', |
| Hulk: 2, |
| abc: 10, |
| }, |
| { |
| __timestamp: '2000-03-01', |
| Hulk: 1, |
| abc: 5, |
| }, |
| ]; |
| const totalStackedValues = [2, 12, 6]; |
| expect(extractSeries(data, { totalStackedValues })).toEqual([ |
| [ |
| { |
| id: 'Hulk', |
| name: 'Hulk', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 2], |
| ['2000-03-01', 1], |
| ], |
| }, |
| { |
| id: 'abc', |
| name: 'abc', |
| data: [ |
| ['2000-01-01', 2], |
| ['2000-02-01', 10], |
| ['2000-03-01', 5], |
| ], |
| }, |
| ], |
| totalStackedValues, |
| 1, |
| ]); |
| }); |
| |
| it('should remove rows that have a null x-value', () => { |
| const data = [ |
| { |
| x: 1, |
| Hulk: null, |
| abc: 2, |
| }, |
| { |
| x: null, |
| Hulk: 2, |
| abc: 10, |
| }, |
| { |
| x: 2, |
| Hulk: 1, |
| abc: 5, |
| }, |
| ]; |
| const totalStackedValues = [3, 12, 8]; |
| expect( |
| extractSeries(data, { |
| totalStackedValues, |
| xAxis: 'x', |
| removeNulls: true, |
| }), |
| ).toEqual([ |
| [ |
| { |
| id: 'Hulk', |
| name: 'Hulk', |
| data: [[2, 1]], |
| }, |
| { |
| id: 'abc', |
| name: 'abc', |
| data: [ |
| [1, 2], |
| [2, 5], |
| ], |
| }, |
| ], |
| totalStackedValues, |
| 1, |
| ]); |
| }); |
| |
| it('should convert NULL x-values to NULL_STRING for categorical axis', () => { |
| const data = [ |
| { |
| browser: 'Firefox', |
| count: 5, |
| }, |
| { |
| browser: null, |
| count: 10, |
| }, |
| { |
| browser: 'Chrome', |
| count: 8, |
| }, |
| ]; |
| expect( |
| extractSeries(data, { |
| xAxis: 'browser', |
| xAxisType: AxisType.Category, |
| }), |
| ).toEqual([ |
| [ |
| { |
| id: 'count', |
| name: 'count', |
| data: [ |
| ['Firefox', 5], |
| [NULL_STRING, 10], |
| ['Chrome', 8], |
| ], |
| }, |
| ], |
| [], |
| 5, |
| ]); |
| }); |
| |
| it('should do missing value imputation', () => { |
| const data = [ |
| { |
| __timestamp: '2000-01-01', |
| abc: null, |
| }, |
| { |
| __timestamp: '2000-02-01', |
| abc: null, |
| }, |
| { |
| __timestamp: '2000-03-01', |
| abc: 1, |
| }, |
| { |
| __timestamp: '2000-04-01', |
| abc: null, |
| }, |
| { |
| __timestamp: '2000-05-01', |
| abc: null, |
| }, |
| { |
| __timestamp: '2000-06-01', |
| abc: null, |
| }, |
| { |
| __timestamp: '2000-07-01', |
| abc: 2, |
| }, |
| { |
| __timestamp: '2000-08-01', |
| abc: 3, |
| }, |
| { |
| __timestamp: '2000-09-01', |
| abc: null, |
| }, |
| { |
| __timestamp: '2000-10-01', |
| abc: null, |
| }, |
| ]; |
| const totalStackedValues = [0, 0, 1, 0, 0, 0, 2, 3, 0, 0]; |
| expect( |
| extractSeries(data, { totalStackedValues, fillNeighborValue: 0 }), |
| ).toEqual([ |
| [ |
| { |
| id: 'abc', |
| name: 'abc', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 0], |
| ['2000-03-01', 1], |
| ['2000-04-01', 0], |
| ['2000-05-01', null], |
| ['2000-06-01', 0], |
| ['2000-07-01', 2], |
| ['2000-08-01', 3], |
| ['2000-09-01', 0], |
| ['2000-10-01', null], |
| ], |
| }, |
| ], |
| totalStackedValues, |
| 1, |
| ]); |
| }); |
| }); |
| |
| describe('extractGroupbyLabel', () => { |
| it('should join together multiple groupby labels', () => { |
| expect( |
| extractGroupbyLabel({ |
| datum: { a: 'abc', b: 'qwerty' }, |
| groupby: ['a', 'b'], |
| }), |
| ).toEqual('abc, qwerty'); |
| }); |
| |
| it('should handle a single groupby', () => { |
| expect( |
| extractGroupbyLabel({ datum: { xyz: 'qqq' }, groupby: ['xyz'] }), |
| ).toEqual('qqq'); |
| }); |
| |
| it('should handle mixed types', () => { |
| expect( |
| extractGroupbyLabel({ |
| datum: { strcol: 'abc', intcol: 123, floatcol: 0.123, boolcol: true }, |
| groupby: ['strcol', 'intcol', 'floatcol', 'boolcol'], |
| }), |
| ).toEqual('abc, 123, 0.123, true'); |
| }); |
| |
| it('should handle null and undefined groupby', () => { |
| expect( |
| extractGroupbyLabel({ |
| datum: { strcol: 'abc', intcol: 123, floatcol: 0.123, boolcol: true }, |
| groupby: null, |
| }), |
| ).toEqual(''); |
| expect(extractGroupbyLabel({})).toEqual(''); |
| }); |
| }); |
| |
| describe('extractShowValueIndexes', () => { |
| it('should return the latest index for stack', () => { |
| expect( |
| extractShowValueIndexes( |
| [ |
| { |
| id: 'abc', |
| name: 'abc', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 0], |
| ['2000-03-01', 1], |
| ['2000-04-01', 0], |
| ['2000-05-01', null], |
| ['2000-06-01', 0], |
| ['2000-07-01', 2], |
| ['2000-08-01', 3], |
| ['2000-09-01', null], |
| ['2000-10-01', null], |
| ], |
| }, |
| { |
| id: 'def', |
| name: 'def', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 0], |
| ['2000-03-01', null], |
| ['2000-04-01', 0], |
| ['2000-05-01', null], |
| ['2000-06-01', 0], |
| ['2000-07-01', 2], |
| ['2000-08-01', 3], |
| ['2000-09-01', null], |
| ['2000-10-01', 0], |
| ], |
| }, |
| { |
| id: 'def', |
| name: 'def', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', null], |
| ['2000-03-01', null], |
| ['2000-04-01', null], |
| ['2000-05-01', null], |
| ['2000-06-01', 3], |
| ['2000-07-01', null], |
| ['2000-08-01', null], |
| ['2000-09-01', null], |
| ['2000-10-01', null], |
| ], |
| }, |
| ], |
| { stack: true, onlyTotal: false, isHorizontal: false }, |
| ), |
| ).toEqual([undefined, 1, 0, 1, undefined, 2, 1, 1, undefined, 1]); |
| }); |
| |
| it('should handle the negative numbers for total only', () => { |
| expect( |
| extractShowValueIndexes( |
| [ |
| { |
| id: 'abc', |
| name: 'abc', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 0], |
| ['2000-03-01', -1], |
| ['2000-04-01', 0], |
| ['2000-05-01', null], |
| ['2000-06-01', 0], |
| ['2000-07-01', -2], |
| ['2000-08-01', -3], |
| ['2000-09-01', null], |
| ['2000-10-01', null], |
| ], |
| }, |
| { |
| id: 'def', |
| name: 'def', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 0], |
| ['2000-03-01', null], |
| ['2000-04-01', 0], |
| ['2000-05-01', null], |
| ['2000-06-01', 0], |
| ['2000-07-01', 2], |
| ['2000-08-01', -3], |
| ['2000-09-01', null], |
| ['2000-10-01', 0], |
| ], |
| }, |
| { |
| id: 'def', |
| name: 'def', |
| data: [ |
| ['2000-01-01', null], |
| ['2000-02-01', 0], |
| ['2000-03-01', null], |
| ['2000-04-01', 1], |
| ['2000-05-01', null], |
| ['2000-06-01', 0], |
| ['2000-07-01', -2], |
| ['2000-08-01', 3], |
| ['2000-09-01', null], |
| ['2000-10-01', 0], |
| ], |
| }, |
| ], |
| { stack: true, onlyTotal: true, isHorizontal: false }, |
| ), |
| ).toEqual([undefined, 1, 0, 2, undefined, 1, 1, 2, undefined, 1]); |
| }); |
| }); |
| |
| describe('formatSeriesName', () => { |
| const numberFormatter = getNumberFormatter(); |
| const timeFormatter = getTimeFormatter(); |
| it('should handle missing values properly', () => { |
| expect(formatSeriesName(undefined)).toEqual('<NULL>'); |
| expect(formatSeriesName(null)).toEqual('<NULL>'); |
| }); |
| |
| it('should handle string values properly', () => { |
| expect(formatSeriesName('abc XYZ!')).toEqual('abc XYZ!'); |
| }); |
| |
| it('should handle boolean values properly', () => { |
| expect(formatSeriesName(true)).toEqual('true'); |
| }); |
| |
| it('should use default formatting for numeric values without formatter', () => { |
| expect(formatSeriesName(12345678.9)).toEqual('12345678.9'); |
| }); |
| |
| it('should use numberFormatter for numeric values when formatter is provided', () => { |
| expect(formatSeriesName(12345678.9, { numberFormatter })).toEqual('12.3M'); |
| }); |
| |
| it('should use default formatting for date values without formatter', () => { |
| expect(formatSeriesName(new Date('2020-09-11'))).toEqual( |
| '2020-09-11T00:00:00.000Z', |
| ); |
| }); |
| |
| it('should use timeFormatter for date values when formatter is provided', () => { |
| expect(formatSeriesName(new Date('2020-09-11'), { timeFormatter })).toEqual( |
| '2020-09-11 00:00:00', |
| ); |
| }); |
| |
| it('should normalize non-UTC string based timestamp', () => { |
| const annualTimeFormatter = getTimeFormatter('%Y'); |
| expect( |
| formatSeriesName('1995-01-01 00:00:00.000000', { |
| timeFormatter: annualTimeFormatter, |
| coltype: GenericDataType.Temporal, |
| }), |
| ).toEqual('1995'); |
| }); |
| }); |
| |
| describe('getLegendProps', () => { |
| it('should return the correct props for scroll type with top orientation without zoom', () => { |
| expect( |
| getLegendProps( |
| LegendType.Scroll, |
| LegendOrientation.Top, |
| true, |
| theme, |
| false, |
| ), |
| ).toEqual({ |
| show: true, |
| top: 0, |
| right: 0, |
| orient: 'horizontal', |
| type: 'scroll', |
| ...expectedThemeProps, |
| }); |
| }); |
| |
| it('should return the correct props for scroll type with top orientation with zoom', () => { |
| expect( |
| getLegendProps( |
| LegendType.Scroll, |
| LegendOrientation.Top, |
| true, |
| theme, |
| true, |
| ), |
| ).toEqual({ |
| show: true, |
| top: 0, |
| right: 55, |
| orient: 'horizontal', |
| type: 'scroll', |
| ...expectedThemeProps, |
| }); |
| }); |
| |
| it('should return the correct props for plain type with left orientation', () => { |
| expect( |
| getLegendProps(LegendType.Plain, LegendOrientation.Left, true, theme), |
| ).toEqual({ |
| show: true, |
| left: 0, |
| orient: 'vertical', |
| type: 'plain', |
| ...expectedThemeProps, |
| }); |
| }); |
| |
| it('should return the correct props for plain type with right orientation without zoom', () => { |
| expect( |
| getLegendProps( |
| LegendType.Plain, |
| LegendOrientation.Right, |
| false, |
| theme, |
| false, |
| ), |
| ).toEqual({ |
| show: false, |
| right: 0, |
| top: 0, |
| orient: 'vertical', |
| type: 'plain', |
| ...expectedThemeProps, |
| }); |
| }); |
| |
| it('should return the correct props for plain type with right orientation with zoom', () => { |
| expect( |
| getLegendProps( |
| LegendType.Plain, |
| LegendOrientation.Right, |
| false, |
| theme, |
| true, |
| ), |
| ).toEqual({ |
| show: false, |
| right: 0, |
| top: 30, |
| orient: 'vertical', |
| type: 'plain', |
| ...expectedThemeProps, |
| }); |
| }); |
| |
| it('should return the correct props for plain type with bottom orientation', () => { |
| expect( |
| getLegendProps(LegendType.Plain, LegendOrientation.Bottom, false, theme), |
| ).toEqual({ |
| show: false, |
| bottom: 0, |
| orient: 'horizontal', |
| type: 'plain', |
| ...expectedThemeProps, |
| }); |
| }); |
| }); |
| |
| describe('getChartPadding', () => { |
| it('should handle top default', () => { |
| expect(getChartPadding(true, LegendOrientation.Top)).toEqual({ |
| bottom: 0, |
| left: 0, |
| right: 0, |
| top: defaultLegendPadding[LegendOrientation.Top], |
| }); |
| }); |
| |
| it('should handle left default', () => { |
| expect(getChartPadding(true, LegendOrientation.Left)).toEqual({ |
| bottom: 0, |
| left: defaultLegendPadding[LegendOrientation.Left], |
| right: 0, |
| top: 0, |
| }); |
| }); |
| |
| it('should return the default padding when show is false', () => { |
| expect( |
| getChartPadding(false, LegendOrientation.Left, 100, { |
| top: 10, |
| bottom: 20, |
| left: 30, |
| right: 40, |
| }), |
| ).toEqual({ |
| bottom: 20, |
| left: 30, |
| right: 40, |
| top: 10, |
| }); |
| }); |
| |
| it('should return the correct padding for left orientation', () => { |
| expect(getChartPadding(true, LegendOrientation.Left, 100)).toEqual({ |
| bottom: 0, |
| left: 100, |
| right: 0, |
| top: 0, |
| }); |
| expect( |
| getChartPadding(true, LegendOrientation.Left, 100, undefined, true), |
| ).toEqual({ |
| bottom: 100, |
| left: 0, |
| right: 0, |
| top: 0, |
| }); |
| }); |
| |
| it('should return the correct padding for right orientation', () => { |
| expect(getChartPadding(true, LegendOrientation.Right, 50)).toEqual({ |
| bottom: 0, |
| left: 0, |
| right: 50, |
| top: 0, |
| }); |
| expect( |
| getChartPadding(true, LegendOrientation.Right, 50, undefined, true), |
| ).toEqual({ |
| bottom: 0, |
| left: 0, |
| right: 50, |
| top: 0, |
| }); |
| }); |
| |
| it('should return the correct padding for top orientation', () => { |
| expect(getChartPadding(true, LegendOrientation.Top, 20)).toEqual({ |
| bottom: 0, |
| left: 0, |
| right: 0, |
| top: 20, |
| }); |
| expect( |
| getChartPadding(true, LegendOrientation.Top, 20, undefined, true), |
| ).toEqual({ |
| bottom: 0, |
| left: 0, |
| right: 0, |
| top: 20, |
| }); |
| }); |
| |
| it('should return the correct padding for bottom orientation', () => { |
| expect(getChartPadding(true, LegendOrientation.Bottom, 10)).toEqual({ |
| bottom: 10, |
| left: 0, |
| right: 0, |
| top: 0, |
| }); |
| expect( |
| getChartPadding(true, LegendOrientation.Bottom, 10, undefined, true), |
| ).toEqual({ |
| bottom: 0, |
| left: 10, |
| right: 0, |
| top: 0, |
| }); |
| }); |
| }); |
| |
| describe('dedupSeries', () => { |
| it('should deduplicate ids in series', () => { |
| expect( |
| dedupSeries([ |
| { |
| id: 'foo', |
| }, |
| { |
| id: 'bar', |
| }, |
| { |
| id: 'foo', |
| }, |
| { |
| id: 'foo', |
| }, |
| ]), |
| ).toEqual([ |
| { id: 'foo' }, |
| { id: 'bar' }, |
| { id: 'foo (1)' }, |
| { id: 'foo (2)' }, |
| ]); |
| }); |
| }); |
| |
| describe('sanitizeHtml', () => { |
| it('should remove html tags from series name', () => { |
| expect(sanitizeHtml(NULL_STRING)).toEqual('<NULL>'); |
| }); |
| }); |
| |
| describe('getOverMaxHiddenFormatter', () => { |
| it('should hide value if greater than max', () => { |
| const formatter = getOverMaxHiddenFormatter({ max: 81000 }); |
| expect(formatter.format(84500)).toEqual(''); |
| }); |
| it('should show value if less or equal than max', () => { |
| const formatter = getOverMaxHiddenFormatter({ max: 81000 }); |
| expect(formatter.format(81000)).toEqual('81000'); |
| expect(formatter.format(50000)).toEqual('50000'); |
| }); |
| }); |
| |
| test('calculateLowerLogTick', () => { |
| expect(calculateLowerLogTick(1000000)).toEqual(1000000); |
| expect(calculateLowerLogTick(456)).toEqual(100); |
| expect(calculateLowerLogTick(100)).toEqual(100); |
| expect(calculateLowerLogTick(99)).toEqual(10); |
| expect(calculateLowerLogTick(2)).toEqual(1); |
| expect(calculateLowerLogTick(0.005)).toEqual(0.001); |
| }); |
| |
| test('getAxisType without forced categorical', () => { |
| expect(getAxisType(false, false, GenericDataType.Temporal)).toEqual( |
| AxisType.Time, |
| ); |
| expect(getAxisType(false, false, GenericDataType.Numeric)).toEqual( |
| AxisType.Value, |
| ); |
| expect(getAxisType(true, false, GenericDataType.Numeric)).toEqual( |
| AxisType.Category, |
| ); |
| expect(getAxisType(false, false, GenericDataType.Boolean)).toEqual( |
| AxisType.Category, |
| ); |
| expect(getAxisType(false, false, GenericDataType.String)).toEqual( |
| AxisType.Category, |
| ); |
| }); |
| |
| test('getAxisType with forced categorical', () => { |
| expect(getAxisType(false, true, GenericDataType.Numeric)).toEqual( |
| AxisType.Category, |
| ); |
| }); |
| |
| test('getMinAndMaxFromBounds returns empty object when not truncating', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Value, |
| false, |
| 10, |
| 100, |
| EchartsTimeseriesSeriesType.Bar, |
| ), |
| ).toEqual({}); |
| }); |
| |
| test('getMinAndMaxFromBounds returns empty object for categorical axis', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Category, |
| false, |
| 10, |
| 100, |
| EchartsTimeseriesSeriesType.Bar, |
| ), |
| ).toEqual({}); |
| }); |
| |
| test('getMinAndMaxFromBounds returns empty object for time axis', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Time, |
| false, |
| 10, |
| 100, |
| EchartsTimeseriesSeriesType.Bar, |
| ), |
| ).toEqual({}); |
| }); |
| |
| test('getMinAndMaxFromBounds returns dataMin/dataMax for non-bar charts', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Value, |
| true, |
| undefined, |
| undefined, |
| EchartsTimeseriesSeriesType.Line, |
| ), |
| ).toEqual({ |
| min: 'dataMin', |
| max: 'dataMax', |
| }); |
| }); |
| |
| test('getMinAndMaxFromBounds returns bound without scale for non-bar charts', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Value, |
| true, |
| 10, |
| undefined, |
| EchartsTimeseriesSeriesType.Line, |
| ), |
| ).toEqual({ |
| min: 10, |
| max: 'dataMax', |
| }); |
| }); |
| |
| test('getMinAndMaxFromBounds returns scale when truncating without bounds', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Value, |
| true, |
| undefined, |
| undefined, |
| EchartsTimeseriesSeriesType.Bar, |
| ), |
| ).toEqual({ scale: true }); |
| }); |
| |
| test('getMinAndMaxFromBounds returns automatic upper bound when truncating', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Value, |
| true, |
| 10, |
| undefined, |
| EchartsTimeseriesSeriesType.Bar, |
| ), |
| ).toEqual({ |
| min: 10, |
| scale: true, |
| }); |
| }); |
| |
| test('getMinAndMaxFromBounds returns automatic lower bound when truncating', () => { |
| expect( |
| getMinAndMaxFromBounds( |
| AxisType.Value, |
| true, |
| undefined, |
| 100, |
| EchartsTimeseriesSeriesType.Bar, |
| ), |
| ).toEqual({ |
| max: 100, |
| scale: true, |
| }); |
| }); |
| |
| describe('getTimeCompareStackId', () => { |
| it('returns the defaultId when timeCompare is empty', () => { |
| const result = getTimeCompareStackId('default', []); |
| expect(result).toEqual('default'); |
| }); |
| |
| it('returns the defaultId when no value in timeCompare is included in name', () => { |
| const result = getTimeCompareStackId( |
| 'default', |
| ['compare1', 'compare2'], |
| 'test__name', |
| ); |
| expect(result).toEqual('default'); |
| }); |
| |
| it('returns the first value in timeCompare that is included in name', () => { |
| const result = getTimeCompareStackId( |
| 'default', |
| ['compare1', 'compare2'], |
| 'test__compare1', |
| ); |
| expect(result).toEqual('compare1'); |
| }); |
| |
| it('handles name being a number', () => { |
| const result = getTimeCompareStackId('default', ['123', '456'], 123); |
| expect(result).toEqual('123'); |
| }); |
| }); |
| |
| const forecastValue = [ |
| { |
| data: [0, 1], |
| seriesId: 'foo', |
| }, |
| { |
| data: [0, 2], |
| seriesId: 'bar', |
| }, |
| ]; |
| |
| test('extractTooltipKeys with rich tooltip', () => { |
| const result = extractTooltipKeys(forecastValue, 1, true, false); |
| expect(result).toEqual(['foo', 'bar']); |
| }); |
| |
| test('extractTooltipKeys with rich tooltip and sorting by metrics', () => { |
| const result = extractTooltipKeys(forecastValue, 1, true, true); |
| expect(result).toEqual(['bar', 'foo']); |
| }); |
| |
| test('extractTooltipKeys with non-rich tooltip', () => { |
| const result = extractTooltipKeys(forecastValue, 1, false, false); |
| expect(result).toEqual(['foo']); |
| }); |