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:
Einat Bertenthal 2021-05-25 18:41:53 +03:00 committed by GitHub
parent 63dc035d6a
commit dfe030b835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 128 additions and 5 deletions

View File

@ -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;

View File

@ -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/);
});
});

View File

@ -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)}