test: SliceHeader (#13888)

* tests for SliceHeader

* Update superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* Update superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* Update superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
This commit is contained in:
Bruno Motta 2021-04-09 13:14:16 -03:00 committed by GitHub
parent 36f101e500
commit ec3f8d07f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 417 additions and 10 deletions

View File

@ -0,0 +1,399 @@
/**
* 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 { Slice } from 'src/types/Chart';
import React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import SliceHeader from '.';
jest.mock('src/dashboard/components/SliceHeaderControls', () => ({
__esModule: true,
default: (props: any) => (
<div
data-test="SliceHeaderControls"
data-slice={JSON.stringify(props.slice)}
data-is-cached={props.isCached}
data-is-expanded={props.isExpanded}
data-cached-dttm={props.cachedDttm}
data-updated-dttm={props.updatedDttm}
data-superset-can-explore={props.supersetCanExplore}
data-superset-can-csv={props.supersetCanCSV}
data-slice-can-edit={props.sliceCanEdit}
data-component-id={props.componentId}
data-dashboard-id={props.dashboardId}
data-is-full-size={props.isFullSize}
data-chart-status={props.chartStatus}
>
<button
type="button"
data-test="toggleExpandSlice"
onClick={props.toggleExpandSlice}
>
toggleExpandSlice
</button>
<button
type="button"
data-test="forceRefresh"
onClick={props.forceRefresh}
>
forceRefresh
</button>
<button
type="button"
data-test="exploreChart"
onClick={props.exploreChart}
>
exploreChart
</button>
<button type="button" data-test="exportCSV" onClick={props.exportCSV}>
exportCSV
</button>
<button
type="button"
data-test="handleToggleFullSize"
onClick={props.handleToggleFullSize}
>
handleToggleFullSize
</button>
<button
type="button"
data-test="addSuccessToast"
onClick={props.addSuccessToast}
>
addSuccessToast
</button>
<button
type="button"
data-test="addDangerToast"
onClick={props.addDangerToast}
>
addDangerToast
</button>
</div>
),
}));
jest.mock('src/dashboard/containers/FiltersBadge', () => ({
__esModule: true,
default: (props: any) => (
<div data-test="FiltersBadge" data-chart-id={props.chartId} />
),
}));
const createProps = () => ({
filters: {}, // is in typing but not being used
editMode: false,
annotationQuery: { param01: 'annotationQuery' } as any,
annotationError: { param01: 'annotationError' } as any,
cachedDttm: [] as string[],
updatedDttm: 1617207718004,
isCached: [false],
isExpanded: false,
sliceName: 'Vaccine Candidates per Phase',
supersetCanExplore: true,
supersetCanCSV: true,
sliceCanEdit: false,
slice: ({
slice_id: 312,
slice_url: '/superset/explore/?form_data=%7B%22slice_id%22%3A%20312%7D',
slice_name: 'Vaccine Candidates per Phase',
form_data: {
adhoc_filters: [],
bottom_margin: 'auto',
color_scheme: 'SUPERSET_DEFAULT',
columns: [],
datasource: '58__table',
groupby: ['clinical_stage'],
label_colors: {},
metrics: ['count'],
row_limit: 10000,
show_legend: false,
time_range: 'No filter',
time_range_endpoints: ['inclusive', 'exclusive'],
url_params: {},
viz_type: 'dist_bar',
x_ticks_layout: 'auto',
y_axis_format: 'SMART_NUMBER',
slice_id: 312,
},
viz_type: 'dist_bar',
datasource: '58__table',
description: null,
description_markeddown: '',
owners: [],
modified: '<span class="no-wrap">20 hours ago</span>',
changed_on: 1617143411366,
} as unknown) as Slice,
componentId: 'CHART-aGfmWtliqA',
dashboardId: 26,
isFullSize: false,
chartStatus: 'rendered',
addSuccessToast: jest.fn(),
addDangerToast: jest.fn(),
handleToggleFullSize: jest.fn(),
updateSliceName: jest.fn(),
toggleExpandSlice: jest.fn(),
forceRefresh: jest.fn(),
exploreChart: jest.fn(),
exportCSV: jest.fn(),
});
test('Should render', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(screen.getByTestId('slice-header')).toBeInTheDocument();
});
test('Should render - default props', () => {
const props = createProps();
// @ts-ignore
delete props.forceRefresh;
// @ts-ignore
delete props.updateSliceName;
// @ts-ignore
delete props.toggleExpandSlice;
// @ts-ignore
delete props.exploreChart;
// @ts-ignore
delete props.exportCSV;
// @ts-ignore
delete props.innerRef;
// @ts-ignore
delete props.editMode;
// @ts-ignore
delete props.annotationQuery;
// @ts-ignore
delete props.annotationError;
// @ts-ignore
delete props.cachedDttm;
// @ts-ignore
delete props.updatedDttm;
// @ts-ignore
delete props.isCached;
// @ts-ignore
delete props.isExpanded;
// @ts-ignore
delete props.sliceName;
// @ts-ignore
delete props.supersetCanExplore;
// @ts-ignore
delete props.supersetCanCSV;
// @ts-ignore
delete props.sliceCanEdit;
render(<SliceHeader {...props} />, { useRedux: true });
expect(screen.getByTestId('slice-header')).toBeInTheDocument();
});
test('Should render default props and "call" actions', () => {
const props = createProps();
// @ts-ignore
delete props.forceRefresh;
// @ts-ignore
delete props.updateSliceName;
// @ts-ignore
delete props.toggleExpandSlice;
// @ts-ignore
delete props.exploreChart;
// @ts-ignore
delete props.exportCSV;
// @ts-ignore
delete props.innerRef;
// @ts-ignore
delete props.editMode;
// @ts-ignore
delete props.annotationQuery;
// @ts-ignore
delete props.annotationError;
// @ts-ignore
delete props.cachedDttm;
// @ts-ignore
delete props.updatedDttm;
// @ts-ignore
delete props.isCached;
// @ts-ignore
delete props.isExpanded;
// @ts-ignore
delete props.sliceName;
// @ts-ignore
delete props.supersetCanExplore;
// @ts-ignore
delete props.supersetCanCSV;
// @ts-ignore
delete props.sliceCanEdit;
render(<SliceHeader {...props} />, { useRedux: true });
userEvent.click(screen.getByTestId('toggleExpandSlice'));
userEvent.click(screen.getByTestId('forceRefresh'));
userEvent.click(screen.getByTestId('exploreChart'));
userEvent.click(screen.getByTestId('exportCSV'));
userEvent.click(screen.getByTestId('addSuccessToast'));
userEvent.click(screen.getByTestId('addDangerToast'));
userEvent.click(screen.getByTestId('handleToggleFullSize'));
expect(screen.getByTestId('slice-header')).toBeInTheDocument();
});
test('Should render title', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(screen.getByText('Vaccine Candidates per Phase')).toBeInTheDocument();
});
test('Should render "annotationsLoading"', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(
screen.getByRole('img', {
name: 'Annotation layers are still loading.',
}),
).toBeInTheDocument();
});
test('Should render "annotationsError"', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(
screen.getByRole('img', {
name: 'One ore more annotation layers failed loading.',
}),
).toBeInTheDocument();
});
test('Should not render "annotationsError" and "annotationsLoading"', () => {
const props = createProps();
props.annotationQuery = {};
props.annotationError = {};
render(<SliceHeader {...props} />, { useRedux: true });
expect(
screen.queryByRole('img', {
name: 'One ore more annotation layers failed loading.',
}),
).not.toBeInTheDocument();
expect(
screen.queryByRole('img', {
name: 'Annotation layers are still loading.',
}),
).not.toBeInTheDocument();
});
test('Correct props to "FiltersBadge"', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(screen.getByTestId('FiltersBadge')).toHaveAttribute(
'data-chart-id',
'312',
);
});
test('Correct props to "SliceHeaderControls"', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-cached-dttm',
'',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-chart-status',
'rendered',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-component-id',
'CHART-aGfmWtliqA',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-dashboard-id',
'26',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-is-cached',
'false',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-is-expanded',
'false',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-is-full-size',
'false',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-slice-can-edit',
'false',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-superset-can-csv',
'true',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-superset-can-explore',
'true',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-test',
'SliceHeaderControls',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-updated-dttm',
'1617207718004',
);
expect(screen.getByTestId('SliceHeaderControls')).toHaveAttribute(
'data-slice',
JSON.stringify(props.slice),
);
});
test('Correct actions to "SliceHeaderControls"', () => {
const props = createProps();
render(<SliceHeader {...props} />, { useRedux: true });
expect(props.toggleExpandSlice).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('toggleExpandSlice'));
expect(props.toggleExpandSlice).toBeCalledTimes(1);
expect(props.forceRefresh).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('forceRefresh'));
expect(props.forceRefresh).toBeCalledTimes(1);
expect(props.exploreChart).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('exploreChart'));
expect(props.exploreChart).toBeCalledTimes(1);
expect(props.exportCSV).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('exportCSV'));
expect(props.exportCSV).toBeCalledTimes(1);
expect(props.addSuccessToast).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('addSuccessToast'));
expect(props.addSuccessToast).toBeCalledTimes(1);
expect(props.addDangerToast).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('addDangerToast'));
expect(props.addDangerToast).toBeCalledTimes(1);
expect(props.handleToggleFullSize).toBeCalledTimes(0);
userEvent.click(screen.getByTestId('handleToggleFullSize'));
expect(props.handleToggleFullSize).toBeCalledTimes(1);
});

View File

@ -20,13 +20,13 @@ import React, { FC } from 'react';
import { styled, t } from '@superset-ui/core';
import { Tooltip } from 'src/common/components/Tooltip';
import { useSelector } from 'react-redux';
import EditableTitle from '../../components/EditableTitle';
import SliceHeaderControls from './SliceHeaderControls';
import FiltersBadge from '../containers/FiltersBadge';
import Icon from '../../components/Icon';
import { RootState } from '../types';
import { Slice } from '../../types/Chart';
import FilterIndicator from './FiltersBadge/FilterIndicator';
import EditableTitle from 'src/components/EditableTitle';
import SliceHeaderControls from 'src/dashboard/components/SliceHeaderControls';
import FiltersBadge from 'src/dashboard/containers/FiltersBadge';
import Icon from 'src/components/Icon';
import { RootState } from 'src/dashboard/types';
import { Slice } from 'src/types/Chart';
import FilterIndicator from 'src/dashboard/components/FiltersBadge/FilterIndicator';
type SliceHeaderProps = {
innerRef?: string;
@ -101,7 +101,7 @@ const SliceHeader: FC<SliceHeaderProps> = ({
);
return (
<div className="chart-header" ref={innerRef}>
<div className="chart-header" data-test="slice-header" ref={innerRef}>
<div className="header-title">
<EditableTitle
title={
@ -121,7 +121,11 @@ const SliceHeader: FC<SliceHeaderProps> = ({
placement="top"
title={annoationsLoading}
>
<i className="fa fa-refresh warning" />
<i
role="img"
aria-label={annoationsLoading}
className="fa fa-refresh warning"
/>
</Tooltip>
)}
{!!Object.values(annotationError).length && (
@ -130,7 +134,11 @@ const SliceHeader: FC<SliceHeaderProps> = ({
placement="top"
title={annoationsError}
>
<i className="fa fa-exclamation-circle danger" />
<i
role="img"
aria-label={annoationsError}
className="fa fa-exclamation-circle danger"
/>
</Tooltip>
)}
</div>