2021-10-28 06:27:35 -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.
|
|
|
|
*/
|
|
|
|
|
2018-12-12 16:18:27 -05:00
|
|
|
import fetchMock from 'fetch-mock';
|
2020-09-03 15:02:23 -04:00
|
|
|
import {
|
|
|
|
SupersetClientClass,
|
|
|
|
SupersetClient,
|
|
|
|
buildQueryContext,
|
|
|
|
QueryFormData,
|
|
|
|
configure as configureTranslation,
|
2019-02-15 19:03:15 -05:00
|
|
|
ChartClient,
|
|
|
|
getChartBuildQueryRegistry,
|
2019-03-19 17:58:20 -04:00
|
|
|
getChartMetadataRegistry,
|
2019-03-22 14:40:23 -04:00
|
|
|
ChartMetadata,
|
2022-01-07 20:16:24 -05:00
|
|
|
} from '@superset-ui/core';
|
|
|
|
|
2020-01-28 18:15:31 -05:00
|
|
|
import { LOGIN_GLOB } from '../fixtures/constants';
|
2020-05-29 20:33:39 -04:00
|
|
|
import { sankeyFormData } from '../fixtures/formData';
|
2022-01-07 20:16:24 -05:00
|
|
|
import { SliceIdAndOrFormData } from '../../../src/chart/clients/ChartClient';
|
2018-12-12 16:18:27 -05:00
|
|
|
|
2020-09-03 15:02:23 -04:00
|
|
|
configureTranslation();
|
|
|
|
|
2018-12-12 16:18:27 -05:00
|
|
|
describe('ChartClient', () => {
|
2018-12-13 20:15:23 -05:00
|
|
|
let chartClient: ChartClient;
|
2018-12-12 16:18:27 -05:00
|
|
|
|
|
|
|
beforeAll(() => {
|
2021-03-01 16:46:25 -05:00
|
|
|
fetchMock.get(LOGIN_GLOB, { result: '1234' });
|
2018-12-12 16:18:27 -05:00
|
|
|
SupersetClient.reset();
|
|
|
|
SupersetClient.configure().init();
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
chartClient = new ChartClient();
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(fetchMock.restore);
|
|
|
|
|
|
|
|
describe('new ChartClient(config)', () => {
|
|
|
|
it('creates a client without argument', () => {
|
|
|
|
expect(chartClient).toBeInstanceOf(ChartClient);
|
|
|
|
});
|
|
|
|
it('creates a client with specified config.client', () => {
|
|
|
|
const customClient = new SupersetClientClass();
|
|
|
|
chartClient = new ChartClient({ client: customClient });
|
|
|
|
expect(chartClient).toBeInstanceOf(ChartClient);
|
|
|
|
expect(chartClient.client).toBe(customClient);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.loadFormData({ sliceId, formData }, options)', () => {
|
2018-12-13 20:15:23 -05:00
|
|
|
const sliceId = 123;
|
2018-12-12 16:18:27 -05:00
|
|
|
it('fetches formData if given only sliceId', () => {
|
2021-11-09 07:42:28 -05:00
|
|
|
fetchMock.get(
|
|
|
|
`glob:*/api/v1/form_data/?slice_id=${sliceId}`,
|
|
|
|
sankeyFormData,
|
|
|
|
);
|
2018-12-12 16:18:27 -05:00
|
|
|
|
2021-11-09 07:42:28 -05:00
|
|
|
return expect(chartClient.loadFormData({ sliceId })).resolves.toEqual(
|
|
|
|
sankeyFormData,
|
|
|
|
);
|
2018-12-12 16:18:27 -05:00
|
|
|
});
|
|
|
|
it('fetches formData from sliceId and merges with specify formData if both fields are specified', () => {
|
2021-11-09 07:42:28 -05:00
|
|
|
fetchMock.get(
|
|
|
|
`glob:*/api/v1/form_data/?slice_id=${sliceId}`,
|
|
|
|
sankeyFormData,
|
|
|
|
);
|
2018-12-12 16:18:27 -05:00
|
|
|
|
|
|
|
return expect(
|
|
|
|
chartClient.loadFormData({
|
2018-12-13 20:15:23 -05:00
|
|
|
sliceId,
|
2018-12-12 16:18:27 -05:00
|
|
|
formData: {
|
2018-12-13 20:15:23 -05:00
|
|
|
granularity: 'second',
|
|
|
|
viz_type: 'bar',
|
2018-12-12 16:18:27 -05:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
).resolves.toEqual({
|
2020-05-29 20:33:39 -04:00
|
|
|
...sankeyFormData,
|
2018-12-13 20:15:23 -05:00
|
|
|
granularity: 'second',
|
|
|
|
viz_type: 'bar',
|
2018-12-12 16:18:27 -05:00
|
|
|
});
|
|
|
|
});
|
|
|
|
it('returns promise of formData if only formData was given', () =>
|
|
|
|
expect(
|
|
|
|
chartClient.loadFormData({
|
|
|
|
formData: {
|
2018-12-13 20:15:23 -05:00
|
|
|
datasource: '1__table',
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'line',
|
2018-12-12 16:18:27 -05:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
).resolves.toEqual({
|
2018-12-13 20:15:23 -05:00
|
|
|
datasource: '1__table',
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'line',
|
2018-12-12 16:18:27 -05:00
|
|
|
}));
|
|
|
|
it('rejects if none of sliceId or formData is specified', () =>
|
2021-11-09 07:42:28 -05:00
|
|
|
expect(
|
|
|
|
chartClient.loadFormData({} as SliceIdAndOrFormData),
|
|
|
|
).rejects.toEqual(
|
2018-12-12 16:18:27 -05:00
|
|
|
new Error('At least one of sliceId or formData must be specified'),
|
|
|
|
));
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.loadQueryData(formData, options)', () => {
|
|
|
|
it('returns a promise of query data for known chart type', () => {
|
2019-03-22 14:40:23 -04:00
|
|
|
getChartMetadataRegistry().registerValue(
|
|
|
|
'word_cloud',
|
|
|
|
new ChartMetadata({ name: 'Word Cloud', thumbnail: '' }),
|
|
|
|
);
|
2019-03-19 17:58:20 -04:00
|
|
|
|
2021-11-09 07:42:28 -05:00
|
|
|
getChartBuildQueryRegistry().registerValue(
|
|
|
|
'word_cloud',
|
|
|
|
(formData: QueryFormData) => buildQueryContext(formData),
|
2018-12-12 16:18:27 -05:00
|
|
|
);
|
2020-12-29 05:10:39 -05:00
|
|
|
fetchMock.post('glob:*/api/v1/chart/data', [
|
|
|
|
{
|
|
|
|
field1: 'abc',
|
|
|
|
field2: 'def',
|
|
|
|
},
|
|
|
|
]);
|
2018-12-12 16:18:27 -05:00
|
|
|
|
|
|
|
return expect(
|
|
|
|
chartClient.loadQueryData({
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'word_cloud',
|
|
|
|
datasource: '1__table',
|
|
|
|
}),
|
2020-12-29 05:10:39 -05:00
|
|
|
).resolves.toEqual([
|
|
|
|
{
|
|
|
|
field1: 'abc',
|
|
|
|
field2: 'def',
|
|
|
|
},
|
|
|
|
]);
|
2018-12-12 16:18:27 -05:00
|
|
|
});
|
|
|
|
it('returns a promise that rejects for unknown chart type', () =>
|
|
|
|
expect(
|
|
|
|
chartClient.loadQueryData({
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'rainbow_3d_pie',
|
|
|
|
datasource: '1__table',
|
|
|
|
}),
|
|
|
|
).rejects.toEqual(new Error('Unknown chart type: rainbow_3d_pie')));
|
2019-03-19 17:58:20 -04:00
|
|
|
|
|
|
|
it('fetches data from the legacy API if ChartMetadata has useLegacyApi=true,', () => {
|
|
|
|
// note legacy charts do not register a buildQuery function in the registry
|
2019-03-22 14:40:23 -04:00
|
|
|
getChartMetadataRegistry().registerValue(
|
|
|
|
'word_cloud_legacy',
|
|
|
|
new ChartMetadata({
|
|
|
|
name: 'Legacy Word Cloud',
|
|
|
|
thumbnail: '.png',
|
|
|
|
useLegacyApi: true,
|
|
|
|
}),
|
|
|
|
);
|
2019-03-19 17:58:20 -04:00
|
|
|
|
2020-05-29 20:33:39 -04:00
|
|
|
fetchMock.post('glob:*/api/v1/chart/data', () =>
|
2020-01-28 18:15:31 -05:00
|
|
|
Promise.reject(new Error('Unexpected all to v1 API')),
|
2019-03-19 17:58:20 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
fetchMock.post('glob:*/superset/explore_json/', {
|
|
|
|
field1: 'abc',
|
|
|
|
field2: 'def',
|
|
|
|
});
|
|
|
|
|
|
|
|
return expect(
|
|
|
|
chartClient.loadQueryData({
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'word_cloud_legacy',
|
|
|
|
datasource: '1__table',
|
|
|
|
}),
|
2020-12-29 05:10:39 -05:00
|
|
|
).resolves.toEqual([
|
|
|
|
{
|
|
|
|
field1: 'abc',
|
|
|
|
field2: 'def',
|
|
|
|
},
|
|
|
|
]);
|
2019-03-19 17:58:20 -04:00
|
|
|
});
|
2018-12-12 16:18:27 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('.loadDatasource(datasourceKey, options)', () => {
|
|
|
|
it('fetches datasource', () => {
|
2021-11-09 07:42:28 -05:00
|
|
|
fetchMock.get(
|
|
|
|
'glob:*/superset/fetch_datasource_metadata?datasourceKey=1__table',
|
|
|
|
{
|
|
|
|
field1: 'abc',
|
|
|
|
field2: 'def',
|
|
|
|
},
|
|
|
|
);
|
2019-07-27 19:21:57 -04:00
|
|
|
|
|
|
|
return expect(chartClient.loadDatasource('1__table')).resolves.toEqual({
|
2018-12-12 16:18:27 -05:00
|
|
|
field1: 'abc',
|
|
|
|
field2: 'def',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.loadAnnotation(annotationLayer)', () => {
|
|
|
|
it('returns an empty object if the annotation layer does not require query', () =>
|
|
|
|
expect(
|
|
|
|
chartClient.loadAnnotation({
|
|
|
|
name: 'my-annotation',
|
|
|
|
}),
|
|
|
|
).resolves.toEqual({}));
|
|
|
|
it('otherwise returns a rejected promise because it is not implemented yet', () =>
|
|
|
|
expect(
|
|
|
|
chartClient.loadAnnotation({
|
|
|
|
name: 'my-annotation',
|
|
|
|
sourceType: 'abc',
|
|
|
|
}),
|
|
|
|
).rejects.toEqual(new Error('This feature is not implemented yet.')));
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.loadAnnotations(annotationLayers)', () => {
|
|
|
|
it('loads multiple annotation layers and combine results', () =>
|
|
|
|
expect(
|
|
|
|
chartClient.loadAnnotations([
|
|
|
|
{
|
|
|
|
name: 'anno1',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'anno2',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'anno3',
|
|
|
|
},
|
|
|
|
]),
|
|
|
|
).resolves.toEqual({
|
|
|
|
anno1: {},
|
|
|
|
anno2: {},
|
|
|
|
anno3: {},
|
|
|
|
}));
|
|
|
|
it('returns an empty object if input is not an array', () =>
|
|
|
|
expect(chartClient.loadAnnotations()).resolves.toEqual({}));
|
|
|
|
it('returns an empty object if input is an empty array', () =>
|
|
|
|
expect(chartClient.loadAnnotations()).resolves.toEqual({}));
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.loadChartData({ sliceId, formData })', () => {
|
2018-12-13 20:15:23 -05:00
|
|
|
const sliceId = 10120;
|
2018-12-12 16:18:27 -05:00
|
|
|
it('loadAllDataNecessaryForAChart', () => {
|
2020-05-29 20:33:39 -04:00
|
|
|
fetchMock.get(`glob:*/api/v1/form_data/?slice_id=${sliceId}`, {
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'line',
|
|
|
|
datasource: '1__table',
|
|
|
|
color: 'living-coral',
|
2018-12-12 16:18:27 -05:00
|
|
|
});
|
|
|
|
|
2021-11-09 07:42:28 -05:00
|
|
|
fetchMock.get(
|
|
|
|
'glob:*/superset/fetch_datasource_metadata?datasourceKey=1__table',
|
|
|
|
{
|
|
|
|
name: 'transactions',
|
|
|
|
schema: 'staging',
|
|
|
|
},
|
|
|
|
);
|
2018-12-12 16:18:27 -05:00
|
|
|
|
2020-05-29 20:33:39 -04:00
|
|
|
fetchMock.post('glob:*/api/v1/chart/data', {
|
2018-12-12 16:18:27 -05:00
|
|
|
lorem: 'ipsum',
|
|
|
|
dolor: 'sit',
|
|
|
|
amet: true,
|
|
|
|
});
|
|
|
|
|
2019-03-22 14:40:23 -04:00
|
|
|
getChartMetadataRegistry().registerValue(
|
|
|
|
'line',
|
|
|
|
new ChartMetadata({ name: 'Line', thumbnail: '.gif' }),
|
|
|
|
);
|
2019-03-19 17:58:20 -04:00
|
|
|
|
2021-11-09 07:42:28 -05:00
|
|
|
getChartBuildQueryRegistry().registerValue(
|
|
|
|
'line',
|
|
|
|
(formData: QueryFormData) => buildQueryContext(formData),
|
2018-12-12 16:18:27 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
return expect(
|
|
|
|
chartClient.loadChartData({
|
2018-12-13 20:15:23 -05:00
|
|
|
sliceId,
|
2018-12-12 16:18:27 -05:00
|
|
|
}),
|
|
|
|
).resolves.toEqual({
|
|
|
|
annotationData: {},
|
|
|
|
datasource: {
|
|
|
|
name: 'transactions',
|
|
|
|
schema: 'staging',
|
|
|
|
},
|
|
|
|
formData: {
|
|
|
|
granularity: 'minute',
|
|
|
|
viz_type: 'line',
|
|
|
|
datasource: '1__table',
|
|
|
|
color: 'living-coral',
|
|
|
|
},
|
2020-12-29 05:10:39 -05:00
|
|
|
queriesData: [
|
|
|
|
{
|
|
|
|
lorem: 'ipsum',
|
|
|
|
dolor: 'sit',
|
|
|
|
amet: true,
|
|
|
|
},
|
|
|
|
],
|
2018-12-12 16:18:27 -05:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|