Skip to content

Commit

Permalink
chore(dashboard): migrate enzyme to RTL (#26260)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpark authored Feb 7, 2024
1 parent 918057e commit f8c75ca
Show file tree
Hide file tree
Showing 17 changed files with 1,036 additions and 1,067 deletions.
125 changes: 71 additions & 54 deletions superset-frontend/src/dashboard/components/DashboardGrid.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,77 +17,94 @@
* under the License.
*/
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import { fireEvent, render } from 'spec/helpers/testing-library';

import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
import DashboardGrid from 'src/dashboard/components/DashboardGrid';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import newComponentFactory from 'src/dashboard/util/newComponentFactory';

import { DASHBOARD_GRID_TYPE } from 'src/dashboard/util/componentTypes';
import { GRID_COLUMN_COUNT } from 'src/dashboard/util/constants';

describe('DashboardGrid', () => {
const props = {
depth: 1,
editMode: false,
gridComponent: {
...newComponentFactory(DASHBOARD_GRID_TYPE),
children: ['a'],
},
handleComponentDrop() {},
resizeComponent() {},
width: 500,
isComponentVisible: true,
setDirectPathToChild() {},
};
const args = { id: 'id', widthMultiple: 1, heightMultiple: 3 };

function setup(overrideProps) {
const wrapper = shallow(<DashboardGrid {...props} {...overrideProps} />);
return wrapper;
}
jest.mock(
'src/dashboard/containers/DashboardComponent',
() =>
({ onResizeStart, onResizeStop }) =>
(
<button
type="button"
data-test="mock-dashboard-component"
onClick={() => onResizeStart()}
onBlur={() => onResizeStop(args)}
>
Mock
</button>
),
);

it('should render a div with class "dashboard-grid"', () => {
const wrapper = setup();
expect(wrapper.find('.dashboard-grid')).toExist();
});
const props = {
depth: 1,
editMode: false,
gridComponent: {
...newComponentFactory(DASHBOARD_GRID_TYPE),
children: ['a'],
},
handleComponentDrop() {},
resizeComponent() {},
width: 500,
isComponentVisible: true,
setDirectPathToChild() {},
};

it('should render one DashboardComponent for each gridComponent child', () => {
const wrapper = setup({
gridComponent: { ...props.gridComponent, children: ['a', 'b'] },
});
expect(wrapper.find(DashboardComponent)).toHaveLength(2);
function setup(overrideProps) {
return render(<DashboardGrid {...props} {...overrideProps} />, {
useRedux: true,
useDnd: true,
});
}

test('should render a div with class "dashboard-grid"', () => {
const { container } = setup();
expect(container.querySelector('.dashboard-grid')).toBeInTheDocument();
});

it('should render two empty DragDroppables in editMode to increase the drop target zone', () => {
const viewMode = setup({ editMode: false });
const editMode = setup({ editMode: true });
expect(viewMode.find(DragDroppable)).toHaveLength(0);
expect(editMode.find(DragDroppable)).toHaveLength(2);
test('should render one DashboardComponent for each gridComponent child', () => {
const { getAllByTestId } = setup({
gridComponent: { ...props.gridComponent, children: ['a', 'b'] },
});
expect(getAllByTestId('mock-dashboard-component')).toHaveLength(2);
});

it('should render grid column guides when resizing', () => {
const wrapper = setup({ editMode: true });
expect(wrapper.find('.grid-column-guide')).not.toExist();
test('should render two empty DragDroppables in editMode to increase the drop target zone', () => {
const { queryAllByTestId } = setup({ editMode: false });
expect(queryAllByTestId('dragdroppable-object').length).toEqual(0);
const { getAllByTestId } = setup({ editMode: true });
expect(getAllByTestId('dragdroppable-object').length).toEqual(2);
});

wrapper.setState({ isResizing: true });
test('should render grid column guides when resizing', () => {
const { container, getAllByTestId } = setup({ editMode: true });
expect(container.querySelector('.grid-column-guide')).not.toBeInTheDocument();

expect(wrapper.find('.grid-column-guide')).toHaveLength(GRID_COLUMN_COUNT);
});
// map handleResizeStart to the onClick prop of the mock DashboardComponent
fireEvent.click(getAllByTestId('mock-dashboard-component')[0]);

expect(container.querySelectorAll('.grid-column-guide')).toHaveLength(
GRID_COLUMN_COUNT,
);
});

it('should call resizeComponent when a child DashboardComponent calls resizeStop', () => {
const resizeComponent = sinon.spy();
const args = { id: 'id', widthMultiple: 1, heightMultiple: 3 };
const wrapper = setup({ resizeComponent });
const dashboardComponent = wrapper.find(DashboardComponent).first();
dashboardComponent.prop('onResizeStop')(args);
test('should call resizeComponent when a child DashboardComponent calls resizeStop', () => {
const resizeComponent = jest.fn();
const { getAllByTestId } = setup({ resizeComponent });
const dashboardComponent = getAllByTestId('mock-dashboard-component')[0];
fireEvent.blur(dashboardComponent);

expect(resizeComponent.callCount).toBe(1);
expect(resizeComponent.getCall(0).args[0]).toEqual({
id: 'id',
width: 1,
height: 3,
});
expect(resizeComponent).toHaveBeenCalledTimes(1);
expect(resizeComponent).toHaveBeenCalledWith({
id: 'id',
width: 1,
height: 3,
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@
* under the License.
*/
import React from 'react';
import { shallow } from 'enzyme';
import { Provider } from 'react-redux';
import { Store } from 'redux';
import * as SupersetUI from '@superset-ui/core';
import { styledMount as mount } from 'spec/helpers/theming';
import { render } from 'spec/helpers/testing-library';
import {
CHART_RENDERING_SUCCEEDED,
CHART_UPDATE_SUCCEEDED,
Expand All @@ -36,123 +33,105 @@ import { sliceId } from 'spec/fixtures/mockChartQueries';
import { dashboardFilters } from 'spec/fixtures/mockDashboardFilters';
import { dashboardWithFilter } from 'spec/fixtures/mockDashboardLayout';

jest.mock(
'src/dashboard/components/FiltersBadge/DetailsPanel',
() =>
({ children }: { children: React.ReactNode }) =>
<div data-test="mock-details-panel">{children}</div>,
);

const defaultStore = getMockStoreWithFilters();
function setup(store: Store = defaultStore) {
return mount(
<Provider store={store}>
<FiltersBadge chartId={sliceId} />
</Provider>,
);
return render(<FiltersBadge chartId={sliceId} />, { store });
}

describe('FiltersBadge', () => {
// there's this bizarre "active filters" thing
// that doesn't actually use any kind of state management.
// Have to set variables in there.
buildActiveFilters({
dashboardFilters,
components: dashboardWithFilter,
});

beforeEach(() => {
// shallow rendering in enzyme doesn't propagate contexts correctly,
// so we have to mock the hook.
// See https://medium.com/7shifts-engineering-blog/testing-usecontext-react-hook-with-enzyme-shallow-da062140fc83
jest
.spyOn(SupersetUI, 'useTheme')
.mockImplementation(() => SupersetUI.supersetTheme);
});
// there's this bizarre "active filters" thing
// that doesn't actually use any kind of state management.
// Have to set variables in there.
buildActiveFilters({
dashboardFilters,
components: dashboardWithFilter,
});

describe('for dashboard filters', () => {
it("doesn't show number when there are no active filters", () => {
const store = getMockStoreWithFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [],
rejected_filters: [],
},
],
dashboardFilters,
});
const wrapper = shallow(
<Provider store={store}>
<FiltersBadge chartId={sliceId} />,
</Provider>,
);
expect(wrapper.find('[data-test="applied-filter-count"]')).not.toExist();
describe('for dashboard filters', () => {
test('does not show number when there are no active filters', () => {
const store = getMockStoreWithFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [],
rejected_filters: [],
},
],
dashboardFilters,
});
const { queryByTestId } = setup(store);
expect(queryByTestId('applied-filter-count')).not.toBeInTheDocument();
});

it('shows the indicator when filters have been applied', () => {
const store = getMockStoreWithFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [{ column: 'region' }],
rejected_filters: [],
},
],
dashboardFilters,
});
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
const wrapper = setup(store);
expect(wrapper.find('DetailsPanelPopover')).toExist();
expect(
wrapper.find('[data-test="applied-filter-count"] .current'),
).toHaveText('1');
expect(wrapper.find('WarningFilled')).not.toExist();
test('shows the indicator when filters have been applied', () => {
const store = getMockStoreWithFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [{ column: 'region' }],
rejected_filters: [],
},
],
dashboardFilters,
});
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
const { getByTestId } = setup(store);
expect(getByTestId('applied-filter-count')).toHaveTextContent('1');
expect(getByTestId('mock-details-panel')).toBeInTheDocument();
});
});

describe('for native filters', () => {
it("doesn't show number when there are no active filters", () => {
const store = getMockStoreWithNativeFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [],
rejected_filters: [],
},
],
});
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
const wrapper = setup(store);
expect(wrapper.find('[data-test="applied-filter-count"]')).not.toExist();
describe('for native filters', () => {
test('does not show number when there are no active filters', () => {
const store = getMockStoreWithNativeFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [],
rejected_filters: [],
},
],
});
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
const { queryByTestId } = setup(store);
expect(queryByTestId('applied-filter-count')).not.toBeInTheDocument();
});

it('shows the indicator when filters have been applied', () => {
const store = getMockStoreWithNativeFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [{ column: 'region' }],
rejected_filters: [],
},
],
});
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
const wrapper = setup(store);
expect(wrapper.find('DetailsPanelPopover')).toExist();
expect(
wrapper.find('[data-test="applied-filter-count"] .current'),
).toHaveText('1');
expect(wrapper.find('WarningFilled')).not.toExist();
test('shows the indicator when filters have been applied', () => {
const store = getMockStoreWithNativeFilters();
// start with basic dashboard state, dispatch an event to simulate query completion
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
queriesResponse: [
{
status: 'success',
applied_filters: [{ column: 'region' }],
rejected_filters: [],
},
],
});
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
const { getByTestId } = setup(store);
expect(getByTestId('applied-filter-count')).toHaveTextContent('1');
expect(getByTestId('mock-details-panel')).toBeInTheDocument();
});
});
Loading

0 comments on commit f8c75ca

Please sign in to comment.