mirror of https://github.com/apache/superset.git
feat: chart gallery search improvement (#14484)
* feat: chart gallery search improvement * test: adding unit test for VizTypeControl * fix: lint errors Co-authored-by: einatnielsen <einat.bertenthal@nielsen.com>
This commit is contained in:
parent
63dc035d6a
commit
dfe030b835
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@import '../../../../stylesheets/less/variables.less';
|
||||
@import '../../../../../stylesheets/less/variables.less';
|
||||
|
||||
.viztype-label {
|
||||
margin-top: 10px;
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* 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 { Preset } from '@superset-ui/core';
|
||||
import { render, cleanup, screen } from 'spec/helpers/testing-library';
|
||||
import { Provider } from 'react-redux';
|
||||
import {
|
||||
getMockStore,
|
||||
mockStore,
|
||||
stateWithoutNativeFilters,
|
||||
} from 'spec/fixtures/mockStore';
|
||||
import React from 'react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { testWithId } from 'src/utils/testUtils';
|
||||
import {
|
||||
EchartsMixedTimeseriesChartPlugin,
|
||||
EchartsTimeseriesChartPlugin,
|
||||
} from '@superset-ui/plugin-chart-echarts/lib';
|
||||
import { LineChartPlugin } from '@superset-ui/preset-chart-xy/lib';
|
||||
import TimeTableChartPlugin from '../../../../visualizations/TimeTable/TimeTableChartPlugin';
|
||||
import VizTypeControl, { VIZ_TYPE_CONTROL_TEST_ID } from './index';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
class MainPreset extends Preset {
|
||||
constructor() {
|
||||
super({
|
||||
name: 'Legacy charts',
|
||||
plugins: [
|
||||
new LineChartPlugin().configure({ key: 'line' }),
|
||||
new EchartsTimeseriesChartPlugin().configure({
|
||||
key: 'echarts_timeseries',
|
||||
}),
|
||||
new TimeTableChartPlugin().configure({ key: 'time_table' }),
|
||||
new EchartsMixedTimeseriesChartPlugin().configure({
|
||||
key: 'mixed_timeseries',
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const getTestId = testWithId<string>(VIZ_TYPE_CONTROL_TEST_ID, true);
|
||||
|
||||
describe('VizTypeControl', () => {
|
||||
new MainPreset().register();
|
||||
const newVizTypeControlProps = {
|
||||
description: '',
|
||||
label: '',
|
||||
name: '',
|
||||
value: '',
|
||||
labelType: '',
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
|
||||
const renderWrapper = (
|
||||
props = newVizTypeControlProps,
|
||||
state: object = stateWithoutNativeFilters,
|
||||
) =>
|
||||
render(
|
||||
<Provider
|
||||
store={state ? getMockStore(stateWithoutNativeFilters) : mockStore}
|
||||
>
|
||||
<VizTypeControl {...props} />
|
||||
</Provider>,
|
||||
);
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('Search visualization type', async () => {
|
||||
renderWrapper();
|
||||
|
||||
const visualizations = screen.getByTestId(getTestId('viz-row'));
|
||||
|
||||
expect(visualizations).toHaveTextContent(/Time-series Table/);
|
||||
expect(visualizations).toHaveTextContent(/Time-series Chart/);
|
||||
expect(visualizations).toHaveTextContent(/Mixed timeseries chart/);
|
||||
expect(visualizations).toHaveTextContent(/Line Chart/);
|
||||
|
||||
const searchInputText = 'time series';
|
||||
|
||||
// search
|
||||
userEvent.type(
|
||||
screen.getByTestId(getTestId('search-input')),
|
||||
searchInputText,
|
||||
);
|
||||
|
||||
expect(visualizations).toHaveTextContent(/Time-series Table/);
|
||||
expect(visualizations).toHaveTextContent(/Time-series Chart/);
|
||||
expect(visualizations).toHaveTextContent(/Mixed timeseries chart/);
|
||||
expect(visualizations).not.toHaveTextContent(/Line Chart/);
|
||||
});
|
||||
});
|
|
@ -93,6 +93,8 @@ const DEFAULT_ORDER = [
|
|||
|
||||
const typesWithDefaultOrder = new Set(DEFAULT_ORDER);
|
||||
|
||||
export const VIZ_TYPE_CONTROL_TEST_ID = 'viz-type-control';
|
||||
|
||||
function VizSupportValidation({ vizType }) {
|
||||
const state = useDynamicPluginContext();
|
||||
if (state.loading || registry.has(vizType)) {
|
||||
|
@ -153,7 +155,10 @@ const VizTypeControl = props => {
|
|||
className={`viztype-selector ${isSelected ? 'selected' : ''}`}
|
||||
src={type.thumbnail}
|
||||
/>
|
||||
<div className="viztype-label" data-test="viztype-label">
|
||||
<div
|
||||
className="viztype-label"
|
||||
data-test={`${VIZ_TYPE_CONTROL_TEST_ID}__viztype-label`}
|
||||
>
|
||||
{type.name}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -162,8 +167,10 @@ const VizTypeControl = props => {
|
|||
|
||||
const { value, labelType } = props;
|
||||
const filterString = filter.toLowerCase();
|
||||
const filterStringParts = filterString.split(' ');
|
||||
|
||||
const filteredTypes = DEFAULT_ORDER.filter(type => registry.has(type))
|
||||
const a = DEFAULT_ORDER.filter(type => registry.has(type));
|
||||
const filteredTypes = a
|
||||
.filter(type => {
|
||||
const behaviors = registry.get(type)?.behaviors || [];
|
||||
return nativeFilterGate(behaviors);
|
||||
|
@ -181,7 +188,11 @@ const VizTypeControl = props => {
|
|||
})
|
||||
.filter(({ key }) => !typesWithDefaultOrder.has(key)),
|
||||
)
|
||||
.filter(entry => entry.value.name.toLowerCase().includes(filterString));
|
||||
.filter(entry =>
|
||||
filterStringParts.every(
|
||||
part => entry.value.name.toLowerCase().indexOf(part) !== -1,
|
||||
),
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -217,9 +228,10 @@ const VizTypeControl = props => {
|
|||
value={filter}
|
||||
placeholder={t('Search')}
|
||||
onChange={changeSearch}
|
||||
data-test={`${VIZ_TYPE_CONTROL_TEST_ID}__search-input`}
|
||||
/>
|
||||
</div>
|
||||
<Row data-test="viz-row" gutter={16}>
|
||||
<Row data-test={`${VIZ_TYPE_CONTROL_TEST_ID}__viz-row`} gutter={16}>
|
||||
{filteredTypes.map(entry => (
|
||||
<Col xs={12} sm={8} md={6} lg={4} key={`grid-col-${entry.key}`}>
|
||||
{renderItem(entry)}
|
Loading…
Reference in New Issue