Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(frontend): migrate 6 tests from Enzyme to RTL #30151

Merged
merged 13 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 127 additions & 18 deletions superset-frontend/package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,28 @@
* under the License.
*/

import { shallow } from 'enzyme';
import '@testing-library/jest-dom';
import { TooltipFrame } from '@superset-ui/core';
import { render, screen } from '@testing-library/react';

describe('TooltipFrame', () => {
it('sets className', () => {
const wrapper = shallow(
const { container } = render(
<TooltipFrame className="test-class">
<span>Hi!</span>
</TooltipFrame>,
);
expect(wrapper.hasClass('test-class')).toEqual(true);
expect(screen.getByText('Hi!')).toBeInTheDocument();
expect(container.querySelector('.test-class')).toBeInTheDocument();
});

it('renders', () => {
const wrapper = shallow(
const { container } = render(
<TooltipFrame>
<span>Hi!</span>
</TooltipFrame>,
);
const span = wrapper.find('span');
expect(span).toHaveLength(1);
expect(span.text()).toEqual('Hi!');
expect(container.querySelectorAll('span')).toHaveLength(1);
expect(container.querySelector('span')).toHaveTextContent('Hi!');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,53 @@
* under the License.
*/

import { shallow } from 'enzyme';
import '@testing-library/jest-dom';
import { screen, render } from '@testing-library/react';
import { TooltipTable } from '@superset-ui/core';
import { CSSProperties } from 'react';

describe('TooltipTable', () => {
it('sets className', () => {
const wrapper = shallow(<TooltipTable className="test-class" />);
expect(wrapper.render().hasClass('test-class')).toEqual(true);
const { container } = render(<TooltipTable className="test-class" />);
expect(container.querySelector('[class="test-class"]')).toBeInTheDocument();
});

it('renders empty table', () => {
const wrapper = shallow(<TooltipTable />);
expect(wrapper.find('tbody')).toHaveLength(1);
expect(wrapper.find('tr')).toHaveLength(0);
const { container } = render(<TooltipTable />);
expect(container.querySelector('tbody')).toBeInTheDocument();
expect(container.querySelector('tr')).not.toBeInTheDocument();
});

it('renders table with content', () => {
const wrapper = shallow(
<TooltipTable
data={[
{
key: 'Cersei',
keyColumn: 'Cersei',
keyStyle: { padding: '10' },
valueColumn: 2,
valueStyle: { textAlign: 'right' },
},
{
key: 'Jaime',
keyColumn: 'Jaime',
keyStyle: { padding: '10' },
valueColumn: 1,
valueStyle: { textAlign: 'right' },
},
{
key: 'Tyrion',
keyStyle: { padding: '10' },
valueColumn: 2,
},
]}
/>,
);
expect(wrapper.find('tbody')).toHaveLength(1);
expect(wrapper.find('tr')).toHaveLength(3);
expect(wrapper.find('tr > td').first().text()).toEqual('Cersei');
it('renders table with content', async () => {
const data = [
{
key: 'Cersei',
keyColumn: 'Cersei',
keyStyle: { padding: '10' },
valueColumn: 2,
valueStyle: { textAlign: 'right' } as CSSProperties,
},
{
key: 'Jaime',
keyColumn: 'Jaime',
keyStyle: { padding: '10' },
valueColumn: 1,
valueStyle: { textAlign: 'right' } as CSSProperties,
},
{
key: 'Tyrion',
keyStyle: { padding: '10' },
valueColumn: 2,
},
];

render(<TooltipTable data={data} />);

for await (const { key, valueColumn } of data) {
const keyCell = await screen.findByText(key);
const valueCell = keyCell?.nextSibling as HTMLElement;
expect(keyCell).toBeInTheDocument();
expect(valueCell?.textContent).toEqual(String(valueColumn));
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
"peerDependencies": {
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"enzyme": "*",
"react": "^16.13.1"
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^12.1.5",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"publishConfig": {
"access": "public"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
import { shallow } from 'enzyme';

import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
import '@testing-library/jest-dom';
import { screen, render, fireEvent, act } from '@testing-library/react';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import OptionDescription from '../src/OptionDescription';

const defaultProps = {
Expand All @@ -28,20 +28,41 @@ const defaultProps = {
},
};

describe('OptionDescription', () => {
let wrapper;
let props;
beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
jest.useRealTimers();
});

describe('OptionDescription', () => {
beforeEach(() => {
props = { option: { ...defaultProps.option } };
wrapper = shallow(<OptionDescription {...props} />);
const props = { option: { ...defaultProps.option } };
render(
<ThemeProvider theme={supersetTheme}>
<OptionDescription {...props} />
</ThemeProvider>,
);
});

it('renders an InfoTooltipWithTrigger', () => {
expect(wrapper.find(InfoTooltipWithTrigger)).toHaveLength(1);
const tooltipTrigger = screen.getByLabelText('Show info tooltip');
expect(tooltipTrigger).toBeInTheDocument();

// Perform delayed mouse hovering so tooltip could pop out
fireEvent.mouseOver(tooltipTrigger);
act(() => jest.runAllTimers());
fireEvent.mouseOut(tooltipTrigger);

const tooltip = screen.getByRole('tooltip');
expect(tooltip).toBeInTheDocument();
expect(tooltip).toHaveTextContent('Description for some option');
});

it('renders a span with the label', () => {
expect(wrapper.find('.option-label').text()).toBe('Some option');
expect(
screen.getByText('Some option', { selector: 'span' }),
).toBeInTheDocument();
});
});
1 change: 0 additions & 1 deletion superset-frontend/plugins/plugin-chart-table/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"dependencies": {
"@react-icons/all-files": "^4.1.0",
"@types/d3-array": "^2.9.0",
"@types/enzyme": "^3.10.18",
"@types/react-table": "^7.7.20",
"classnames": "^2.5.1",
"d3-array": "^2.4.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
import { CommonWrapper } from 'enzyme';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import TableChart from '../src/TableChart';
import transformProps from '../src/transformProps';
import DateWithFormatter from '../src/utils/DateWithFormatter';
import testData from './testData';
import { mount, ProviderWrapper } from './enzyme';
import { ProviderWrapper } from './testHelpers';

describe('plugin-chart-table', () => {
describe('transformProps', () => {
Expand Down Expand Up @@ -178,39 +178,42 @@ describe('plugin-chart-table', () => {
});

describe('TableChart', () => {
let wrap: CommonWrapper; // the ReactDataTable wrapper
let tree: Cheerio;

it('render basic data', () => {
wrap = mount(
<TableChart {...transformProps(testData.basic)} sticky={false} />,
render(
<ThemeProvider theme={supersetTheme}>
<TableChart {...transformProps(testData.basic)} sticky={false} />,
</ThemeProvider>,
);

tree = wrap.render(); // returns a CheerioWrapper with jQuery-like API
const cells = tree.find('td');
const firstDataRow = screen.getAllByRole('rowgroup')[1];
const cells = firstDataRow.querySelectorAll('td');
expect(cells).toHaveLength(12);
expect(cells.eq(0).text()).toEqual('2020-01-01 12:34:56');
expect(cells.eq(1).text()).toEqual('Michael');
expect(cells[0]).toHaveTextContent('2020-01-01 12:34:56');
expect(cells[1]).toHaveTextContent('Michael');
// number is not in `metrics` list, so it should output raw value
// (in real world Superset, this would mean the column is used in GROUP BY)
expect(cells.eq(2).text()).toEqual('2467063');
expect(cells[2]).toHaveTextContent('2467063');
// should not render column with `.` in name as `undefined`
expect(cells.eq(3).text()).toEqual('foo');
expect(cells.eq(6).text()).toEqual('2467');
expect(cells.eq(8).text()).toEqual('N/A');
expect(cells[3]).toHaveTextContent('foo');
expect(cells[6]).toHaveTextContent('2467');
expect(cells[8]).toHaveTextContent('N/A');
});

it('render advanced data', () => {
wrap = mount(
<TableChart {...transformProps(testData.advanced)} sticky={false} />,
render(
<ThemeProvider theme={supersetTheme}>
<TableChart {...transformProps(testData.advanced)} sticky={false} />,
</ThemeProvider>,
);
tree = wrap.render();
// should successful rerender with new props
const cells = tree.find('td');
expect(tree.find('th').eq(1).text()).toEqual('Sum of Num');
expect(cells.eq(0).text()).toEqual('Michael');
expect(cells.eq(2).text()).toEqual('12.346%');
expect(cells.eq(4).text()).toEqual('2.47k');
const secondColumnHeader = screen.getByText('Sum of Num');
expect(secondColumnHeader).toBeInTheDocument();
expect(secondColumnHeader?.getAttribute('data-column-name')).toEqual('1');

const firstDataRow = screen.getAllByRole('rowgroup')[1];
const cells = firstDataRow.querySelectorAll('td');
expect(cells[0]).toHaveTextContent('Michael');
expect(cells[2]).toHaveTextContent('12.346%');
expect(cells[4]).toHaveTextContent('2.47k');
});

it('render advanced data with currencies', () => {
Expand Down Expand Up @@ -318,9 +321,12 @@ describe('plugin-chart-table', () => {
});

it('render empty data', () => {
wrap.setProps({ ...transformProps(testData.empty), sticky: false });
tree = wrap.render();
expect(tree.text()).toContain('No records found');
render(
<ThemeProvider theme={supersetTheme}>
<TableChart {...transformProps(testData.empty)} sticky={false} />,
</ThemeProvider>,
);
expect(screen.getByText('No records found')).toBeInTheDocument();
});

it('render color with column color formatter', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ReactElement } from 'react';
import { shallow as enzymeShallow, mount as enzymeMount } from 'enzyme';
import {
EmotionCacheProvider,
createEmotionCache,
Expand All @@ -29,12 +27,6 @@ const emotionCache = createEmotionCache({
key: 'test',
});

type optionsType = {
wrappingComponentProps?: any;
wrappingComponent?: ReactElement;
context?: any;
};

export function ProviderWrapper(props: any) {
const { children, theme = supersetTheme } = props;
return (
Expand All @@ -43,25 +35,3 @@ export function ProviderWrapper(props: any) {
</EmotionCacheProvider>
);
}

export function mount(component: ReactElement, options: optionsType = {}) {
return enzymeMount(component, {
...options,
wrappingComponent: ProviderWrapper,
wrappingComponentProps: {
theme: supersetTheme,
...options?.wrappingComponentProps,
},
});
}

export function shallow(component: ReactElement, options: optionsType = {}) {
return enzymeShallow(component, {
...options,
wrappingComponent: ProviderWrapper,
wrappingComponentProps: {
theme: supersetTheme,
...options?.wrappingComponentProps,
},
}).dive();
}
Loading
Loading