mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
feat(plugin): add plugin-chart-cartodiagram (#25869)
Co-authored-by: Jakob Miksch <jakob@meggsimum.de>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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 { ChartLayer } from '../../src/components/ChartLayer';
|
||||
import { ChartLayerOptions } from '../../src/types';
|
||||
|
||||
describe('ChartLayer', () => {
|
||||
it('creates div and loading mask', () => {
|
||||
const options: ChartLayerOptions = {
|
||||
chartVizType: 'pie',
|
||||
};
|
||||
const chartLayer = new ChartLayer(options);
|
||||
|
||||
expect(chartLayer.loadingMask).toBeDefined();
|
||||
expect(chartLayer.div).toBeDefined();
|
||||
});
|
||||
|
||||
it('can remove chart elements', () => {
|
||||
const options: ChartLayerOptions = {
|
||||
chartVizType: 'pie',
|
||||
};
|
||||
const chartLayer = new ChartLayer(options);
|
||||
chartLayer.charts = [
|
||||
{
|
||||
htmlElement: document.createElement('div'),
|
||||
},
|
||||
];
|
||||
|
||||
chartLayer.removeAllChartElements();
|
||||
expect(chartLayer.charts).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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 { CartodiagramPlugin } from '../src';
|
||||
|
||||
/**
|
||||
* The example tests in this file act as a starting point, and
|
||||
* we encourage you to build more. These tests check that the
|
||||
* plugin loads properly, and focus on `transformProps`
|
||||
* to ake sure that data, controls, and props are all
|
||||
* treated correctly (e.g. formData from plugin controls
|
||||
* properly transform the data and/or any resulting props).
|
||||
*/
|
||||
describe('CartodiagramPlugin', () => {
|
||||
it('exists', () => {
|
||||
expect(CartodiagramPlugin).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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 { getChartBuildQueryRegistry } from '@superset-ui/core';
|
||||
import buildQuery from '../../src/plugin/buildQuery';
|
||||
|
||||
describe('CartodiagramPlugin buildQuery', () => {
|
||||
const selectedChartParams = {
|
||||
extra_form_data: {},
|
||||
groupby: [],
|
||||
};
|
||||
|
||||
const selectedChart = {
|
||||
viz_type: 'pie',
|
||||
params: JSON.stringify(selectedChartParams),
|
||||
};
|
||||
|
||||
const formData = {
|
||||
datasource: '5__table',
|
||||
granularity_sqla: 'ds',
|
||||
series: 'foo',
|
||||
viz_type: 'my_chart',
|
||||
selected_chart: JSON.stringify(selectedChart),
|
||||
geom_column: 'geom',
|
||||
};
|
||||
|
||||
let chartQueryBuilderMock: jest.MockedFunction<any>;
|
||||
beforeEach(() => {
|
||||
chartQueryBuilderMock = jest.fn();
|
||||
|
||||
const registry = getChartBuildQueryRegistry();
|
||||
registry.registerValue('pie', chartQueryBuilderMock);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// remove registered buildQuery
|
||||
const registry = getChartBuildQueryRegistry();
|
||||
registry.clear();
|
||||
});
|
||||
|
||||
it('should call the buildQuery function of the referenced chart', () => {
|
||||
buildQuery(formData);
|
||||
expect(chartQueryBuilderMock.mock.calls).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should build groupby with geom in form data', () => {
|
||||
const expectedParams = { ...selectedChartParams, groupby: ['geom'] };
|
||||
|
||||
buildQuery(formData);
|
||||
expect(chartQueryBuilderMock.mock.calls[0][0]).toEqual(expectedParams);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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 CartodiagramPlugin from '../../src/CartodiagramPlugin';
|
||||
|
||||
describe('CartodiagramPlugin', () => {
|
||||
it('exists', () => {
|
||||
expect(CartodiagramPlugin).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* 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 {
|
||||
ChartProps,
|
||||
getChartTransformPropsRegistry,
|
||||
supersetTheme,
|
||||
} from '@superset-ui/core';
|
||||
import { LayerConf, MapViewConfigs, ZoomConfigs } from '../../src/types';
|
||||
import transformProps from '../../src/plugin/transformProps';
|
||||
import {
|
||||
groupedTimeseriesChartData,
|
||||
groupedTimeseriesLabelMap,
|
||||
} from '../testData';
|
||||
|
||||
describe('CartodiagramPlugin transformProps', () => {
|
||||
const chartSize: ZoomConfigs = {
|
||||
type: 'FIXED',
|
||||
configs: {
|
||||
height: 10,
|
||||
width: 10,
|
||||
zoom: 1,
|
||||
},
|
||||
values: {
|
||||
1: {
|
||||
height: 10,
|
||||
width: 10,
|
||||
},
|
||||
},
|
||||
};
|
||||
const layerConfigs: LayerConf[] = [
|
||||
{
|
||||
type: 'XYZ',
|
||||
title: 'foo',
|
||||
url: 'example.com',
|
||||
},
|
||||
];
|
||||
const mapView: MapViewConfigs = {
|
||||
mode: 'FIT_DATA',
|
||||
zoom: 1,
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
fixedZoom: 1,
|
||||
fixedLatitude: 0,
|
||||
fixedLongitude: 0,
|
||||
};
|
||||
|
||||
// only minimal subset of actual params
|
||||
const selectedChartParams = {
|
||||
groupby: ['bar'],
|
||||
x_axis: 'mydate',
|
||||
};
|
||||
|
||||
const selectedChart = {
|
||||
id: 1,
|
||||
viz_type: 'pie',
|
||||
slice_name: 'foo',
|
||||
params: JSON.stringify(selectedChartParams),
|
||||
};
|
||||
|
||||
const formData = {
|
||||
viz_type: 'cartodiagram',
|
||||
geomColumn: 'geom',
|
||||
selectedChart: JSON.stringify(selectedChart),
|
||||
chartSize,
|
||||
layerConfigs,
|
||||
mapView,
|
||||
chartBackgroundColor: '#000000',
|
||||
chartBackgroundBorderRadius: 5,
|
||||
};
|
||||
|
||||
const chartProps = new ChartProps({
|
||||
formData,
|
||||
width: 800,
|
||||
height: 600,
|
||||
queriesData: [
|
||||
{
|
||||
data: groupedTimeseriesChartData,
|
||||
label_map: groupedTimeseriesLabelMap,
|
||||
},
|
||||
],
|
||||
theme: supersetTheme,
|
||||
});
|
||||
|
||||
let chartTransformPropsPieMock: jest.MockedFunction<any>;
|
||||
let chartTransformPropsTimeseriesMock: jest.MockedFunction<any>;
|
||||
beforeEach(() => {
|
||||
chartTransformPropsPieMock = jest.fn();
|
||||
chartTransformPropsTimeseriesMock = jest.fn();
|
||||
const registry = getChartTransformPropsRegistry();
|
||||
registry.registerValue('pie', chartTransformPropsPieMock);
|
||||
registry.registerValue(
|
||||
'echarts_timeseries',
|
||||
chartTransformPropsTimeseriesMock,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// remove registered transformProps
|
||||
const registry = getChartTransformPropsRegistry();
|
||||
registry.clear();
|
||||
});
|
||||
|
||||
it('should call the transform props function of the referenced chart', () => {
|
||||
transformProps(chartProps);
|
||||
expect(chartTransformPropsPieMock).toHaveBeenCalled();
|
||||
expect(chartTransformPropsTimeseriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should transform chart props for viz', () => {
|
||||
const transformedProps = transformProps(chartProps);
|
||||
expect(transformedProps).toEqual(
|
||||
expect.objectContaining({
|
||||
width: chartProps.width,
|
||||
height: chartProps.height,
|
||||
geomColumn: formData.geomColumn,
|
||||
selectedChart: expect.objectContaining({
|
||||
viz_type: selectedChart.viz_type,
|
||||
params: selectedChartParams,
|
||||
}),
|
||||
// The actual test for the created chartConfigs
|
||||
// will be done in transformPropsUtil.test.ts
|
||||
chartConfigs: expect.objectContaining({
|
||||
type: 'FeatureCollection',
|
||||
}),
|
||||
chartVizType: selectedChart.viz_type,
|
||||
chartSize,
|
||||
layerConfigs,
|
||||
mapView,
|
||||
chartBackgroundColor: formData.chartBackgroundColor,
|
||||
chartBackgroundBorderRadius: formData.chartBackgroundBorderRadius,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const coord1 = '[1,2]';
|
||||
const coord2 = '[3,4]';
|
||||
export const geom1 = `{"type":"Point","coordinates":${coord1}}`;
|
||||
export const geom2 = `{"type":"Point","coordinates":${coord2}}`;
|
||||
|
||||
export const nonTimeSeriesChartData: any = [
|
||||
{
|
||||
geom: geom1,
|
||||
my_value: 'apple',
|
||||
my_count: 347,
|
||||
},
|
||||
{
|
||||
geom: geom1,
|
||||
my_value: 'apple',
|
||||
my_count: 360,
|
||||
},
|
||||
{
|
||||
geom: geom1,
|
||||
my_value: 'lemon',
|
||||
my_count: 335,
|
||||
},
|
||||
{
|
||||
geom: geom1,
|
||||
my_value: 'lemon',
|
||||
my_count: 333,
|
||||
},
|
||||
{
|
||||
geom: geom1,
|
||||
my_value: 'lemon',
|
||||
my_count: 353,
|
||||
},
|
||||
{
|
||||
geom: geom1,
|
||||
my_value: 'lemon',
|
||||
my_count: 359,
|
||||
},
|
||||
{
|
||||
geom: geom2,
|
||||
my_value: 'lemon',
|
||||
my_count: 347,
|
||||
},
|
||||
{
|
||||
geom: geom2,
|
||||
my_value: 'apple',
|
||||
my_count: 335,
|
||||
},
|
||||
{
|
||||
geom: geom2,
|
||||
my_value: 'apple',
|
||||
my_count: 356,
|
||||
},
|
||||
{
|
||||
geom: geom2,
|
||||
my_value: 'banana',
|
||||
my_count: 218,
|
||||
},
|
||||
];
|
||||
|
||||
export const timeseriesChartData = [
|
||||
{
|
||||
[geom1]: 347,
|
||||
[geom2]: 360,
|
||||
mydate: 1564275000000,
|
||||
},
|
||||
{
|
||||
[geom1]: 353,
|
||||
[geom2]: 328,
|
||||
mydate: 1564272000000,
|
||||
},
|
||||
];
|
||||
|
||||
export const groupedTimeseriesChartData = [
|
||||
{
|
||||
[`${geom1}, apple`]: 347,
|
||||
[`${geom2}, apple`]: 360,
|
||||
[`${geom1}, lemon`]: 352,
|
||||
[`${geom2}, lemon`]: 364,
|
||||
mydate: 1564275000000,
|
||||
},
|
||||
{
|
||||
[`${geom1}, apple`]: 353,
|
||||
[`${geom2}, apple`]: 328,
|
||||
[`${geom1}, lemon`]: 346,
|
||||
[`${geom2}, lemon`]: 333,
|
||||
mydate: 1564272000000,
|
||||
},
|
||||
];
|
||||
|
||||
export const groupedTimeseriesLabelMap = {
|
||||
[`${geom1}, apple`]: [geom1, 'apple'],
|
||||
[`${geom2}, apple`]: [geom2, 'apple'],
|
||||
[`${geom1}, lemon`]: [geom1, 'lemon'],
|
||||
[`${geom2}, lemon`]: [geom2, 'lemon'],
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": false,
|
||||
"emitDeclarationOnly": false,
|
||||
"noEmit": true,
|
||||
"rootDir": "."
|
||||
},
|
||||
"extends": "../../../tsconfig.json",
|
||||
"include": [
|
||||
"**/*",
|
||||
"../types/**/*",
|
||||
"../../../types/**/*"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../packages/superset-ui-chart-controls"
|
||||
},
|
||||
{
|
||||
"path": "../../../packages/superset-ui-core"
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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 { ChartConfig } from '../../src/types';
|
||||
import { isChartConfigEqual, simplifyConfig } from '../../src/util/chartUtil';
|
||||
|
||||
describe('chartUtil', () => {
|
||||
const configA: ChartConfig = {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [],
|
||||
},
|
||||
properties: {
|
||||
refs: 'foo',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const configB: ChartConfig = {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [],
|
||||
},
|
||||
properties: {
|
||||
refs: 'foo',
|
||||
foo: 'bar',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe('simplifyConfig', () => {
|
||||
it('removes the refs property from a feature', () => {
|
||||
const simplifiedConfig = simplifyConfig(configA);
|
||||
const propKeys = Object.keys(simplifiedConfig.features[0].properties);
|
||||
|
||||
expect(propKeys).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isChartConfigEqual', () => {
|
||||
it('returns true, if configurations are equal', () => {
|
||||
const isEqual = isChartConfigEqual(configA, structuredClone(configA));
|
||||
expect(isEqual).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if configurations are not equal', () => {
|
||||
const isEqual = isChartConfigEqual(configA, configB);
|
||||
expect(isEqual).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* 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 {
|
||||
ControlPanelConfig,
|
||||
CustomControlItem,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import {
|
||||
getLayerConfig,
|
||||
selectedChartMutator,
|
||||
} from '../../src/util/controlPanelUtil';
|
||||
|
||||
describe('controlPanelUtil', () => {
|
||||
describe('getLayerConfig', () => {
|
||||
it('returns the correct layer config', () => {
|
||||
const layerConfigs: CustomControlItem = {
|
||||
name: 'layer_configs',
|
||||
config: {
|
||||
type: 'dummy',
|
||||
renderTrigger: true,
|
||||
label: 'Layers',
|
||||
default: [
|
||||
{
|
||||
type: 'XYZ',
|
||||
url: 'http://example.com/',
|
||||
title: 'dummy title',
|
||||
attribution: 'dummy attribution',
|
||||
},
|
||||
],
|
||||
description: 'The configuration for the map layers',
|
||||
},
|
||||
};
|
||||
const controlPanel: ControlPanelConfig = {
|
||||
controlPanelSections: [
|
||||
{
|
||||
label: 'Configuration',
|
||||
expanded: true,
|
||||
controlSetRows: [],
|
||||
},
|
||||
{
|
||||
label: 'Map Options',
|
||||
expanded: true,
|
||||
controlSetRows: [
|
||||
[
|
||||
{
|
||||
name: 'map_view',
|
||||
config: {
|
||||
type: 'dummy',
|
||||
},
|
||||
},
|
||||
],
|
||||
[layerConfigs],
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Chart Options',
|
||||
expanded: true,
|
||||
controlSetRows: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
const extractedLayerConfigs = getLayerConfig(controlPanel);
|
||||
|
||||
expect(extractedLayerConfigs).toEqual(layerConfigs);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectedChartMutator', () => {
|
||||
it('returns empty array for empty inputs', () => {
|
||||
const response = {};
|
||||
const value = undefined;
|
||||
const result = selectedChartMutator(response, value);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns parsed value if response is empty', () => {
|
||||
const response = {};
|
||||
|
||||
const sliceName = 'foobar';
|
||||
const value = JSON.stringify({
|
||||
id: 278,
|
||||
params: '',
|
||||
slice_name: sliceName,
|
||||
viz_type: 'pie',
|
||||
});
|
||||
|
||||
const result = selectedChartMutator(response, value);
|
||||
|
||||
expect(result[0].label).toEqual(sliceName);
|
||||
});
|
||||
|
||||
it('returns response options if no value is chosen', () => {
|
||||
const sliceName1 = 'foo';
|
||||
const sliceName2 = 'bar';
|
||||
const response = {
|
||||
result: [
|
||||
{
|
||||
id: 1,
|
||||
params: '{}',
|
||||
slice_name: sliceName1,
|
||||
viz_type: 'viz1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
params: '{}',
|
||||
slice_name: sliceName2,
|
||||
viz_type: 'viz2',
|
||||
},
|
||||
],
|
||||
};
|
||||
const value = undefined;
|
||||
|
||||
const result = selectedChartMutator(response, value);
|
||||
expect(result[0].label).toEqual(sliceName1);
|
||||
expect(result[1].label).toEqual(sliceName2);
|
||||
});
|
||||
|
||||
it('returns correct result if id of chosen config does not exist in response', () => {
|
||||
const response = {
|
||||
result: [
|
||||
{
|
||||
id: 1,
|
||||
params: '{}',
|
||||
slice_name: 'foo',
|
||||
viz_type: 'viz1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
params: '{}',
|
||||
slice_name: 'bar',
|
||||
viz_type: 'viz2',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const value = JSON.stringify({
|
||||
id: 3,
|
||||
params: '{}',
|
||||
slice_name: 'my-slice',
|
||||
viz_type: 'pie',
|
||||
});
|
||||
|
||||
const result = selectedChartMutator(response, value);
|
||||
|
||||
// collect all ids in a set to prevent double entries
|
||||
const ids = new Set();
|
||||
result.forEach((item: any) => {
|
||||
const config = JSON.parse(item.value);
|
||||
const { id } = config;
|
||||
ids.add(id);
|
||||
});
|
||||
|
||||
const threeDifferentIds = ids.size === 3;
|
||||
|
||||
expect(threeDifferentIds).toEqual(true);
|
||||
});
|
||||
|
||||
it('returns correct result if id of chosen config already exists', () => {
|
||||
const response = {
|
||||
result: [
|
||||
{
|
||||
id: 1,
|
||||
params: '{}',
|
||||
slice_name: 'foo',
|
||||
viz_type: 'viz1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
params: '{}',
|
||||
slice_name: 'bar',
|
||||
viz_type: 'viz2',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const value = JSON.stringify({
|
||||
id: 1,
|
||||
params: '{}',
|
||||
slice_name: 'my-slice',
|
||||
viz_type: 'pie',
|
||||
});
|
||||
|
||||
const result = selectedChartMutator(response, value);
|
||||
|
||||
const itemsIdWithId1 = result.filter((item: any) => {
|
||||
const config = JSON.parse(item.value);
|
||||
const { id } = config;
|
||||
return id === 1;
|
||||
});
|
||||
expect(itemsIdWithId1.length).toEqual(2);
|
||||
|
||||
const labelsEqual = itemsIdWithId1[0].label === itemsIdWithId1[1].label;
|
||||
expect(labelsEqual).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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 GeoJSON from 'ol/format/GeoJSON';
|
||||
import { Point } from 'geojson';
|
||||
import {
|
||||
getExtentFromFeatures,
|
||||
getProjectedCoordinateFromPointGeoJson,
|
||||
} from '../../src/util/geometryUtil';
|
||||
import { ChartConfig } from '../../src/types';
|
||||
|
||||
describe('geometryUtil', () => {
|
||||
describe('getProjectedCoordinateFromPointGeoJson', () => {
|
||||
it('returns a plausible result', () => {
|
||||
const pointGeoJson: Point = {
|
||||
type: 'Point',
|
||||
coordinates: [6.6555, 49.74283],
|
||||
};
|
||||
const result = getProjectedCoordinateFromPointGeoJson(pointGeoJson);
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
|
||||
const valuesAreNumbers =
|
||||
!Number.isNaN(result[0]) && !Number.isNaN(result[1]);
|
||||
expect(valuesAreNumbers).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExtentFromFeatures', () => {
|
||||
it('computes correct extent with valid input', () => {
|
||||
const expectedExtent = [1, 2, 3, 4];
|
||||
|
||||
const chartConfig: ChartConfig = {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [expectedExtent[0], expectedExtent[1]],
|
||||
},
|
||||
properties: {
|
||||
setDataMask: '',
|
||||
labelMap: '',
|
||||
labelMapB: '',
|
||||
groupby: '',
|
||||
selectedValues: '',
|
||||
formData: '',
|
||||
groupbyB: '',
|
||||
seriesBreakdown: '',
|
||||
legendData: '',
|
||||
echartOptions: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [expectedExtent[2], expectedExtent[3]],
|
||||
},
|
||||
properties: {
|
||||
setDataMask: '',
|
||||
labelMap: '',
|
||||
labelMapB: '',
|
||||
groupby: '',
|
||||
selectedValues: '',
|
||||
formData: '',
|
||||
groupbyB: '',
|
||||
seriesBreakdown: '',
|
||||
legendData: '',
|
||||
echartOptions: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const features = new GeoJSON().readFeatures(chartConfig);
|
||||
const extent = getExtentFromFeatures(features);
|
||||
expect(extent).toEqual(expectedExtent);
|
||||
});
|
||||
|
||||
it('returns undefined on invalid input', () => {
|
||||
const emptyExtent = getExtentFromFeatures([]);
|
||||
expect(emptyExtent).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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 { WfsLayerConf } from '../../src/types';
|
||||
import {
|
||||
createLayer,
|
||||
createWfsLayer,
|
||||
createWmsLayer,
|
||||
createXyzLayer,
|
||||
} from '../../src/util/layerUtil';
|
||||
|
||||
describe('layerUtil', () => {
|
||||
describe('createWmsLayer', () => {
|
||||
it('exists', () => {
|
||||
// function is trivial
|
||||
expect(createWmsLayer).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createWfsLayer', () => {
|
||||
it('properly applies style', async () => {
|
||||
const colorToExpect = '#123456';
|
||||
|
||||
const wfsLayerConf: WfsLayerConf = {
|
||||
title: 'osm:osm-fuel',
|
||||
url: 'https://ows-demo.terrestris.de/geoserver/osm/wfs',
|
||||
type: 'WFS',
|
||||
version: '2.0.2',
|
||||
typeName: 'osm:osm-fuel',
|
||||
style: {
|
||||
name: 'Default Style',
|
||||
rules: [
|
||||
{
|
||||
name: 'Default Rule',
|
||||
symbolizers: [
|
||||
{
|
||||
kind: 'Line',
|
||||
color: '#000000',
|
||||
width: 2,
|
||||
},
|
||||
{
|
||||
kind: 'Mark',
|
||||
wellKnownName: 'circle',
|
||||
color: colorToExpect,
|
||||
},
|
||||
{
|
||||
kind: 'Fill',
|
||||
color: '#000000',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const wfsLayer = await createWfsLayer(wfsLayerConf);
|
||||
|
||||
const style = wfsLayer!.getStyle();
|
||||
// @ts-ignore
|
||||
expect(style!.length).toEqual(3);
|
||||
|
||||
const colorAtLayer = style![1].getImage().getFill().getColor();
|
||||
expect(colorToExpect).toEqual(colorAtLayer);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createXyzLayer', () => {
|
||||
it('exists', () => {
|
||||
// function is trivial
|
||||
expect(createXyzLayer).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createLayer', () => {
|
||||
it('exists', () => {
|
||||
expect(createLayer).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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 Map from 'ol/Map.js';
|
||||
import OSM from 'ol/source/OSM.js';
|
||||
import TileLayer from 'ol/layer/Tile.js';
|
||||
import View from 'ol/View.js';
|
||||
import { ChartConfig } from '../../src/types';
|
||||
import { fitMapToCharts } from '../../src/util/mapUtil';
|
||||
|
||||
describe('mapUtil', () => {
|
||||
describe('fitMapToCharts', () => {
|
||||
it('changes the center of the map', () => {
|
||||
const chartConfig: ChartConfig = {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [8.793, 53.04117],
|
||||
},
|
||||
properties: {
|
||||
setDataMask: '',
|
||||
labelMap: '',
|
||||
labelMapB: '',
|
||||
groupby: '',
|
||||
selectedValues: '',
|
||||
formData: '',
|
||||
groupbyB: '',
|
||||
seriesBreakdown: '',
|
||||
legendData: '',
|
||||
echartOptions: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [10.61833, 51.8],
|
||||
},
|
||||
properties: {
|
||||
setDataMask: '',
|
||||
labelMap: '',
|
||||
labelMapB: '',
|
||||
groupby: '',
|
||||
selectedValues: '',
|
||||
formData: '',
|
||||
groupbyB: '',
|
||||
seriesBreakdown: '',
|
||||
legendData: '',
|
||||
echartOptions: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [6.86883, 50.35667],
|
||||
},
|
||||
properties: {
|
||||
setDataMask: '',
|
||||
labelMap: '',
|
||||
labelMapB: '',
|
||||
groupby: '',
|
||||
selectedValues: '',
|
||||
formData: '',
|
||||
groupbyB: '',
|
||||
seriesBreakdown: '',
|
||||
legendData: '',
|
||||
echartOptions: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const initialCenter = [0, 0];
|
||||
|
||||
const olMap = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM(),
|
||||
}),
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: initialCenter,
|
||||
zoom: 2,
|
||||
}),
|
||||
});
|
||||
|
||||
// should set center
|
||||
fitMapToCharts(olMap, chartConfig);
|
||||
|
||||
const updatedCenter = olMap.getView().getCenter();
|
||||
|
||||
expect(initialCenter).not.toEqual(updatedCenter);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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 { isVersionBelow } from '../../src/util/serviceUtil';
|
||||
|
||||
describe('serviceUtil', () => {
|
||||
describe('isVersionBelow', () => {
|
||||
describe('WMS', () => {
|
||||
it('recognizes the higher version', () => {
|
||||
const result = isVersionBelow('1.3.0', '1.1.0', 'WMS');
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
it('recognizes the lower version', () => {
|
||||
const result = isVersionBelow('1.1.1', '1.3.0', 'WMS');
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('WFS', () => {
|
||||
it('recognizes the higher version', () => {
|
||||
const result = isVersionBelow('2.0.2', '1.1.0', 'WFS');
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
it('recognizes the lower version', () => {
|
||||
const result = isVersionBelow('1.1.0', '2.0.2', 'WFS');
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* 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 {
|
||||
groupByLocation,
|
||||
getChartConfigs,
|
||||
parseSelectedChart,
|
||||
getGeojsonColumns,
|
||||
createColumnName,
|
||||
groupByLocationGenericX,
|
||||
stripGeomFromColnamesAndTypes,
|
||||
stripGeomColumnFromLabelMap,
|
||||
} from '../../src/util/transformPropsUtil';
|
||||
import {
|
||||
nonTimeSeriesChartData,
|
||||
groupedTimeseriesChartData,
|
||||
geom1,
|
||||
geom2,
|
||||
groupedTimeseriesLabelMap,
|
||||
} from '../testData';
|
||||
|
||||
describe('transformPropsUtil', () => {
|
||||
const groupedTimeseriesParams = {
|
||||
x_axis: 'mydate',
|
||||
};
|
||||
|
||||
const groupedTimeseriesQueryData = {
|
||||
label_map: groupedTimeseriesLabelMap,
|
||||
};
|
||||
|
||||
describe('getGeojsonColumns', () => {
|
||||
it('gets the GeoJSON columns', () => {
|
||||
const columns = ['foo', 'bar', geom1];
|
||||
const result = getGeojsonColumns(columns);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual(2);
|
||||
});
|
||||
|
||||
it('gets multiple GeoJSON columns', () => {
|
||||
const columns = ['foo', geom2, 'bar', geom1];
|
||||
const result = getGeojsonColumns(columns);
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result[0]).toEqual(1);
|
||||
expect(result[1]).toEqual(3);
|
||||
});
|
||||
|
||||
it('returns empty array when no GeoJSON is included', () => {
|
||||
const columns = ['foo', 'bar'];
|
||||
const result = getGeojsonColumns(columns);
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createColumnName', () => {
|
||||
it('creates a columns name', () => {
|
||||
const columns = ['foo', 'bar'];
|
||||
const result = createColumnName(columns, []);
|
||||
expect(result).toEqual('foo, bar');
|
||||
});
|
||||
|
||||
it('ignores items provided by ignoreIdx', () => {
|
||||
const columns = ['foo', 'bar', 'baz'];
|
||||
const ignoreIdx = [1];
|
||||
const result = createColumnName(columns, ignoreIdx);
|
||||
expect(result).toEqual('foo, baz');
|
||||
});
|
||||
});
|
||||
|
||||
describe('groupByLocationGenericX', () => {
|
||||
it('groups in the correct count of geometries', () => {
|
||||
const result = groupByLocationGenericX(
|
||||
groupedTimeseriesChartData,
|
||||
groupedTimeseriesParams,
|
||||
groupedTimeseriesQueryData,
|
||||
);
|
||||
const countOfGeometries = Object.keys(result).length;
|
||||
expect(countOfGeometries).toEqual(2);
|
||||
});
|
||||
|
||||
it('groups items by same geometry', () => {
|
||||
const result = groupByLocationGenericX(
|
||||
groupedTimeseriesChartData,
|
||||
groupedTimeseriesParams,
|
||||
groupedTimeseriesQueryData,
|
||||
);
|
||||
const allGeom1 = result[geom1].length === 2;
|
||||
const allGeom2 = result[geom2].length === 2;
|
||||
expect(allGeom1 && allGeom2).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('groupByLocation', () => {
|
||||
it('groups in the correct count of geometries', () => {
|
||||
const geometryColumn = 'geom';
|
||||
const result = groupByLocation(nonTimeSeriesChartData, geometryColumn);
|
||||
const countOfGeometries = Object.keys(result).length;
|
||||
expect(countOfGeometries).toEqual(2);
|
||||
});
|
||||
|
||||
it('groups items by same geometry', () => {
|
||||
const geometryColumn = 'geom';
|
||||
const result = groupByLocation(nonTimeSeriesChartData, geometryColumn);
|
||||
const allGeom1 = result[geom1].length === 6;
|
||||
const allGeom2 = result[geom2].length === 4;
|
||||
expect(allGeom1 && allGeom2).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripGeomFromColnamesAndTypes', () => {
|
||||
it('strips the geom from colnames with geom column', () => {
|
||||
const queryData = {
|
||||
colnames: ['foo', 'geom'],
|
||||
coltypes: [0, 0],
|
||||
};
|
||||
const result = stripGeomFromColnamesAndTypes(queryData, 'geom');
|
||||
expect(result).toEqual({
|
||||
colnames: ['foo'],
|
||||
coltypes: [0],
|
||||
});
|
||||
});
|
||||
|
||||
it('strips the geom from colnames with grouped columns', () => {
|
||||
const queryData = {
|
||||
colnames: ['foo', `bar, ${geom1}`],
|
||||
coltypes: [0, 0],
|
||||
};
|
||||
const result = stripGeomFromColnamesAndTypes(queryData, 'geom');
|
||||
expect(result).toEqual({
|
||||
colnames: ['foo', 'bar'],
|
||||
coltypes: [0, 0],
|
||||
});
|
||||
});
|
||||
|
||||
it('strips the geom from colnames with grouped columns without geom', () => {
|
||||
const queryData = {
|
||||
colnames: ['foo', `bar, baz`],
|
||||
coltypes: [0, 0],
|
||||
};
|
||||
const result = stripGeomFromColnamesAndTypes(queryData, 'geom');
|
||||
expect(result).toEqual({
|
||||
colnames: ['foo', 'bar, baz'],
|
||||
coltypes: [0, 0],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripGeomColumnFromLabelMap', () => {
|
||||
it('strips the geom column from label_map', () => {
|
||||
const labelMap = {
|
||||
[`apple, ${geom1}`]: ['apple', geom1],
|
||||
[`${geom2}, lemon`]: [geom2, 'lemon'],
|
||||
geom: ['geom'],
|
||||
};
|
||||
const result = stripGeomColumnFromLabelMap(labelMap, 'geom');
|
||||
expect(result).toEqual({
|
||||
apple: ['apple'],
|
||||
lemon: ['lemon'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getChartConfigs', () => {
|
||||
let chartTransformer: jest.MockedFunction<any>;
|
||||
const geomColumn = 'geom';
|
||||
const pieChartConfig = {
|
||||
params: {},
|
||||
viz_type: 'pie',
|
||||
};
|
||||
const chartProps: any = {
|
||||
queriesData: [
|
||||
{
|
||||
data: nonTimeSeriesChartData,
|
||||
},
|
||||
],
|
||||
};
|
||||
beforeEach(() => {
|
||||
chartTransformer = jest.fn();
|
||||
});
|
||||
|
||||
it('calls the transformProps function for every location', () => {
|
||||
getChartConfigs(pieChartConfig, geomColumn, chartProps, chartTransformer);
|
||||
|
||||
expect(chartTransformer).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
it('returns a geojson', () => {
|
||||
const result = getChartConfigs(
|
||||
pieChartConfig,
|
||||
geomColumn,
|
||||
chartProps,
|
||||
chartTransformer,
|
||||
);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({
|
||||
type: 'FeatureCollection',
|
||||
features: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
type: 'Feature',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
);
|
||||
});
|
||||
it('returns a feature for each location', () => {
|
||||
const result = getChartConfigs(
|
||||
pieChartConfig,
|
||||
geomColumn,
|
||||
chartProps,
|
||||
chartTransformer,
|
||||
);
|
||||
expect(result.features).toHaveLength(2);
|
||||
expect(result.features[0].geometry).toEqual(JSON.parse(geom1));
|
||||
expect(result.features[1].geometry).toEqual(JSON.parse(geom2));
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseSelectedChart', () => {
|
||||
it('parses the inline stringified JSON', () => {
|
||||
const selectedChartObject = {
|
||||
id: 278,
|
||||
params:
|
||||
'{"adhoc_filters":[],"applied_time_extras":{},"datasource":"24__table","viz_type":"pie","time_range":"No filter","groupby":["nuclide"],"metric":{"expressionType":"SIMPLE","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"nuclide","description":null,"expression":null,"filterable":true,"groupby":true,"id":772,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"TEXT","type_generic":1,"verbose_name":null,"warning_markdown":null},"aggregate":"COUNT","sqlExpression":null,"isNew":false,"datasourceWarning":false,"hasCustomLabel":false,"label":"COUNT(nuclide)","optionName":"metric_k6d9mt9zujc_7v9szd1i0pl"},"dashboards":[]}',
|
||||
slice_name: 'pie',
|
||||
viz_type: 'pie',
|
||||
};
|
||||
|
||||
const selectedChartString = JSON.stringify(selectedChartObject);
|
||||
const result = parseSelectedChart(selectedChartString);
|
||||
const expectedParams = JSON.parse(selectedChartObject.params);
|
||||
|
||||
expect(result.params).toEqual(expectedParams);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user