Skip to content

Commit a8a7322

Browse files
justinparksfirke
authored andcommitted
chore(dashboard): migrate enzyme to RTL (apache#26260)
1 parent 45666c5 commit a8a7322

17 files changed

+1036
-1067
lines changed

superset-frontend/src/dashboard/components/DashboardGrid.test.jsx

+71-54
Original file line numberDiff line numberDiff line change
@@ -17,77 +17,94 @@
1717
* under the License.
1818
*/
1919
import React from 'react';
20-
import { shallow } from 'enzyme';
21-
import sinon from 'sinon';
20+
import { fireEvent, render } from 'spec/helpers/testing-library';
2221

23-
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
2422
import DashboardGrid from 'src/dashboard/components/DashboardGrid';
25-
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
2623
import newComponentFactory from 'src/dashboard/util/newComponentFactory';
2724

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

31-
describe('DashboardGrid', () => {
32-
const props = {
33-
depth: 1,
34-
editMode: false,
35-
gridComponent: {
36-
...newComponentFactory(DASHBOARD_GRID_TYPE),
37-
children: ['a'],
38-
},
39-
handleComponentDrop() {},
40-
resizeComponent() {},
41-
width: 500,
42-
isComponentVisible: true,
43-
setDirectPathToChild() {},
44-
};
28+
const args = { id: 'id', widthMultiple: 1, heightMultiple: 3 };
4529

46-
function setup(overrideProps) {
47-
const wrapper = shallow(<DashboardGrid {...props} {...overrideProps} />);
48-
return wrapper;
49-
}
30+
jest.mock(
31+
'src/dashboard/containers/DashboardComponent',
32+
() =>
33+
({ onResizeStart, onResizeStop }) =>
34+
(
35+
<button
36+
type="button"
37+
data-test="mock-dashboard-component"
38+
onClick={() => onResizeStart()}
39+
onBlur={() => onResizeStop(args)}
40+
>
41+
Mock
42+
</button>
43+
),
44+
);
5045

51-
it('should render a div with class "dashboard-grid"', () => {
52-
const wrapper = setup();
53-
expect(wrapper.find('.dashboard-grid')).toExist();
54-
});
46+
const props = {
47+
depth: 1,
48+
editMode: false,
49+
gridComponent: {
50+
...newComponentFactory(DASHBOARD_GRID_TYPE),
51+
children: ['a'],
52+
},
53+
handleComponentDrop() {},
54+
resizeComponent() {},
55+
width: 500,
56+
isComponentVisible: true,
57+
setDirectPathToChild() {},
58+
};
5559

56-
it('should render one DashboardComponent for each gridComponent child', () => {
57-
const wrapper = setup({
58-
gridComponent: { ...props.gridComponent, children: ['a', 'b'] },
59-
});
60-
expect(wrapper.find(DashboardComponent)).toHaveLength(2);
60+
function setup(overrideProps) {
61+
return render(<DashboardGrid {...props} {...overrideProps} />, {
62+
useRedux: true,
63+
useDnd: true,
6164
});
65+
}
66+
67+
test('should render a div with class "dashboard-grid"', () => {
68+
const { container } = setup();
69+
expect(container.querySelector('.dashboard-grid')).toBeInTheDocument();
70+
});
6271

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

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

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

76-
expect(wrapper.find('.grid-column-guide')).toHaveLength(GRID_COLUMN_COUNT);
77-
});
90+
// map handleResizeStart to the onClick prop of the mock DashboardComponent
91+
fireEvent.click(getAllByTestId('mock-dashboard-component')[0]);
92+
93+
expect(container.querySelectorAll('.grid-column-guide')).toHaveLength(
94+
GRID_COLUMN_COUNT,
95+
);
96+
});
7897

79-
it('should call resizeComponent when a child DashboardComponent calls resizeStop', () => {
80-
const resizeComponent = sinon.spy();
81-
const args = { id: 'id', widthMultiple: 1, heightMultiple: 3 };
82-
const wrapper = setup({ resizeComponent });
83-
const dashboardComponent = wrapper.find(DashboardComponent).first();
84-
dashboardComponent.prop('onResizeStop')(args);
98+
test('should call resizeComponent when a child DashboardComponent calls resizeStop', () => {
99+
const resizeComponent = jest.fn();
100+
const { getAllByTestId } = setup({ resizeComponent });
101+
const dashboardComponent = getAllByTestId('mock-dashboard-component')[0];
102+
fireEvent.blur(dashboardComponent);
85103

86-
expect(resizeComponent.callCount).toBe(1);
87-
expect(resizeComponent.getCall(0).args[0]).toEqual({
88-
id: 'id',
89-
width: 1,
90-
height: 3,
91-
});
104+
expect(resizeComponent).toHaveBeenCalledTimes(1);
105+
expect(resizeComponent).toHaveBeenCalledWith({
106+
id: 'id',
107+
width: 1,
108+
height: 3,
92109
});
93110
});

superset-frontend/src/dashboard/components/FiltersBadge/FiltersBadge.test.tsx

+88-109
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717
* under the License.
1818
*/
1919
import React from 'react';
20-
import { shallow } from 'enzyme';
21-
import { Provider } from 'react-redux';
2220
import { Store } from 'redux';
23-
import * as SupersetUI from '@superset-ui/core';
24-
import { styledMount as mount } from 'spec/helpers/theming';
21+
import { render } from 'spec/helpers/testing-library';
2522
import {
2623
CHART_RENDERING_SUCCEEDED,
2724
CHART_UPDATE_SUCCEEDED,
@@ -36,123 +33,105 @@ import { sliceId } from 'spec/fixtures/mockChartQueries';
3633
import { dashboardFilters } from 'spec/fixtures/mockDashboardFilters';
3734
import { dashboardWithFilter } from 'spec/fixtures/mockDashboardLayout';
3835

36+
jest.mock(
37+
'src/dashboard/components/FiltersBadge/DetailsPanel',
38+
() =>
39+
({ children }: { children: React.ReactNode }) =>
40+
<div data-test="mock-details-panel">{children}</div>,
41+
);
42+
3943
const defaultStore = getMockStoreWithFilters();
4044
function setup(store: Store = defaultStore) {
41-
return mount(
42-
<Provider store={store}>
43-
<FiltersBadge chartId={sliceId} />
44-
</Provider>,
45-
);
45+
return render(<FiltersBadge chartId={sliceId} />, { store });
4646
}
4747

48-
describe('FiltersBadge', () => {
49-
// there's this bizarre "active filters" thing
50-
// that doesn't actually use any kind of state management.
51-
// Have to set variables in there.
52-
buildActiveFilters({
53-
dashboardFilters,
54-
components: dashboardWithFilter,
55-
});
56-
57-
beforeEach(() => {
58-
// shallow rendering in enzyme doesn't propagate contexts correctly,
59-
// so we have to mock the hook.
60-
// See https://medium.com/7shifts-engineering-blog/testing-usecontext-react-hook-with-enzyme-shallow-da062140fc83
61-
jest
62-
.spyOn(SupersetUI, 'useTheme')
63-
.mockImplementation(() => SupersetUI.supersetTheme);
64-
});
48+
// there's this bizarre "active filters" thing
49+
// that doesn't actually use any kind of state management.
50+
// Have to set variables in there.
51+
buildActiveFilters({
52+
dashboardFilters,
53+
components: dashboardWithFilter,
54+
});
6555

66-
describe('for dashboard filters', () => {
67-
it("doesn't show number when there are no active filters", () => {
68-
const store = getMockStoreWithFilters();
69-
// start with basic dashboard state, dispatch an event to simulate query completion
70-
store.dispatch({
71-
type: CHART_UPDATE_SUCCEEDED,
72-
key: sliceId,
73-
queriesResponse: [
74-
{
75-
status: 'success',
76-
applied_filters: [],
77-
rejected_filters: [],
78-
},
79-
],
80-
dashboardFilters,
81-
});
82-
const wrapper = shallow(
83-
<Provider store={store}>
84-
<FiltersBadge chartId={sliceId} />,
85-
</Provider>,
86-
);
87-
expect(wrapper.find('[data-test="applied-filter-count"]')).not.toExist();
56+
describe('for dashboard filters', () => {
57+
test('does not show number when there are no active filters', () => {
58+
const store = getMockStoreWithFilters();
59+
// start with basic dashboard state, dispatch an event to simulate query completion
60+
store.dispatch({
61+
type: CHART_UPDATE_SUCCEEDED,
62+
key: sliceId,
63+
queriesResponse: [
64+
{
65+
status: 'success',
66+
applied_filters: [],
67+
rejected_filters: [],
68+
},
69+
],
70+
dashboardFilters,
8871
});
72+
const { queryByTestId } = setup(store);
73+
expect(queryByTestId('applied-filter-count')).not.toBeInTheDocument();
74+
});
8975

90-
it('shows the indicator when filters have been applied', () => {
91-
const store = getMockStoreWithFilters();
92-
// start with basic dashboard state, dispatch an event to simulate query completion
93-
store.dispatch({
94-
type: CHART_UPDATE_SUCCEEDED,
95-
key: sliceId,
96-
queriesResponse: [
97-
{
98-
status: 'success',
99-
applied_filters: [{ column: 'region' }],
100-
rejected_filters: [],
101-
},
102-
],
103-
dashboardFilters,
104-
});
105-
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
106-
const wrapper = setup(store);
107-
expect(wrapper.find('DetailsPanelPopover')).toExist();
108-
expect(
109-
wrapper.find('[data-test="applied-filter-count"] .current'),
110-
).toHaveText('1');
111-
expect(wrapper.find('WarningFilled')).not.toExist();
76+
test('shows the indicator when filters have been applied', () => {
77+
const store = getMockStoreWithFilters();
78+
// start with basic dashboard state, dispatch an event to simulate query completion
79+
store.dispatch({
80+
type: CHART_UPDATE_SUCCEEDED,
81+
key: sliceId,
82+
queriesResponse: [
83+
{
84+
status: 'success',
85+
applied_filters: [{ column: 'region' }],
86+
rejected_filters: [],
87+
},
88+
],
89+
dashboardFilters,
11290
});
91+
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
92+
const { getByTestId } = setup(store);
93+
expect(getByTestId('applied-filter-count')).toHaveTextContent('1');
94+
expect(getByTestId('mock-details-panel')).toBeInTheDocument();
11395
});
96+
});
11497

115-
describe('for native filters', () => {
116-
it("doesn't show number when there are no active filters", () => {
117-
const store = getMockStoreWithNativeFilters();
118-
// start with basic dashboard state, dispatch an event to simulate query completion
119-
store.dispatch({
120-
type: CHART_UPDATE_SUCCEEDED,
121-
key: sliceId,
122-
queriesResponse: [
123-
{
124-
status: 'success',
125-
applied_filters: [],
126-
rejected_filters: [],
127-
},
128-
],
129-
});
130-
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
131-
const wrapper = setup(store);
132-
expect(wrapper.find('[data-test="applied-filter-count"]')).not.toExist();
98+
describe('for native filters', () => {
99+
test('does not show number when there are no active filters', () => {
100+
const store = getMockStoreWithNativeFilters();
101+
// start with basic dashboard state, dispatch an event to simulate query completion
102+
store.dispatch({
103+
type: CHART_UPDATE_SUCCEEDED,
104+
key: sliceId,
105+
queriesResponse: [
106+
{
107+
status: 'success',
108+
applied_filters: [],
109+
rejected_filters: [],
110+
},
111+
],
133112
});
113+
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
114+
const { queryByTestId } = setup(store);
115+
expect(queryByTestId('applied-filter-count')).not.toBeInTheDocument();
116+
});
134117

135-
it('shows the indicator when filters have been applied', () => {
136-
const store = getMockStoreWithNativeFilters();
137-
// start with basic dashboard state, dispatch an event to simulate query completion
138-
store.dispatch({
139-
type: CHART_UPDATE_SUCCEEDED,
140-
key: sliceId,
141-
queriesResponse: [
142-
{
143-
status: 'success',
144-
applied_filters: [{ column: 'region' }],
145-
rejected_filters: [],
146-
},
147-
],
148-
});
149-
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
150-
const wrapper = setup(store);
151-
expect(wrapper.find('DetailsPanelPopover')).toExist();
152-
expect(
153-
wrapper.find('[data-test="applied-filter-count"] .current'),
154-
).toHaveText('1');
155-
expect(wrapper.find('WarningFilled')).not.toExist();
118+
test('shows the indicator when filters have been applied', () => {
119+
const store = getMockStoreWithNativeFilters();
120+
// start with basic dashboard state, dispatch an event to simulate query completion
121+
store.dispatch({
122+
type: CHART_UPDATE_SUCCEEDED,
123+
key: sliceId,
124+
queriesResponse: [
125+
{
126+
status: 'success',
127+
applied_filters: [{ column: 'region' }],
128+
rejected_filters: [],
129+
},
130+
],
156131
});
132+
store.dispatch({ type: CHART_RENDERING_SUCCEEDED, key: sliceId });
133+
const { getByTestId } = setup(store);
134+
expect(getByTestId('applied-filter-count')).toHaveTextContent('1');
135+
expect(getByTestId('mock-details-panel')).toBeInTheDocument();
157136
});
158137
});

0 commit comments

Comments
 (0)