mirror of
https://github.com/apache/superset.git
synced 2026-07-12 09:45:43 +00:00
267 lines
7.7 KiB
TypeScript
267 lines
7.7 KiB
TypeScript
/**
|
||
* 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 transformProps from '../src/transformProps';
|
||
import { TableChartProps } from '../src/types';
|
||
import { GenericDataType } from '@apache-superset/core/common';
|
||
import { QueryMode } from '@superset-ui/core';
|
||
|
||
function createMockChartProps(
|
||
overrides: Partial<TableChartProps> = {},
|
||
): TableChartProps {
|
||
const defaultProps = {
|
||
height: 400,
|
||
width: 800,
|
||
rawFormData: {
|
||
viz_type: 'table',
|
||
datasource: '1__table',
|
||
query_mode: QueryMode.Aggregate,
|
||
metrics: [],
|
||
percent_metrics: [],
|
||
column_config: {},
|
||
table_timestamp_format: '',
|
||
granularity_sqla: 'day',
|
||
time_range: 'No filter',
|
||
},
|
||
queriesData: [
|
||
{
|
||
data: [],
|
||
colnames: [],
|
||
coltypes: [],
|
||
rowcount: 0,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
},
|
||
],
|
||
datasource: {
|
||
columns: [],
|
||
metrics: [],
|
||
columnFormats: {},
|
||
currencyFormats: {},
|
||
verboseMap: {},
|
||
},
|
||
rawDatasource: {
|
||
columns: [],
|
||
metrics: [],
|
||
},
|
||
filterState: {},
|
||
hooks: { setDataMask: jest.fn(), onChartStateChange: jest.fn() },
|
||
ownState: {},
|
||
emitCrossFilters: false,
|
||
theme: {},
|
||
...overrides,
|
||
};
|
||
return defaultProps as unknown as TableChartProps;
|
||
}
|
||
|
||
test('extracts description from datasource.columns for a regular column', () => {
|
||
const props = createMockChartProps({
|
||
queriesData: [
|
||
{
|
||
data: [{ col1: 'value' }],
|
||
colnames: ['col1'],
|
||
coltypes: [GenericDataType.String],
|
||
rowcount: 1,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
} as unknown as TableChartProps['queriesData'][number],
|
||
],
|
||
rawDatasource: {
|
||
columns: [
|
||
{ column_name: 'col1', description: 'This is a column description' },
|
||
],
|
||
metrics: [],
|
||
},
|
||
});
|
||
|
||
const result = transformProps(props);
|
||
const { columns } = result;
|
||
const columnMeta = columns.find(c => c.key === 'col1');
|
||
expect(columnMeta).toBeDefined();
|
||
expect(columnMeta!.description).toBe('This is a column description');
|
||
});
|
||
|
||
test('extracts description from datasource.metrics for a metric column', () => {
|
||
const props = createMockChartProps({
|
||
rawFormData: {
|
||
viz_type: 'table',
|
||
datasource: '1__table',
|
||
query_mode: QueryMode.Aggregate,
|
||
metrics: ['sum_sales'],
|
||
percent_metrics: [],
|
||
column_config: {},
|
||
table_timestamp_format: '',
|
||
granularity_sqla: 'day',
|
||
time_range: 'No filter',
|
||
},
|
||
queriesData: [
|
||
{
|
||
data: [{ sum_sales: 100 }],
|
||
colnames: ['sum_sales'],
|
||
coltypes: [GenericDataType.Numeric],
|
||
rowcount: 1,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
},
|
||
] as unknown as TableChartProps['queriesData'],
|
||
rawDatasource: {
|
||
columns: [],
|
||
metrics: [
|
||
{ metric_name: 'sum_sales', description: 'Total sales amount' },
|
||
],
|
||
},
|
||
});
|
||
|
||
const result = transformProps(props);
|
||
const { columns } = result;
|
||
const columnMeta = columns.find(c => c.key === 'sum_sales');
|
||
expect(columnMeta).toBeDefined();
|
||
expect(columnMeta!.description).toBe('Total sales amount');
|
||
});
|
||
|
||
test('prefers column description over metric description when both exist with same key', () => {
|
||
const props = createMockChartProps({
|
||
rawFormData: {
|
||
viz_type: 'table',
|
||
datasource: '1__table',
|
||
query_mode: QueryMode.Aggregate,
|
||
metrics: ['revenue'],
|
||
percent_metrics: [],
|
||
column_config: {},
|
||
table_timestamp_format: '',
|
||
granularity_sqla: 'day',
|
||
time_range: 'No filter',
|
||
},
|
||
queriesData: [
|
||
{
|
||
data: [{ revenue: 500 }],
|
||
colnames: ['revenue'],
|
||
coltypes: [GenericDataType.Numeric],
|
||
rowcount: 1,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
},
|
||
] as unknown as TableChartProps['queriesData'],
|
||
rawDatasource: {
|
||
columns: [{ column_name: 'revenue', description: 'Column desc' }],
|
||
metrics: [{ metric_name: 'revenue', description: 'Metric desc' }],
|
||
},
|
||
});
|
||
|
||
const result = transformProps(props);
|
||
const { columns } = result;
|
||
const columnMeta = columns.find(c => c.key === 'revenue');
|
||
expect(columnMeta!.description).toBe('Column desc');
|
||
});
|
||
|
||
test('handles percent metrics correctly – uses base metric name for lookup', () => {
|
||
const props = createMockChartProps({
|
||
rawFormData: {
|
||
viz_type: 'table',
|
||
datasource: '1__table',
|
||
query_mode: QueryMode.Aggregate,
|
||
metrics: ['profit'],
|
||
percent_metrics: ['profit'],
|
||
column_config: {},
|
||
table_timestamp_format: '',
|
||
granularity_sqla: 'day',
|
||
time_range: 'No filter',
|
||
},
|
||
queriesData: [
|
||
{
|
||
data: [{ '%profit': 0.15 }],
|
||
colnames: ['%profit'],
|
||
coltypes: [GenericDataType.Numeric],
|
||
rowcount: 1,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
},
|
||
] as unknown as TableChartProps['queriesData'],
|
||
rawDatasource: {
|
||
columns: [],
|
||
metrics: [
|
||
{ metric_name: 'profit', description: 'Profit margin percent' },
|
||
],
|
||
},
|
||
});
|
||
|
||
const result = transformProps(props);
|
||
const { columns } = result;
|
||
const columnMeta = columns.find(c => c.key === '%profit');
|
||
expect(columnMeta).toBeDefined();
|
||
expect(columnMeta!.description).toBe('Profit margin percent');
|
||
});
|
||
|
||
test('sets description to undefined when no matching column or metric is found', () => {
|
||
const props = createMockChartProps({
|
||
queriesData: [
|
||
{
|
||
data: [{ unknown_col: 'x' }],
|
||
colnames: ['unknown_col'],
|
||
coltypes: [GenericDataType.String],
|
||
rowcount: 1,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
},
|
||
] as unknown as TableChartProps['queriesData'],
|
||
rawDatasource: {
|
||
columns: [],
|
||
metrics: [],
|
||
},
|
||
});
|
||
|
||
const result = transformProps(props);
|
||
const { columns } = result;
|
||
const columnMeta = columns.find(c => c.key === 'unknown_col');
|
||
expect(columnMeta!.description).toBeUndefined();
|
||
});
|
||
|
||
test('uses description from column even when verboseMap renames the column', () => {
|
||
const props = createMockChartProps({
|
||
queriesData: [
|
||
{
|
||
data: [{ col_x: 10 }],
|
||
colnames: ['col_x'],
|
||
coltypes: [GenericDataType.Numeric],
|
||
rowcount: 1,
|
||
applied_filters: [],
|
||
rejected_filters: [],
|
||
},
|
||
] as unknown as TableChartProps['queriesData'],
|
||
datasource: {
|
||
columns: [],
|
||
metrics: [],
|
||
columnFormats: {},
|
||
currencyFormats: {},
|
||
verboseMap: { col_x: 'Custom Label' },
|
||
} as unknown as TableChartProps['datasource'],
|
||
rawDatasource: {
|
||
columns: [
|
||
{ column_name: 'col_x', description: 'Original column description' },
|
||
],
|
||
metrics: [],
|
||
},
|
||
});
|
||
|
||
const result = transformProps(props);
|
||
const { columns } = result;
|
||
const columnMeta = columns.find(c => c.key === 'col_x');
|
||
expect(columnMeta!.label).toBe('Custom Label');
|
||
expect(columnMeta!.description).toBe('Original column description');
|
||
});
|