blob: 86635c754e24de571d4d56920005fcb342395f00 [file] [log] [blame]
import fetchMock from 'fetch-mock';
import {
SupersetClientClass,
SupersetClient,
buildQueryContext,
QueryFormData,
configure as configureTranslation,
} from '@superset-ui/core/src';
import {
ChartClient,
getChartBuildQueryRegistry,
getChartMetadataRegistry,
ChartMetadata,
} from '@superset-ui/core/src/chart';
import { SliceIdAndOrFormData } from '@superset-ui/core/src/chart/clients/ChartClient';
import { LOGIN_GLOB } from '../fixtures/constants';
import { sankeyFormData } from '../fixtures/formData';
configureTranslation();
describe('ChartClient', () => {
let chartClient: ChartClient;
beforeAll(() => {
fetchMock.get(LOGIN_GLOB, { csrf_token: '1234' });
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)', () => {
const sliceId = 123;
it('fetches formData if given only sliceId', () => {
fetchMock.get(`glob:*/api/v1/form_data/?slice_id=${sliceId}`, sankeyFormData);
return expect(chartClient.loadFormData({ sliceId })).resolves.toEqual(sankeyFormData);
});
it('fetches formData from sliceId and merges with specify formData if both fields are specified', () => {
fetchMock.get(`glob:*/api/v1/form_data/?slice_id=${sliceId}`, sankeyFormData);
return expect(
chartClient.loadFormData({
sliceId,
formData: {
granularity: 'second',
viz_type: 'bar',
},
}),
).resolves.toEqual({
...sankeyFormData,
granularity: 'second',
viz_type: 'bar',
});
});
it('returns promise of formData if only formData was given', () =>
expect(
chartClient.loadFormData({
formData: {
datasource: '1__table',
granularity: 'minute',
viz_type: 'line',
},
}),
).resolves.toEqual({
datasource: '1__table',
granularity: 'minute',
viz_type: 'line',
}));
it('rejects if none of sliceId or formData is specified', () =>
expect(chartClient.loadFormData({} as SliceIdAndOrFormData)).rejects.toEqual(
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', () => {
getChartMetadataRegistry().registerValue(
'word_cloud',
new ChartMetadata({ name: 'Word Cloud', thumbnail: '' }),
);
getChartBuildQueryRegistry().registerValue('word_cloud', (formData: QueryFormData) =>
buildQueryContext(formData),
);
fetchMock.post('glob:*/api/v1/chart/data', [
{
field1: 'abc',
field2: 'def',
},
]);
return expect(
chartClient.loadQueryData({
granularity: 'minute',
viz_type: 'word_cloud',
datasource: '1__table',
}),
).resolves.toEqual([
{
field1: 'abc',
field2: 'def',
},
]);
});
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')));
it('fetches data from the legacy API if ChartMetadata has useLegacyApi=true,', () => {
// note legacy charts do not register a buildQuery function in the registry
getChartMetadataRegistry().registerValue(
'word_cloud_legacy',
new ChartMetadata({
name: 'Legacy Word Cloud',
thumbnail: '.png',
useLegacyApi: true,
}),
);
fetchMock.post('glob:*/api/v1/chart/data', () =>
Promise.reject(new Error('Unexpected all to v1 API')),
);
fetchMock.post('glob:*/superset/explore_json/', {
field1: 'abc',
field2: 'def',
});
return expect(
chartClient.loadQueryData({
granularity: 'minute',
viz_type: 'word_cloud_legacy',
datasource: '1__table',
}),
).resolves.toEqual([
{
field1: 'abc',
field2: 'def',
},
]);
});
});
describe('.loadDatasource(datasourceKey, options)', () => {
it('fetches datasource', () => {
fetchMock.get('glob:*/superset/fetch_datasource_metadata?datasourceKey=1__table', {
field1: 'abc',
field2: 'def',
});
return expect(chartClient.loadDatasource('1__table')).resolves.toEqual({
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 })', () => {
const sliceId = 10120;
it('loadAllDataNecessaryForAChart', () => {
fetchMock.get(`glob:*/api/v1/form_data/?slice_id=${sliceId}`, {
granularity: 'minute',
viz_type: 'line',
datasource: '1__table',
color: 'living-coral',
});
fetchMock.get('glob:*/superset/fetch_datasource_metadata?datasourceKey=1__table', {
name: 'transactions',
schema: 'staging',
});
fetchMock.post('glob:*/api/v1/chart/data', {
lorem: 'ipsum',
dolor: 'sit',
amet: true,
});
getChartMetadataRegistry().registerValue(
'line',
new ChartMetadata({ name: 'Line', thumbnail: '.gif' }),
);
getChartBuildQueryRegistry().registerValue('line', (formData: QueryFormData) =>
buildQueryContext(formData),
);
return expect(
chartClient.loadChartData({
sliceId,
}),
).resolves.toEqual({
annotationData: {},
datasource: {
name: 'transactions',
schema: 'staging',
},
formData: {
granularity: 'minute',
viz_type: 'line',
datasource: '1__table',
color: 'living-coral',
},
queriesData: [
{
lorem: 'ipsum',
dolor: 'sit',
amet: true,
},
],
});
});
});
});