From 9156f089ffb96fe765d67766cc015cf3d7df2faa Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Thu, 1 Apr 2021 09:14:51 +0300 Subject: [PATCH] test: Refactor and enhance tests for the Explore DatasourcePanel Component (#13799) * Refactor and enhance tests * Fix linting issues --- .../components/DatasourcePanel_spec.jsx | 127 -------------- .../DatasourcePanel/DatasourcePanel.test.tsx | 164 ++++++++++++++++++ .../components/DatasourcePanel/index.ts | 19 -- .../{DatasourcePanel.tsx => index.tsx} | 2 +- 4 files changed, 165 insertions(+), 147 deletions(-) delete mode 100644 superset-frontend/spec/javascripts/explore/components/DatasourcePanel_spec.jsx create mode 100644 superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.test.tsx delete mode 100644 superset-frontend/src/explore/components/DatasourcePanel/index.ts rename superset-frontend/src/explore/components/DatasourcePanel/{DatasourcePanel.tsx => index.tsx} (99%) diff --git a/superset-frontend/spec/javascripts/explore/components/DatasourcePanel_spec.jsx b/superset-frontend/spec/javascripts/explore/components/DatasourcePanel_spec.jsx deleted file mode 100644 index c0ddb5b3db848..0000000000000 --- a/superset-frontend/spec/javascripts/explore/components/DatasourcePanel_spec.jsx +++ /dev/null @@ -1,127 +0,0 @@ -/** - * 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 React from 'react'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import { DndProvider } from 'react-dnd'; -import { render, screen } from 'spec/helpers/testing-library'; -import userEvent from '@testing-library/user-event'; -import DatasourcePanel from 'src/explore/components/DatasourcePanel'; -import { columns, metrics } from 'spec/javascripts/datasource/fixtures'; - -describe('datasourcepanel', () => { - const datasource = { - name: 'birth_names', - type: 'table', - uid: '1__table', - id: 1, - columns, - metrics, - database: { - backend: 'mysql', - name: 'main', - }, - }; - const props = { - datasource, - controls: { - datasource: { - validationErrors: null, - mapStateToProps: () => null, - type: 'DatasourceControl', - label: 'hello', - datasource, - }, - }, - actions: {}, - }; - - const setup = props => ( - - - - ); - - function search(value, input) { - userEvent.clear(input); - userEvent.type(input, value); - } - - it('should render', () => { - const { container } = render(setup(props)); - expect(container).toBeVisible(); - }); - - it('should display items in controls', () => { - render(setup(props)); - expect(screen.getByText('birth_names')).toBeTruthy(); - expect(screen.getByText('Columns')).toBeTruthy(); - expect(screen.getByText('Metrics')).toBeTruthy(); - expect(screen.queryByTestId('warning')).not.toBeInTheDocument(); - }); - - it('should render search results', () => { - const { container } = render(setup(props)); - const c = container.getElementsByClassName('option-label'); - - expect(c).toHaveLength(5); - }); - - it('should render 0 search results', () => { - const { container } = render(setup(props)); - const c = container.getElementsByClassName('option-label'); - const searchInput = screen.getByPlaceholderText('Search Metrics & Columns'); - - search('sssssssss', searchInput); - setTimeout(() => { - expect(c).toHaveLength(0); - }, 201); - }); - - it('should render and sort search results', () => { - const { container } = render(setup(props)); - const c = container.getElementsByClassName('option-label'); - const searchInput = screen.getByPlaceholderText('Search Metrics & Columns'); - - search('end', searchInput); - setTimeout(() => { - expect(c).toHaveLength(4); - expect(c[0].value).toBe('metric_end_certified'); - }, 201); - }); - - it('should render a warning', () => { - const deprecatedDatasource = { - ...datasource, - extra: JSON.stringify({ warning_markdown: 'This is a warning.' }), - }; - render( - setup({ - ...props, - datasource: deprecatedDatasource, - controls: { - datasource: { - ...props.controls.datasource, - datasource: deprecatedDatasource, - }, - }, - }), - ); - expect(screen.getByTestId('alert-solid')).toBeTruthy(); - }); -}); diff --git a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.test.tsx b/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.test.tsx new file mode 100644 index 0000000000000..c8f61ad3eb2bd --- /dev/null +++ b/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.test.tsx @@ -0,0 +1,164 @@ +/** + * 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 React from 'react'; +import { HTML5Backend } from 'react-dnd-html5-backend'; +import { DndProvider } from 'react-dnd'; +import { render, screen, waitFor } from 'spec/helpers/testing-library'; +import userEvent from '@testing-library/user-event'; +import DatasourcePanel, { + Props as DatasourcePanelProps, +} from 'src/explore/components/DatasourcePanel'; +import { columns, metrics } from 'spec/javascripts/datasource/fixtures'; +import { DatasourceType } from '@superset-ui/core/lib/query/types/Datasource'; +import DatasourceControl from 'src/explore/components/controls/DatasourceControl'; + +const datasource = { + id: 1, + type: DatasourceType.Table, + name: 'birth_names', + columns, + metrics, + uid: '1__table', + database: { + backend: 'mysql', + name: 'main', + }, + column_format: { ratio: '.2%' }, + verbose_map: { __timestamp: 'Time' }, + main_dttm_col: 'None', + datasource_name: 'table1', + description: 'desc', +}; +const props = { + datasource, + controls: { + datasource: { + validationErrors: null, + mapStateToProps: () => ({ value: undefined }), + type: DatasourceControl, + label: 'hello', + datasource, + }, + }, + actions: { + setControlValue: () => ({ + type: 'type', + controlName: 'control', + value: 'val', + validationErrors: [], + }), + }, +}; + +const setup = (props: DatasourcePanelProps) => ( + + + +); + +function search(value: string, input: HTMLElement) { + userEvent.clear(input); + userEvent.type(input, value); +} + +test('should render', () => { + const { container } = render(setup(props)); + expect(container).toBeVisible(); +}); + +test('should display items in controls', () => { + render(setup(props)); + expect(screen.getByText('birth_names')).toBeInTheDocument(); + expect(screen.getByText('Metrics')).toBeInTheDocument(); + expect(screen.getByText('Columns')).toBeInTheDocument(); +}); + +test('should render the metrics', () => { + render(setup(props)); + const metricsNum = metrics.length; + metrics.forEach(metric => + expect(screen.getByText(metric.metric_name)).toBeInTheDocument(), + ); + expect( + screen.getByText(`Showing ${metricsNum} of ${metricsNum}`), + ).toBeInTheDocument(); +}); + +test('should render the columns', () => { + render(setup(props)); + const columnsNum = columns.length; + columns.forEach(col => + expect(screen.getByText(col.column_name)).toBeInTheDocument(), + ); + expect( + screen.getByText(`Showing ${columnsNum} of ${columnsNum}`), + ).toBeInTheDocument(); +}); + +test('should render 0 search results', async () => { + render(setup(props)); + const searchInput = screen.getByPlaceholderText('Search Metrics & Columns'); + + search('nothing', searchInput); + expect(await screen.findByText('Showing 0 of 0')).toBeInTheDocument(); +}); + +test('should search and render matching columns', async () => { + render(setup(props)); + const searchInput = screen.getByPlaceholderText('Search Metrics & Columns'); + + search(columns[0].column_name, searchInput); + + await waitFor(() => { + expect(screen.getByText(columns[0].column_name)).toBeInTheDocument(); + expect(screen.queryByText(columns[1].column_name)).not.toBeInTheDocument(); + }); +}); + +test('should search and render matching metrics', async () => { + render(setup(props)); + const searchInput = screen.getByPlaceholderText('Search Metrics & Columns'); + + search(metrics[0].metric_name, searchInput); + + await waitFor(() => { + expect(screen.getByText(metrics[0].metric_name)).toBeInTheDocument(); + expect(screen.queryByText(metrics[1].metric_name)).not.toBeInTheDocument(); + }); +}); + +test('should render a warning', () => { + const deprecatedDatasource = { + ...datasource, + extra: JSON.stringify({ warning_markdown: 'This is a warning.' }), + }; + render( + setup({ + ...props, + datasource: deprecatedDatasource, + controls: { + datasource: { + ...props.controls.datasource, + datasource: deprecatedDatasource, + }, + }, + }), + ); + expect(screen.getByTestId('alert-solid')).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/explore/components/DatasourcePanel/index.ts b/superset-frontend/src/explore/components/DatasourcePanel/index.ts deleted file mode 100644 index 82a2573159641..0000000000000 --- a/superset-frontend/src/explore/components/DatasourcePanel/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 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. - */ -export { default } from './DatasourcePanel'; diff --git a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.tsx b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx similarity index 99% rename from superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.tsx rename to superset-frontend/src/explore/components/DatasourcePanel/index.tsx index cd195d63d3f98..475601ac49d7d 100644 --- a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.tsx +++ b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx @@ -38,7 +38,7 @@ interface DatasourceControl extends ControlConfig { datasource?: DatasourceMeta; } -interface Props { +export interface Props { datasource: DatasourceMeta; controls: { datasource: DatasourceControl;