2020-09-01 02:00:51 -04:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-04-12 09:13:41 -04:00
|
|
|
import { SortSeriesType } from '@superset-ui/chart-controls';
|
2023-03-16 10:26:01 -04:00
|
|
|
import {
|
2023-11-24 10:36:32 -05:00
|
|
|
AxisType,
|
2023-03-16 10:26:01 -04:00
|
|
|
DataRecord,
|
2023-05-19 09:29:11 -04:00
|
|
|
GenericDataType,
|
2023-03-16 10:26:01 -04:00
|
|
|
getNumberFormatter,
|
|
|
|
getTimeFormatter,
|
2023-04-06 08:36:34 -04:00
|
|
|
supersetTheme as theme,
|
2023-03-16 10:26:01 -04:00
|
|
|
} from '@superset-ui/core';
|
2020-09-18 15:28:18 -04:00
|
|
|
import {
|
2023-05-23 06:25:08 -04:00
|
|
|
calculateLowerLogTick,
|
2021-04-09 02:55:03 -04:00
|
|
|
dedupSeries,
|
2020-09-18 15:28:18 -04:00
|
|
|
extractGroupbyLabel,
|
2022-01-21 14:23:23 -05:00
|
|
|
extractSeries,
|
2023-03-16 10:26:01 -04:00
|
|
|
extractShowValueIndexes,
|
2020-09-18 15:28:18 -04:00
|
|
|
formatSeriesName,
|
2023-11-24 10:36:32 -05:00
|
|
|
getAxisType,
|
2021-01-20 13:15:55 -05:00
|
|
|
getChartPadding,
|
|
|
|
getLegendProps,
|
2022-08-22 10:55:09 -04:00
|
|
|
getOverMaxHiddenFormatter,
|
2023-12-08 08:40:09 -05:00
|
|
|
getMinAndMaxFromBounds,
|
2023-03-16 10:26:01 -04:00
|
|
|
sanitizeHtml,
|
|
|
|
sortAndFilterSeries,
|
2023-04-12 09:13:41 -04:00
|
|
|
sortRows,
|
2020-09-18 15:28:18 -04:00
|
|
|
} from '../../src/utils/series';
|
2023-04-12 09:13:41 -04:00
|
|
|
import { LegendOrientation, LegendType } from '../../src/types';
|
2021-01-20 13:15:55 -05:00
|
|
|
import { defaultLegendPadding } from '../../src/defaults';
|
2021-11-09 05:34:07 -05:00
|
|
|
import { NULL_STRING } from '../../src/constants';
|
2020-09-01 02:00:51 -04:00
|
|
|
|
2023-04-06 08:36:34 -04:00
|
|
|
const expectedThemeProps = {
|
|
|
|
selector: ['all', 'inverse'],
|
|
|
|
selectorLabel: {
|
|
|
|
fontFamily: theme.typography.families.sansSerif,
|
|
|
|
fontSize: theme.typography.sizes.s,
|
|
|
|
color: theme.colors.grayscale.base,
|
|
|
|
borderColor: theme.colors.grayscale.base,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2023-04-12 09:13:41 -04:00
|
|
|
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 },
|
|
|
|
];
|
|
|
|
|
2023-04-14 13:43:15 -04:00
|
|
|
const totalStackedValues = [3, 15, 14];
|
|
|
|
|
2023-04-12 09:13:41 -04:00
|
|
|
test('sortRows by name ascending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by name descending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by sum ascending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by sum descending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
2023-03-16 10:26:01 -04:00
|
|
|
|
2023-04-12 09:13:41 -04:00
|
|
|
test('sortRows by avg ascending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by avg descending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by min ascending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by min descending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by max ascending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortRows by max descending', () => {
|
2023-04-14 13:43:15 -04:00
|
|
|
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 },
|
2023-04-12 09:13:41 -04:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by min ascending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Min, true),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['y', 'x', 'z']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by min descending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Min, false),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['z', 'x', 'y']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by max ascending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Max, true),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['x', 'z', 'y']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by max descending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Max, false),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['y', 'z', 'x']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by avg ascending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Avg, true),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['x', 'y', 'z']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by avg descending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Avg, false),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['z', 'y', 'x']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by sum ascending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Sum, true),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['x', 'y', 'z']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by sum descending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Sum, false),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['z', 'y', 'x']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by name ascending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, true),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['x', 'y', 'z']);
|
2023-04-12 09:13:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('sortAndFilterSeries by name descending', () => {
|
2023-03-16 10:26:01 -04:00
|
|
|
expect(
|
2023-04-12 09:13:41 -04:00
|
|
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, false),
|
2023-03-16 10:26:01 -04:00
|
|
|
).toEqual(['z', 'y', 'x']);
|
|
|
|
});
|
|
|
|
|
2022-01-21 14:23:23 -05:00
|
|
|
describe('extractSeries', () => {
|
2020-09-01 02:00:51 -04:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
];
|
2023-04-14 13:43:15 -04:00
|
|
|
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,
|
2023-05-23 06:25:08 -04:00
|
|
|
1,
|
2022-01-21 14:23:23 -05:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
];
|
2023-04-14 13:43:15 -04:00
|
|
|
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,
|
2023-05-23 06:25:08 -04:00
|
|
|
1,
|
2020-09-01 02:00:51 -04:00
|
|
|
]);
|
|
|
|
});
|
2021-03-19 12:42:55 -04:00
|
|
|
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
];
|
2023-04-14 13:43:15 -04:00
|
|
|
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,
|
2023-05-23 06:25:08 -04:00
|
|
|
1,
|
2021-03-19 12:42:55 -04:00
|
|
|
]);
|
|
|
|
});
|
2020-09-01 02:00:51 -04:00
|
|
|
});
|
2020-09-10 17:56:38 -04:00
|
|
|
|
|
|
|
describe('extractGroupbyLabel', () => {
|
|
|
|
it('should join together multiple groupby labels', () => {
|
2021-11-09 07:42:28 -05:00
|
|
|
expect(
|
|
|
|
extractGroupbyLabel({
|
|
|
|
datum: { a: 'abc', b: 'qwerty' },
|
|
|
|
groupby: ['a', 'b'],
|
|
|
|
}),
|
|
|
|
).toEqual('abc, qwerty');
|
2020-09-10 17:56:38 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a single groupby', () => {
|
2021-11-09 07:42:28 -05:00
|
|
|
expect(
|
|
|
|
extractGroupbyLabel({ datum: { xyz: 'qqq' }, groupby: ['xyz'] }),
|
|
|
|
).toEqual('qqq');
|
2020-09-10 17:56:38 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle mixed types', () => {
|
|
|
|
expect(
|
2020-09-18 15:28:18 -04:00
|
|
|
extractGroupbyLabel({
|
|
|
|
datum: { strcol: 'abc', intcol: 123, floatcol: 0.123, boolcol: true },
|
|
|
|
groupby: ['strcol', 'intcol', 'floatcol', 'boolcol'],
|
|
|
|
}),
|
|
|
|
).toEqual('abc, 123, 0.123, true');
|
|
|
|
});
|
2020-10-31 14:41:15 -04:00
|
|
|
|
|
|
|
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('');
|
|
|
|
});
|
2020-09-18 15:28:18 -04:00
|
|
|
});
|
|
|
|
|
2022-08-11 14:28:18 -04:00
|
|
|
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]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-09-18 15:28:18 -04:00
|
|
|
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');
|
|
|
|
});
|
|
|
|
|
2022-04-26 13:35:01 -04:00
|
|
|
it('should use default formatting for date values without formatter', () => {
|
2021-11-09 07:42:28 -05:00
|
|
|
expect(formatSeriesName(new Date('2020-09-11'))).toEqual(
|
|
|
|
'2020-09-11T00:00:00.000Z',
|
|
|
|
);
|
2020-09-18 15:28:18 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
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',
|
|
|
|
);
|
2020-09-10 17:56:38 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04: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,
|
2021-02-16 04:47:02 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-02-16 04:47:02 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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,
|
2021-02-16 04:47:02 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-02-16 04:47:02 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
describe('getChartPadding', () => {
|
|
|
|
it('should handle top default', () => {
|
|
|
|
expect(getChartPadding(true, LegendOrientation.Top)).toEqual({
|
|
|
|
bottom: 0,
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
top: defaultLegendPadding[LegendOrientation.Top],
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
it('should handle left default', () => {
|
|
|
|
expect(getChartPadding(true, LegendOrientation.Left)).toEqual({
|
|
|
|
bottom: 0,
|
|
|
|
left: defaultLegendPadding[LegendOrientation.Left],
|
|
|
|
right: 0,
|
|
|
|
top: 0,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
it('should return the default padding when show is false', () => {
|
|
|
|
expect(
|
|
|
|
getChartPadding(false, LegendOrientation.Left, 100, {
|
|
|
|
top: 10,
|
2021-01-20 13:15:55 -05:00
|
|
|
bottom: 20,
|
|
|
|
left: 30,
|
|
|
|
right: 40,
|
2023-05-19 09:29:11 -04:00
|
|
|
}),
|
|
|
|
).toEqual({
|
|
|
|
bottom: 20,
|
|
|
|
left: 30,
|
|
|
|
right: 40,
|
|
|
|
top: 10,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
it('should return the correct padding for left orientation', () => {
|
|
|
|
expect(getChartPadding(true, LegendOrientation.Left, 100)).toEqual({
|
|
|
|
bottom: 0,
|
|
|
|
left: 100,
|
|
|
|
right: 0,
|
|
|
|
top: 0,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
it('should return the correct padding for right orientation', () => {
|
|
|
|
expect(getChartPadding(true, LegendOrientation.Right, 50)).toEqual({
|
|
|
|
bottom: 0,
|
|
|
|
left: 0,
|
|
|
|
right: 50,
|
|
|
|
top: 0,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
it('should return the correct padding for top orientation', () => {
|
|
|
|
expect(getChartPadding(true, LegendOrientation.Top, 20)).toEqual({
|
|
|
|
bottom: 0,
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
top: 20,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-01-20 13:15:55 -05:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
it('should return the correct padding for bottom orientation', () => {
|
|
|
|
expect(getChartPadding(true, LegendOrientation.Bottom, 10)).toEqual({
|
|
|
|
bottom: 10,
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
top: 0,
|
2021-01-20 13:15:55 -05:00
|
|
|
});
|
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-04-09 02:55:03 -04:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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)' },
|
|
|
|
]);
|
2021-04-09 02:55:03 -04:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2021-07-02 07:45:40 -04:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
describe('sanitizeHtml', () => {
|
|
|
|
it('should remove html tags from series name', () => {
|
|
|
|
expect(sanitizeHtml(NULL_STRING)).toEqual('<NULL>');
|
2021-07-02 07:45:40 -04:00
|
|
|
});
|
2023-05-19 09:29:11 -04:00
|
|
|
});
|
2022-08-22 10:55:09 -04:00
|
|
|
|
2023-05-19 09:29:11 -04:00
|
|
|
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');
|
2022-08-22 10:55:09 -04:00
|
|
|
});
|
2020-09-10 17:56:38 -04:00
|
|
|
});
|
2023-05-23 06:25:08 -04:00
|
|
|
|
|
|
|
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);
|
|
|
|
});
|
2023-11-24 10:36:32 -05:00
|
|
|
|
|
|
|
test('getAxisType', () => {
|
|
|
|
expect(getAxisType(GenericDataType.TEMPORAL)).toEqual(AxisType.time);
|
|
|
|
expect(getAxisType(GenericDataType.NUMERIC)).toEqual(AxisType.value);
|
|
|
|
expect(getAxisType(GenericDataType.BOOLEAN)).toEqual(AxisType.category);
|
|
|
|
expect(getAxisType(GenericDataType.STRING)).toEqual(AxisType.category);
|
|
|
|
});
|
2023-12-08 08:40:09 -05:00
|
|
|
|
|
|
|
test('getMinAndMaxFromBounds returns empty object when not truncating', () => {
|
|
|
|
expect(getMinAndMaxFromBounds(AxisType.value, false, 10, 100)).toEqual({});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('getMinAndMaxFromBounds returns automatic bounds when truncating', () => {
|
|
|
|
expect(
|
|
|
|
getMinAndMaxFromBounds(AxisType.value, true, undefined, undefined),
|
|
|
|
).toEqual({
|
|
|
|
min: 'dataMin',
|
|
|
|
max: 'dataMax',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('getMinAndMaxFromBounds returns automatic upper bound when truncating', () => {
|
|
|
|
expect(getMinAndMaxFromBounds(AxisType.value, true, 10, undefined)).toEqual({
|
|
|
|
min: 10,
|
|
|
|
max: 'dataMax',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('getMinAndMaxFromBounds returns automatic lower bound when truncating', () => {
|
|
|
|
expect(getMinAndMaxFromBounds(AxisType.value, true, undefined, 100)).toEqual({
|
|
|
|
min: 'dataMin',
|
|
|
|
max: 100,
|
|
|
|
});
|
|
|
|
});
|