blob: d8f78451791066690ed2f39a44d8113f84d3043b [file] [log] [blame]
import PropTypes from 'prop-types';
import React from 'react';
import { mount } from 'enzyme';
import reactify, { RenderFuncType } from '@superset-ui/core/src/chart/components/reactify';
describe('reactify(renderFn)', () => {
const renderFn: RenderFuncType<{ content?: string }> = jest.fn((element, props) => {
const container = element;
container.innerHTML = '';
const child = document.createElement('b');
child.innerHTML = props.content ?? '';
container.append(child);
});
renderFn.displayName = 'BoldText';
renderFn.propTypes = {
content: PropTypes.string,
};
renderFn.defaultProps = {
content: 'ghi',
};
const willUnmountCb = jest.fn();
const TheChart = reactify(renderFn);
const TheChartWithWillUnmountHook = reactify(renderFn, { componentWillUnmount: willUnmountCb });
class TestComponent extends React.PureComponent<{}, { content: string }> {
constructor(props = {}) {
super(props);
this.state = { content: 'abc' };
}
componentDidMount() {
setTimeout(() => {
this.setState({ content: 'def' });
}, 10);
}
render() {
const { content } = this.state;
return <TheChart id="test" content={content} />;
}
}
class AnotherTestComponent extends React.PureComponent<{}, {}> {
render() {
return <TheChartWithWillUnmountHook id="another_test" />;
}
}
it('returns a React component class', () =>
new Promise(done => {
const wrapper = mount(<TestComponent />);
expect(renderFn).toHaveBeenCalledTimes(1);
expect(wrapper.html()).toEqual('<div id="test"><b>abc</b></div>');
setTimeout(() => {
expect(renderFn).toHaveBeenCalledTimes(2);
expect(wrapper.html()).toEqual('<div id="test"><b>def</b></div>');
wrapper.unmount();
done();
}, 20);
}));
describe('displayName', () => {
it('has displayName if renderFn.displayName is defined', () => {
expect(TheChart.displayName).toEqual('BoldText');
});
it('does not have displayName if renderFn.displayName is not defined', () => {
const AnotherChart = reactify(() => {});
expect(AnotherChart.displayName).toBeUndefined();
});
});
describe('propTypes', () => {
it('has propTypes if renderFn.propTypes is defined', () => {
/* eslint-disable-next-line react/forbid-foreign-prop-types */
expect(Object.keys(TheChart.propTypes ?? {})).toEqual(['id', 'className', 'content']);
});
it('does not have propTypes if renderFn.propTypes is not defined', () => {
const AnotherChart = reactify(() => {});
/* eslint-disable-next-line react/forbid-foreign-prop-types */
expect(Object.keys(AnotherChart.propTypes ?? {})).toEqual(['id', 'className']);
});
});
describe('defaultProps', () => {
it('has defaultProps if renderFn.defaultProps is defined', () => {
expect(TheChart.defaultProps).toBe(renderFn.defaultProps);
const wrapper = mount(<TheChart id="test" />);
expect(wrapper.html()).toEqual('<div id="test"><b>ghi</b></div>');
});
it('does not have defaultProps if renderFn.defaultProps is not defined', () => {
const AnotherChart = reactify(() => {});
expect(AnotherChart.defaultProps).toBeUndefined();
});
});
it('does not try to render if not mounted', () => {
const anotherRenderFn = jest.fn();
const AnotherChart = reactify(anotherRenderFn); // enables valid new AnotherChart() call
// @ts-ignore
new AnotherChart({ id: 'test' }).execute();
expect(anotherRenderFn).not.toHaveBeenCalled();
});
it('calls willUnmount hook when it is provided', () =>
new Promise(done => {
const wrapper = mount(<AnotherTestComponent />);
setTimeout(() => {
wrapper.unmount();
expect(willUnmountCb).toHaveBeenCalledTimes(1);
done();
}, 20);
}));
});