diff --git a/superset-frontend/jest.config.js b/superset-frontend/jest.config.js index 18d20a1f97..0d66ade8b3 100644 --- a/superset-frontend/jest.config.js +++ b/superset-frontend/jest.config.js @@ -47,7 +47,7 @@ module.exports = { 'tmp/', 'dist/', ], - coverageReporters: ['lcov', 'json-summary', 'html'], + coverageReporters: ['lcov', 'json-summary', 'html', 'text'], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], snapshotSerializers: ['@emotion/jest/enzyme-serializer'], globals: { diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/types.ts b/superset-frontend/packages/superset-ui-chart-controls/src/types.ts index a7bd128be9..431450f142 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/types.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/types.ts @@ -17,17 +17,17 @@ * specific language governing permissions and limitations * under the License. */ -import React, { ReactNode, ReactText, ReactElement } from 'react'; +import React, { ReactElement, ReactNode, ReactText } from 'react'; import type { AdhocColumn, Column, DatasourceType, JsonValue, Metric, - QueryFormData, - QueryResponse, - QueryFormMetric, QueryFormColumn, + QueryFormData, + QueryFormMetric, + QueryResponse, } from '@superset-ui/core'; import { sharedControls } from './shared-controls'; import sharedControlComponents from './shared-controls/components'; @@ -437,3 +437,19 @@ export function isControlPanelSectionConfig( ): section is ControlPanelSectionConfig { return section !== null; } + +export function isDataset( + datasource: Dataset | QueryResponse | null | undefined, +): datasource is Dataset { + return !!datasource && 'columns' in datasource; +} + +export function isQueryResponse( + datasource: Dataset | QueryResponse | null | undefined, +): datasource is QueryResponse { + return ( + !!datasource && + ('results' in datasource || + datasource?.type === ('query' as DatasourceType.Query)) + ); +} diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/utils/columnChoices.ts b/superset-frontend/packages/superset-ui-chart-controls/src/utils/columnChoices.ts index 0387717ff7..fd4e1fb512 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/utils/columnChoices.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/utils/columnChoices.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { QueryResponse } from '@superset-ui/core'; -import { Dataset } from '../types'; +import { ensureIsArray, QueryResponse } from '@superset-ui/core'; +import { Dataset, isColumnMeta, isDataset, isQueryResponse } from '../types'; /** * Convert Datasource columns to column choices @@ -25,23 +25,24 @@ import { Dataset } from '../types'; export default function columnChoices( datasource?: Dataset | QueryResponse | null, ): [string, string][] { - if (datasource?.columns[0]?.hasOwnProperty('column_name')) { - return ( - (datasource as Dataset)?.columns - .map((col): [string, string] => [ - col.column_name, - col.verbose_name || col.column_name, - ]) - .sort((opt1, opt2) => - opt1[1].toLowerCase() > opt2[1].toLowerCase() ? 1 : -1, - ) || [] - ); + if (isDataset(datasource) && isColumnMeta(datasource.columns[0])) { + return datasource.columns + .map((col): [string, string] => [ + col.column_name, + col.verbose_name || col.column_name, + ]) + .sort((opt1, opt2) => + opt1[1].toLowerCase() > opt2[1].toLowerCase() ? 1 : -1, + ); } - return ( - (datasource as QueryResponse)?.columns + + if (isQueryResponse(datasource)) { + return ensureIsArray(datasource.columns) .map((col): [string, string] => [col.name, col.name]) .sort((opt1, opt2) => opt1[1].toLowerCase() > opt2[1].toLowerCase() ? 1 : -1, - ) || [] - ); + ); + } + + return []; } diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/utils/defineSavedMetrics.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/utils/defineSavedMetrics.test.tsx index 59036bf604..48b000ed17 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/utils/defineSavedMetrics.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/utils/defineSavedMetrics.test.tsx @@ -26,30 +26,31 @@ import { defineSavedMetrics } from '@superset-ui/chart-controls'; describe('defineSavedMetrics', () => { it('defines saved metrics if source is a Dataset', () => { - expect( - defineSavedMetrics({ - id: 1, - metrics: [ - { - metric_name: 'COUNT(*) non-default-dataset-metric', - expression: 'COUNT(*) non-default-dataset-metric', - }, - ], - type: DatasourceType.Table, - main_dttm_col: 'test', - time_grain_sqla: 'P1D', - columns: [], - verbose_map: {}, - column_format: {}, - datasource_name: 'my_datasource', - description: 'this is my datasource', - }), - ).toEqual([ + const dataset = { + id: 1, + metrics: [ + { + metric_name: 'COUNT(*) non-default-dataset-metric', + expression: 'COUNT(*) non-default-dataset-metric', + }, + ], + type: DatasourceType.Table, + main_dttm_col: 'test', + time_grain_sqla: 'P1D', + columns: [], + verbose_map: {}, + column_format: {}, + datasource_name: 'my_datasource', + description: 'this is my datasource', + }; + expect(defineSavedMetrics(dataset)).toEqual([ { metric_name: 'COUNT(*) non-default-dataset-metric', expression: 'COUNT(*) non-default-dataset-metric', }, ]); + // @ts-ignore + expect(defineSavedMetrics({ ...dataset, metrics: undefined })).toEqual([]); }); it('returns default saved metrics if souce is a Query', () => { diff --git a/superset-frontend/packages/superset-ui-core/src/index.ts b/superset-frontend/packages/superset-ui-core/src/index.ts index 2a53112f6f..4d3c4b7c95 100644 --- a/superset-frontend/packages/superset-ui-core/src/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/index.ts @@ -22,7 +22,6 @@ export * from './utils'; export * from './types'; export * from './translation'; export * from './connection'; -export * from './dashboard'; export * from './dynamic-plugins'; export * from './query'; export * from './number-format'; diff --git a/superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts similarity index 99% rename from superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts rename to superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts index af7ca34dde..4089512de4 100644 --- a/superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts @@ -127,3 +127,5 @@ export type DashboardComponentMetadata = { nativeFilters: NativeFiltersState; dataMask: DataMaskStateWithId; }; + +export default {}; diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts index d4b672a7a3..bcbedf536b 100644 --- a/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts @@ -362,16 +362,16 @@ export const testQuery: Query = { type: DatasourceType.Query, is_dttm: false, }, - { - name: 'Column 2', - type: DatasourceType.Query, - is_dttm: true, - }, { name: 'Column 3', type: DatasourceType.Query, is_dttm: false, }, + { + name: 'Column 2', + type: DatasourceType.Query, + is_dttm: true, + }, ], }; diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/index.ts b/superset-frontend/packages/superset-ui-core/src/query/types/index.ts index 2ee4427efd..9c4b17edd8 100644 --- a/superset-frontend/packages/superset-ui-core/src/query/types/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/types/index.ts @@ -27,6 +27,7 @@ export * from './QueryResponse'; export * from './Time'; export * from './AdvancedAnalytics'; export * from './PostProcessing'; +export * from './Dashboard'; export { default as __hack_reexport_Datasource } from './Datasource'; export { default as __hack_reexport_Column } from './Column'; @@ -36,5 +37,6 @@ export { default as __hack_reexport_QueryResponse } from './QueryResponse'; export { default as __hack_reexport_QueryFormData } from './QueryFormData'; export { default as __hack_reexport_Time } from './Time'; export { default as __hack_reexport_AdvancedAnalytics } from './AdvancedAnalytics'; +export { default as __hack_reexport_Dashboard } from './Dashboard'; export default {}; diff --git a/superset-frontend/packages/superset-ui-core/test/query/types/Dashboard.test.ts b/superset-frontend/packages/superset-ui-core/test/query/types/Dashboard.test.ts new file mode 100644 index 0000000000..ea6236338c --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/test/query/types/Dashboard.test.ts @@ -0,0 +1,47 @@ +/** + * 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 { + isNativeFilter, + isFilterDivider, + Filter, + NativeFilterType, +} from '@superset-ui/core'; + +test('should do native filter type guard', () => { + const dummyFilter: Filter = { + cascadeParentIds: [], + defaultDataMask: {}, + id: 'dummyID', + name: 'dummyName', + scope: { rootPath: [], excluded: [] }, + filterType: 'dummyType', + targets: [{}], + controlValues: {}, + type: NativeFilterType.NATIVE_FILTER, + description: 'dummyDesc', + }; + expect(isNativeFilter(dummyFilter)).toBeTruthy(); + expect( + isFilterDivider({ + ...dummyFilter, + type: NativeFilterType.DIVIDER, + title: 'dummyTitle', + }), + ).toBeTruthy(); +}); diff --git a/superset-frontend/packages/superset-ui-core/src/dashboard/index.ts b/superset-frontend/packages/superset-ui-core/test/ui-overrides/UiOverrideRegistry.test.ts similarity index 80% rename from superset-frontend/packages/superset-ui-core/src/dashboard/index.ts rename to superset-frontend/packages/superset-ui-core/test/ui-overrides/UiOverrideRegistry.test.ts index 10b785cba8..6e44055141 100644 --- a/superset-frontend/packages/superset-ui-core/src/dashboard/index.ts +++ b/superset-frontend/packages/superset-ui-core/test/ui-overrides/UiOverrideRegistry.test.ts @@ -16,5 +16,8 @@ * specific language governing permissions and limitations * under the License. */ +import { getUiOverrideRegistry } from '@superset-ui/core'; -export * from './types/Base'; +test('should get instance of getUiOverrideRegistry', () => { + expect(getUiOverrideRegistry().name).toBe('UiOverrideRegistry'); +});