From 62a808bf1fefec3ead2c5f89130340120d2f70de Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Mon, 9 Sep 2019 02:29:37 -0700 Subject: [PATCH] MixedDataSource: refactor, cleanup, and add tests (#18948) * merge master * move mixed datasource * all responses in test * fix tests/mocks * remove ? --- .../datasource/mixed/MixedDataSource.test.ts | 35 ++++++++++ .../datasource/mixed/MixedDataSource.ts | 67 +++++++++++++++++++ .../plugins/datasource/mixed/datasource.ts | 51 -------------- public/app/plugins/datasource/mixed/module.ts | 2 +- public/test/mocks/datasource_srv.ts | 10 ++- 5 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 public/app/plugins/datasource/mixed/MixedDataSource.test.ts create mode 100644 public/app/plugins/datasource/mixed/MixedDataSource.ts delete mode 100644 public/app/plugins/datasource/mixed/datasource.ts diff --git a/public/app/plugins/datasource/mixed/MixedDataSource.test.ts b/public/app/plugins/datasource/mixed/MixedDataSource.test.ts new file mode 100644 index 00000000000..3d25daee15f --- /dev/null +++ b/public/app/plugins/datasource/mixed/MixedDataSource.test.ts @@ -0,0 +1,35 @@ +import { DatasourceSrvMock, MockDataSourceApi } from 'test/mocks/datasource_srv'; +import { getDataSourceSrv } from '@grafana/runtime'; +import { getQueryOptions } from 'test/helpers/getQueryOptions'; +import { DataSourceInstanceSettings } from '@grafana/ui'; +import { MixedDatasource } from './module'; + +const defaultDS = new MockDataSourceApi('DefaultDS', { data: ['DDD'] }); +const datasourceSrv = new DatasourceSrvMock(defaultDS, { + '-- Mixed --': new MixedDatasource({ name: 'mixed', id: 5 } as DataSourceInstanceSettings), + A: new MockDataSourceApi('DSA', { data: ['AAAA'] }), + B: new MockDataSourceApi('DSB', { data: ['BBBB'] }), + C: new MockDataSourceApi('DSC', { data: ['CCCC'] }), +}); + +jest.mock('@grafana/runtime', () => ({ + getDataSourceSrv: () => { + return datasourceSrv; + }, +})); + +describe('MixedDatasource', () => { + const requestMixed = getQueryOptions({ + targets: [ + { refId: 'QA', datasource: 'A' }, // 1 + { refId: 'QB', datasource: 'B' }, // 2 + { refId: 'QC', datasource: 'C' }, // 3 + ], + }); + + it('direct query should return results', async () => { + const ds = await getDataSourceSrv().get('-- Mixed --'); + const res = await ds.query(requestMixed); + expect(res.data).toEqual(['AAAA', 'BBBB', 'CCCC']); + }); +}); diff --git a/public/app/plugins/datasource/mixed/MixedDataSource.ts b/public/app/plugins/datasource/mixed/MixedDataSource.ts new file mode 100644 index 00000000000..5462d1e11d9 --- /dev/null +++ b/public/app/plugins/datasource/mixed/MixedDataSource.ts @@ -0,0 +1,67 @@ +import cloneDeep from 'lodash/cloneDeep'; +import groupBy from 'lodash/groupBy'; +import map from 'lodash/map'; +import flatten from 'lodash/flatten'; +import filter from 'lodash/filter'; + +import { + DataSourceApi, + DataQuery, + DataQueryRequest, + DataQueryResponse, + DataStreamObserver, + DataSourceInstanceSettings, +} from '@grafana/ui'; + +import { getDataSourceSrv } from '@grafana/runtime'; + +export const MIXED_DATASOURCE_NAME = '-- Mixed --'; + +export class MixedDatasource extends DataSourceApi { + constructor(instanceSettings: DataSourceInstanceSettings) { + super(instanceSettings); + } + + async query(request: DataQueryRequest, observer: DataStreamObserver): Promise { + // Remove any invalid queries + const queries = request.targets.filter(t => { + return t.datasource !== MIXED_DATASOURCE_NAME; + }); + + if (!queries.length) { + return Promise.resolve({ data: [] }); // nothing + } + + const sets = groupBy(queries, 'datasource'); + + const promises = map(sets, (targets: DataQuery[]) => { + const dsName = targets[0].datasource; + return getDataSourceSrv() + .get(dsName) + .then((ds: DataSourceApi) => { + const opt = cloneDeep(request); + + // Remove any unused hidden queries + if (!ds.meta.hiddenQueries) { + targets = filter(targets, (t: DataQuery) => { + return !t.hide; + }); + if (targets.length === 0) { + return { data: [] }; + } + } + + opt.targets = targets; + return ds.query(opt); + }); + }); + + return Promise.all(promises).then(results => { + return { data: flatten(map(results, 'data')) }; + }); + } + + testDatasource() { + return Promise.resolve({}); + } +} diff --git a/public/app/plugins/datasource/mixed/datasource.ts b/public/app/plugins/datasource/mixed/datasource.ts deleted file mode 100644 index 81cf381d75d..00000000000 --- a/public/app/plugins/datasource/mixed/datasource.ts +++ /dev/null @@ -1,51 +0,0 @@ -import _ from 'lodash'; - -import { DataSourceApi, DataQuery, DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui'; -import DatasourceSrv from 'app/features/plugins/datasource_srv'; - -class MixedDatasource extends DataSourceApi { - /** @ngInject */ - constructor(instanceSettings: DataSourceInstanceSettings, private datasourceSrv: DatasourceSrv) { - super(instanceSettings); - } - - query(options: DataQueryRequest) { - const sets = _.groupBy(options.targets, 'datasource'); - const promises: any = _.map(sets, (targets: DataQuery[]) => { - const dsName = targets[0].datasource; - if (dsName === '-- Mixed --') { - return Promise.resolve([]); - } - - if (targets.length === 0) { - return { data: [] }; - } - - return this.datasourceSrv.get(dsName).then(ds => { - // Remove any unused hidden queries - if (!ds.meta.hiddenQueries) { - targets = _.filter(targets, (t: DataQuery) => { - return !t.hide; - }); - if (targets.length === 0) { - return { data: [] }; - } - } - - const opt = _.cloneDeep(options); - opt.targets = targets; - return ds.query(opt); - }); - }); - - return Promise.all(promises).then(results => { - return { data: _.flatten(_.map(results, 'data')) }; - }); - } - - testDatasource() { - return Promise.resolve({}); - } -} - -export { MixedDatasource, MixedDatasource as Datasource }; diff --git a/public/app/plugins/datasource/mixed/module.ts b/public/app/plugins/datasource/mixed/module.ts index 6ae72be9a45..59fd1aed795 100644 --- a/public/app/plugins/datasource/mixed/module.ts +++ b/public/app/plugins/datasource/mixed/module.ts @@ -1,2 +1,2 @@ -import { MixedDatasource } from './datasource'; +import { MixedDatasource } from './MixedDataSource'; export { MixedDatasource, MixedDatasource as Datasource }; diff --git a/public/test/mocks/datasource_srv.ts b/public/test/mocks/datasource_srv.ts index 5c4d8944cb6..3f71bfda4d2 100644 --- a/public/test/mocks/datasource_srv.ts +++ b/public/test/mocks/datasource_srv.ts @@ -1,4 +1,10 @@ -import { DataSourceApi, DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/ui'; +import { + DataSourceApi, + DataQueryRequest, + DataQueryResponse, + DataSourceInstanceSettings, + DataSourcePluginMeta, +} from '@grafana/ui'; export class DatasourceSrvMock { constructor(private defaultDS: DataSourceApi, private datasources: { [name: string]: DataSourceApi }) { @@ -26,6 +32,8 @@ export class MockDataSourceApi extends DataSourceApi { if (result) { this.result = result; } + + this.meta = {} as DataSourcePluginMeta; } query(request: DataQueryRequest): Promise {