From c4c0e3fce44e723e0ef931f721d1cef11a841ccc Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Thu, 1 Apr 2021 13:10:42 -0300 Subject: [PATCH] test: Adds tests to the AnnotationLayer component (#13748) --- .../components/controls/AnnotationLayer.less | 24 --- .../AnnotationLayer.jsx | 24 ++- .../AnnotationLayer.test.tsx | 190 ++++++++++++++++++ .../index.jsx} | 0 .../components/controls/SelectControl.jsx | 2 + .../components/controls/TextControl/index.tsx | 4 +- 6 files changed, 209 insertions(+), 35 deletions(-) delete mode 100644 superset-frontend/src/explore/components/controls/AnnotationLayer.less rename superset-frontend/src/explore/components/controls/{ => AnnotationLayerControl}/AnnotationLayer.jsx (97%) create mode 100644 superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx rename superset-frontend/src/explore/components/controls/{AnnotationLayerControl.jsx => AnnotationLayerControl/index.jsx} (100%) diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayer.less b/superset-frontend/src/explore/components/controls/AnnotationLayer.less deleted file mode 100644 index 2f8c6c2f4303b..0000000000000 --- a/superset-frontend/src/explore/components/controls/AnnotationLayer.less +++ /dev/null @@ -1,24 +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. - */ - -.optionWrapper { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayer.jsx b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx similarity index 97% rename from superset-frontend/src/explore/components/controls/AnnotationLayer.jsx rename to superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx index 6de8677d61c64..b2eef07218373 100644 --- a/superset-frontend/src/explore/components/controls/AnnotationLayer.jsx +++ b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx @@ -29,10 +29,9 @@ import { validateNonEmpty, } from '@superset-ui/core'; -import SelectControl from './SelectControl'; -import TextControl from './TextControl'; -import CheckboxControl from './CheckboxControl'; - +import SelectControl from 'src/explore/components/controls/SelectControl'; +import TextControl from 'src/explore/components/controls/TextControl'; +import CheckboxControl from 'src/explore/components/controls/CheckboxControl'; import { ANNOTATION_SOURCE_TYPES, ANNOTATION_TYPES, @@ -40,11 +39,9 @@ import { DEFAULT_ANNOTATION_TYPE, requiresQuery, ANNOTATION_SOURCE_TYPES_METADATA, -} from '../../../modules/AnnotationTypes'; - -import PopoverSection from '../../../components/PopoverSection'; -import ControlHeader from '../ControlHeader'; -import './AnnotationLayer.less'; +} from 'src/modules/AnnotationTypes'; +import PopoverSection from 'src/components/PopoverSection'; +import ControlHeader from 'src/explore/components/ControlHeader'; const AUTOMATIC_COLOR = ''; @@ -359,7 +356,14 @@ export default class AnnotationLayer extends React.PureComponent { renderOption(option) { return ( - + {option.label} ); diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx new file mode 100644 index 0000000000000..22350af54363c --- /dev/null +++ b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx @@ -0,0 +1,190 @@ +/** + * 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 { render, screen, waitFor } from 'spec/helpers/testing-library'; +import userEvent from '@testing-library/user-event'; +import { getChartMetadataRegistry, ChartMetadata } from '@superset-ui/core'; +import fetchMock from 'fetch-mock'; +import setupColors from 'src/setup/setupColors'; +import { ANNOTATION_TYPES_METADATA } from 'src/modules/AnnotationTypes'; +import AnnotationLayer from './AnnotationLayer'; + +const defaultProps = { + value: '', + vizType: 'table', + annotationType: ANNOTATION_TYPES_METADATA.FORMULA.value, +}; + +beforeAll(() => { + const supportedAnnotationTypes = Object.values(ANNOTATION_TYPES_METADATA).map( + value => value.value, + ); + + fetchMock.get('glob:*/annotationlayermodelview/api/read?*', { + result: [{ label: 'Chart A', value: 'a' }], + }); + + fetchMock.get('glob:*/superset/user_slices*', [ + { id: 'a', title: 'Chart A', viz_type: 'table', data: {} }, + ]); + + setupColors(); + + getChartMetadataRegistry().registerValue( + 'table', + new ChartMetadata({ + name: 'Table', + thumbnail: '', + supportedAnnotationTypes, + canBeAnnotationTypes: ['EVENT'], + }), + ); +}); + +test('renders with default props', () => { + const { container } = render(); + expect(container).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled(); + expect(screen.getByRole('button', { name: 'OK' })).toBeDisabled(); + expect(screen.getByRole('button', { name: 'Cancel' })).toBeEnabled(); +}); + +test('renders extra checkboxes when type is time series', () => { + render(); + expect( + screen.queryByRole('button', { name: 'Show Markers' }), + ).not.toBeInTheDocument(); + expect( + screen.queryByRole('button', { name: 'Hide Line' }), + ).not.toBeInTheDocument(); + userEvent.click(screen.getAllByText('Formula')[0]); + userEvent.click(screen.getByText('Time series')); + expect( + screen.getByRole('button', { name: 'Show Markers' }), + ).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Hide Line' })).toBeInTheDocument(); +}); + +test('enables apply and ok buttons', async () => { + render(); + userEvent.type(screen.getByLabelText('Name'), 'Test'); + userEvent.type(screen.getByLabelText('Formula'), '2x'); + await waitFor(() => { + expect(screen.getByRole('button', { name: 'Apply' })).toBeEnabled(); + expect(screen.getByRole('button', { name: 'OK' })).toBeEnabled(); + }); +}); + +test('triggers addAnnotationLayer when apply button is clicked', () => { + const addAnnotationLayer = jest.fn(); + render( + , + ); + userEvent.click(screen.getByRole('button', { name: 'Apply' })); + expect(addAnnotationLayer).toHaveBeenCalled(); +}); + +test('triggers addAnnotationLayer and close when ok button is clicked', () => { + const addAnnotationLayer = jest.fn(); + const close = jest.fn(); + render( + , + ); + userEvent.click(screen.getByRole('button', { name: 'OK' })); + expect(addAnnotationLayer).toHaveBeenCalled(); + expect(close).toHaveBeenCalled(); +}); + +test('triggers close when cancel button is clicked', () => { + const close = jest.fn(); + render(); + userEvent.click(screen.getByRole('button', { name: 'Cancel' })); + expect(close).toHaveBeenCalled(); +}); + +test('triggers removeAnnotationLayer and close when remove button is clicked', () => { + const removeAnnotationLayer = jest.fn(); + const close = jest.fn(); + render( + , + ); + userEvent.click(screen.getByRole('button', { name: 'Remove' })); + expect(removeAnnotationLayer).toHaveBeenCalled(); + expect(close).toHaveBeenCalled(); +}); + +test('renders chart options', async () => { + render( + , + ); + userEvent.click(screen.getByText('2 option(s)')); + userEvent.click(screen.getByText('Superset annotation')); + expect(await screen.findByLabelText('Annotation layer')).toBeInTheDocument(); + userEvent.click(screen.getByText('Superset annotation')); + userEvent.click(screen.getByText('Table')); + expect(await screen.findByLabelText('Chart')).toBeInTheDocument(); +}); + +test('keeps apply disabled when missing required fields', async () => { + render( + , + ); + userEvent.click(await screen.findByText('1 option(s)')); + userEvent.click(screen.getByText('Chart A')); + expect( + screen.getByText('Annotation Slice Configuration'), + ).toBeInTheDocument(); + + userEvent.click(screen.getByRole('button', { name: 'Automatic Color' })); + userEvent.click(screen.getByLabelText('Title Column')); + userEvent.click(screen.getByText('None')); + userEvent.click(screen.getByLabelText('Style')); + userEvent.click(screen.getByText('Dashed')); + userEvent.click(screen.getByLabelText('Opacity')); + userEvent.click(screen.getByText('0.5')); + + const checkboxes = screen.getAllByRole('checkbox'); + checkboxes.forEach(checkbox => userEvent.click(checkbox)); + + expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled(); +}); diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayerControl.jsx b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.jsx similarity index 100% rename from superset-frontend/src/explore/components/controls/AnnotationLayerControl.jsx rename to superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.jsx diff --git a/superset-frontend/src/explore/components/controls/SelectControl.jsx b/superset-frontend/src/explore/components/controls/SelectControl.jsx index a26206eb54c4f..08b6e8576a72d 100644 --- a/superset-frontend/src/explore/components/controls/SelectControl.jsx +++ b/superset-frontend/src/explore/components/controls/SelectControl.jsx @@ -221,6 +221,7 @@ export default class SelectControl extends React.PureComponent { disabled, filterOption, isLoading, + label, menuPlacement, name, noResultsText, @@ -255,6 +256,7 @@ export default class SelectControl extends React.PureComponent { const selectProps = { autoFocus, + 'aria-label': label, clearable, disabled, filterOption, diff --git a/superset-frontend/src/explore/components/controls/TextControl/index.tsx b/superset-frontend/src/explore/components/controls/TextControl/index.tsx index 93c69e5a82914..ee41cbdf02a31 100644 --- a/superset-frontend/src/explore/components/controls/TextControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/TextControl/index.tsx @@ -26,6 +26,7 @@ import ControlHeader from 'src/explore/components/ControlHeader'; type InputValueType = string | number; export interface TextControlProps { + label?: string; disabled?: boolean; isFloat?: boolean; isInt?: boolean; @@ -109,7 +110,7 @@ export default class TextControl< return (
- +