mirror of
https://github.com/apache/superset.git
synced 2026-04-17 15:15:20 +00:00
refactor(charts): filter saved metrics by key and label (#37136)
This commit is contained in:
committed by
GitHub
parent
3b75af9ac3
commit
82d6076804
@@ -17,7 +17,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { render, fireEvent } from 'spec/helpers/testing-library';
|
||||
import {
|
||||
render,
|
||||
fireEvent,
|
||||
screen,
|
||||
userEvent,
|
||||
within,
|
||||
} from 'spec/helpers/testing-library';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import ColumnSelectPopover, {
|
||||
@@ -116,3 +122,123 @@ test('open with Custom SQL tab selected when there is a custom SQL selected', ()
|
||||
expect(getByText('Simple')).toHaveAttribute('aria-selected', 'false');
|
||||
expect(getByText('Custom SQL')).toHaveAttribute('aria-selected', 'true');
|
||||
});
|
||||
|
||||
test('Should filter simple columns by column_name and verbose_name', async () => {
|
||||
renderPopover({
|
||||
columns: [
|
||||
{ column_name: 'revenue_amount', verbose_name: 'Total Sales' },
|
||||
{ column_name: 'user_id', verbose_name: 'User Identifier' },
|
||||
{ column_name: 'created_at', verbose_name: 'Creation Date' },
|
||||
{ column_name: 'order_status', verbose_name: 'Status' },
|
||||
{ column_name: 'updated_at', verbose_name: 'Last Update' },
|
||||
],
|
||||
editedColumn: undefined,
|
||||
getCurrentTab: jest.fn(),
|
||||
onChange: jest.fn(),
|
||||
});
|
||||
|
||||
const combobox = screen.getByRole('combobox', {
|
||||
name: 'Columns and metrics',
|
||||
});
|
||||
|
||||
await userEvent.type(combobox, 'revenue');
|
||||
|
||||
let dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Total Sales')).toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('User Identifier'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Creation Date')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Status')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Last Update')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(combobox);
|
||||
await userEvent.type(combobox, 'Identifier');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('User Identifier')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Total Sales')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Creation Date')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(combobox);
|
||||
await userEvent.type(combobox, '_at');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Creation Date')).toBeInTheDocument();
|
||||
expect(within(dropdown).getByText('Last Update')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Total Sales')).not.toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('User Identifier'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Status')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should filter saved expressions by column_name and verbose_name', async () => {
|
||||
const { container } = renderPopover({
|
||||
columns: [
|
||||
{
|
||||
column_name: 'calc_revenue',
|
||||
verbose_name: 'Total Sales',
|
||||
expression: 'price * quantity',
|
||||
},
|
||||
{
|
||||
column_name: 'calc_tax',
|
||||
verbose_name: 'Tax Amount',
|
||||
expression: 'price * 0.1',
|
||||
},
|
||||
{
|
||||
column_name: 'calc_profit',
|
||||
verbose_name: 'Net Profit',
|
||||
expression: 'revenue - cost',
|
||||
},
|
||||
{
|
||||
column_name: 'calc_margin',
|
||||
verbose_name: 'Profit Margin',
|
||||
expression: 'profit / revenue',
|
||||
},
|
||||
{
|
||||
column_name: 'calc_discount',
|
||||
verbose_name: 'Discount Rate',
|
||||
expression: 'discount / price',
|
||||
},
|
||||
],
|
||||
editedColumn: undefined,
|
||||
getCurrentTab: jest.fn(),
|
||||
onChange: jest.fn(),
|
||||
});
|
||||
|
||||
const savedTab = container.querySelector('#adhoc-metric-edit-tabs-tab-saved');
|
||||
expect(savedTab).not.toBeNull();
|
||||
fireEvent.click(savedTab!);
|
||||
|
||||
const combobox = screen.getByRole('combobox', {
|
||||
name: 'Saved expressions',
|
||||
});
|
||||
|
||||
await userEvent.type(combobox, 'revenue');
|
||||
|
||||
let dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Total Sales')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Tax Amount')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Net Profit')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Profit Margin')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Discount Rate')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(combobox);
|
||||
await userEvent.type(combobox, 'Rate');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Discount Rate')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Total Sales')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Tax Amount')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(combobox);
|
||||
await userEvent.type(combobox, 'profit');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Net Profit')).toBeInTheDocument();
|
||||
expect(within(dropdown).getByText('Profit Margin')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Total Sales')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Tax Amount')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Discount Rate')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -427,8 +427,12 @@ const ColumnSelectPopover = ({
|
||||
/>
|
||||
),
|
||||
key: calculatedColumn.column_name,
|
||||
column_name: calculatedColumn.column_name,
|
||||
verbose_name:
|
||||
calculatedColumn.verbose_name ?? '',
|
||||
}),
|
||||
)}
|
||||
optionFilterProps={['column_name', 'verbose_name']}
|
||||
/>
|
||||
</FormItem>
|
||||
) : datasourceType === DatasourceType.Table ? (
|
||||
@@ -544,6 +548,8 @@ const ColumnSelectPopover = ({
|
||||
/>
|
||||
),
|
||||
key: `column-${simpleColumn.column_name}`,
|
||||
column_name: simpleColumn.column_name,
|
||||
verbose_name: simpleColumn.verbose_name ?? '',
|
||||
})),
|
||||
...availableMetrics.map(metric => ({
|
||||
value: metric.metric_name,
|
||||
@@ -556,8 +562,15 @@ const ColumnSelectPopover = ({
|
||||
</MetricOptionContainer>
|
||||
),
|
||||
key: `metric-${metric.metric_name}`,
|
||||
metric_name: metric.metric_name,
|
||||
verbose_name: metric.verbose_name ?? '',
|
||||
})),
|
||||
]}
|
||||
optionFilterProps={[
|
||||
'column_name',
|
||||
'verbose_name',
|
||||
'metric_name',
|
||||
]}
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
screen,
|
||||
selectOption,
|
||||
userEvent,
|
||||
within,
|
||||
} from 'spec/helpers/testing-library';
|
||||
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
||||
import AdhocMetricEditPopover from '.';
|
||||
@@ -248,3 +249,160 @@ test('Should render "Custom SQL" tab correctly', async () => {
|
||||
|
||||
expect(await screen.findByRole('textbox')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should filter saved metrics by metric_name and verbose_name', async () => {
|
||||
const props = {
|
||||
...createProps(),
|
||||
savedMetricsOptions: [
|
||||
{
|
||||
id: 1,
|
||||
metric_name: 'count',
|
||||
expression: 'COUNT(*)',
|
||||
verbose_name: 'Total Count',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
metric_name: 'revenue_sum',
|
||||
expression: 'sum(revenue)',
|
||||
verbose_name: 'Gross Revenue',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
metric_name: 'avg_price',
|
||||
expression: 'AVG(price)',
|
||||
verbose_name: 'Average Price',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
metric_name: 'user_count',
|
||||
expression: 'COUNT(DISTINCT user_id)',
|
||||
verbose_name: 'Unique Users',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
metric_name: 'total_quantity',
|
||||
expression: 'SUM(quantity)',
|
||||
verbose_name: 'Total Quantity',
|
||||
},
|
||||
],
|
||||
};
|
||||
render(<AdhocMetricEditPopover {...props} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox', {
|
||||
name: 'Select saved metrics',
|
||||
});
|
||||
userEvent.click(combobox);
|
||||
|
||||
await userEvent.type(combobox, 'revenue');
|
||||
|
||||
let dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Gross Revenue')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Total Count')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Average Price')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Unique Users')).not.toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('Total Quantity'),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(combobox);
|
||||
await userEvent.type(combobox, 'Unique');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Unique Users')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Total Count')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Gross Revenue')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(combobox);
|
||||
await userEvent.type(combobox, 'total');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Total Count')).toBeInTheDocument();
|
||||
expect(within(dropdown).getByText('Total Quantity')).toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Gross Revenue')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Average Price')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Unique Users')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should filter columns by column_name and verbose_name in Simple tab', async () => {
|
||||
const props = {
|
||||
...createProps(),
|
||||
columns: [
|
||||
{
|
||||
id: 1,
|
||||
column_name: 'user_id',
|
||||
verbose_name: 'User Identifier',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
column_name: 'created_at',
|
||||
verbose_name: 'Creation Timestamp',
|
||||
type: 'DATETIME',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
column_name: 'order_total',
|
||||
verbose_name: 'Order Amount',
|
||||
type: 'DECIMAL',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
column_name: 'product_name',
|
||||
verbose_name: 'Product Title',
|
||||
type: 'STRING',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
column_name: 'updated_at',
|
||||
verbose_name: 'Last Modified',
|
||||
type: 'DATETIME',
|
||||
},
|
||||
],
|
||||
};
|
||||
props.getCurrentTab.mockImplementation(tab => {
|
||||
props.adhocMetric.expressionType = tab;
|
||||
});
|
||||
render(<AdhocMetricEditPopover {...props} />);
|
||||
|
||||
const tab = screen.getByRole('tab', { name: 'Simple' }).parentElement!;
|
||||
userEvent.click(tab);
|
||||
|
||||
const columnCombobox = screen.getByRole('combobox', {
|
||||
name: 'Select column',
|
||||
});
|
||||
|
||||
await userEvent.type(columnCombobox, 'product');
|
||||
|
||||
let dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Product Title')).toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('User Identifier'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('Creation Timestamp'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Order Amount')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Last Modified')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(columnCombobox);
|
||||
await userEvent.type(columnCombobox, 'Modified');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Last Modified')).toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('User Identifier'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Product Title')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.clear(columnCombobox);
|
||||
await userEvent.type(columnCombobox, '_at');
|
||||
|
||||
dropdown = document.querySelector('.rc-virtual-list') as HTMLElement;
|
||||
expect(within(dropdown).getByText('Creation Timestamp')).toBeInTheDocument();
|
||||
expect(within(dropdown).getByText('Last Modified')).toBeInTheDocument();
|
||||
expect(
|
||||
within(dropdown).queryByText('User Identifier'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Order Amount')).not.toBeInTheDocument();
|
||||
expect(within(dropdown).queryByText('Product Title')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -450,8 +450,11 @@ export default class AdhocMetricEditPopover extends PureComponent<
|
||||
value: savedMetric.metric_name,
|
||||
label: this.renderMetricOption(savedMetric),
|
||||
key: savedMetric.id,
|
||||
metric_name: savedMetric.metric_name,
|
||||
verbose_name: savedMetric.verbose_name ?? '',
|
||||
}),
|
||||
)}
|
||||
optionFilterProps={['metric_name', 'verbose_name']}
|
||||
{...savedSelectProps}
|
||||
/>
|
||||
</FormItem>
|
||||
@@ -509,7 +512,10 @@ export default class AdhocMetricEditPopover extends PureComponent<
|
||||
value: column.column_name,
|
||||
key: (column as { id?: unknown }).id,
|
||||
label: this.renderColumnOption(column),
|
||||
column_name: column.column_name,
|
||||
verbose_name: column.verbose_name ?? '',
|
||||
}))}
|
||||
optionFilterProps={['column_name', 'verbose_name']}
|
||||
{...columnSelectProps}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
Reference in New Issue
Block a user