blob: 31b590baa5d30901255b47cf59d4b8be6dd0317c [file] [log] [blame]
import React from 'react';
import { mount } from 'enzyme';
import mockConsole, { RestoreConsole } from 'jest-mock-console';
import { triggerResizeObserver } from 'resize-observer-polyfill';
import ErrorBoundary from 'react-error-boundary';
import { promiseTimeout } from '@superset-ui/core';
import { SuperChart } from '@superset-ui/core/src/chart';
import RealSuperChart, { WrapperProps } from '@superset-ui/core/src/chart/components/SuperChart';
import NoResultsComponent from '@superset-ui/core/src/chart/components/NoResultsComponent';
import { ChartKeys, DiligentChartPlugin, BuggyChartPlugin } from './MockChartPlugins';
const DEFAULT_QUERY_DATA = { data: ['foo', 'bar'] };
const DEFAULT_QUERIES_DATA = [{ data: ['foo', 'bar'] }, { data: ['foo2', 'bar2'] }];
function expectDimension(renderedWrapper: Cheerio, width: number, height: number) {
expect(renderedWrapper.find('.dimension').text()).toEqual([width, height].join('x'));
}
describe('SuperChart', () => {
const plugins = [
new DiligentChartPlugin().configure({ key: ChartKeys.DILIGENT }),
new BuggyChartPlugin().configure({ key: ChartKeys.BUGGY }),
];
let restoreConsole: RestoreConsole;
beforeAll(() => {
plugins.forEach(p => {
p.unregister().register();
});
});
afterAll(() => {
plugins.forEach(p => {
p.unregister();
});
});
beforeEach(() => {
restoreConsole = mockConsole();
});
afterEach(() => {
restoreConsole();
});
describe('includes ErrorBoundary', () => {
let expectedErrors = 0;
let actualErrors = 0;
function onError(e: Event) {
e.preventDefault();
actualErrors += 1;
}
beforeEach(() => {
expectedErrors = 0;
actualErrors = 0;
window.addEventListener('error', onError);
});
afterEach(() => {
window.removeEventListener('error', onError);
// eslint-disable-next-line jest/no-standalone-expect
expect(actualErrors).toBe(expectedErrors);
expectedErrors = 0;
});
it('renders default FallbackComponent', () => {
expectedErrors = 1;
jest.spyOn(RealSuperChart.defaultProps, 'FallbackComponent');
const wrapper = mount(
<SuperChart
chartType={ChartKeys.BUGGY}
queriesData={[DEFAULT_QUERY_DATA]}
width="200"
height="200"
/>,
);
const renderedWrapper = wrapper.render();
return promiseTimeout(() => {
expect(renderedWrapper.find('div.test-component')).toHaveLength(0);
expect(RealSuperChart.defaultProps.FallbackComponent).toHaveBeenCalledTimes(1);
}, 100);
});
it('renders custom FallbackComponent', () => {
expectedErrors = 1;
const CustomFallbackComponent = jest.fn(() => <div>Custom Fallback!</div>);
const wrapper = mount(
<SuperChart
chartType={ChartKeys.BUGGY}
queriesData={[DEFAULT_QUERY_DATA]}
width="200"
height="200"
FallbackComponent={CustomFallbackComponent}
/>,
);
return promiseTimeout(() => {
expect(wrapper.render().find('div.test-component')).toHaveLength(0);
expect(CustomFallbackComponent).toHaveBeenCalledTimes(1);
});
});
it('call onErrorBoundary', () => {
expectedErrors = 1;
const handleError = jest.fn();
mount(
<SuperChart
chartType={ChartKeys.BUGGY}
queriesData={[DEFAULT_QUERY_DATA]}
width="200"
height="200"
onErrorBoundary={handleError}
/>,
);
return promiseTimeout(() => {
expect(handleError).toHaveBeenCalledTimes(1);
});
});
it('does not include ErrorBoundary if told so', () => {
expectedErrors = 1;
const inactiveErrorHandler = jest.fn();
const activeErrorHandler = jest.fn();
mount(
<ErrorBoundary onError={activeErrorHandler}>
<SuperChart
disableErrorBoundary
chartType={ChartKeys.BUGGY}
queriesData={[DEFAULT_QUERY_DATA]}
width="200"
height="200"
onErrorBoundary={inactiveErrorHandler}
/>
</ErrorBoundary>,
);
return promiseTimeout(() => {
expect(activeErrorHandler).toHaveBeenCalledTimes(1);
expect(inactiveErrorHandler).toHaveBeenCalledTimes(0);
});
});
});
it('passes the props to renderer correctly', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
width={101}
height={118}
formData={{ abc: 1 }}
/>,
);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 101, 118);
});
});
it('passes the props with multiple queries to renderer correctly', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={DEFAULT_QUERIES_DATA}
width={101}
height={118}
formData={{ abc: 1 }}
/>,
);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 101, 118);
});
});
it('passes the props with multiple queries and single query to renderer correctly (backward compatibility)', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={DEFAULT_QUERIES_DATA}
width={101}
height={118}
formData={{ abc: 1 }}
/>,
);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 101, 118);
});
});
describe('supports NoResultsComponent', () => {
it('renders NoResultsComponent when queriesData is missing', () => {
const wrapper = mount(<SuperChart chartType={ChartKeys.DILIGENT} width="200" height="200" />);
expect(wrapper.find(NoResultsComponent)).toHaveLength(1);
});
it('renders NoResultsComponent when queriesData data is null', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[{ data: null }]}
width="200"
height="200"
/>,
);
expect(wrapper.find(NoResultsComponent)).toHaveLength(1);
});
});
describe('supports dynamic width and/or height', () => {
it('works with width and height that are numbers', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
width={100}
height={100}
/>,
);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 100, 100);
});
});
it('works when width and height are percent', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
debounceTime={1}
width="100%"
height="100%"
/>,
);
triggerResizeObserver();
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 300, 300);
}, 100);
});
it('works when only width is percent', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
debounceTime={1}
width="50%"
height="125"
/>,
);
triggerResizeObserver([{ contentRect: { height: 125, width: 150 } }]);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
const boundingBox = renderedWrapper.find('div.test-component').parent().parent().parent();
expect(boundingBox.css('width')).toEqual('50%');
expect(boundingBox.css('height')).toEqual('125px');
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 150, 125);
}, 100);
});
it('works when only height is percent', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
debounceTime={1}
width="50"
height="25%"
/>,
);
triggerResizeObserver([{ contentRect: { height: 75, width: 50 } }]);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
const boundingBox = renderedWrapper.find('div.test-component').parent().parent().parent();
expect(boundingBox.css('width')).toEqual('50px');
expect(boundingBox.css('height')).toEqual('25%');
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 50, 75);
}, 100);
});
it('works when width and height are not specified', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
debounceTime={1}
/>,
);
triggerResizeObserver();
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 300, 400);
}, 100);
});
});
describe('supports Wrapper', () => {
function MyWrapper({ width, height, children }: WrapperProps) {
return (
<div>
<div className="wrapper-insert">
{width}x{height}
</div>
{children}
</div>
);
}
it('works with width and height that are numbers', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
width={100}
height={100}
Wrapper={MyWrapper}
/>,
);
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.wrapper-insert')).toHaveLength(1);
expect(renderedWrapper.find('div.wrapper-insert').text()).toEqual('100x100');
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 100, 100);
}, 100);
});
it('works when width and height are percent', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queriesData={[DEFAULT_QUERY_DATA]}
debounceTime={1}
width="100%"
height="100%"
Wrapper={MyWrapper}
/>,
);
triggerResizeObserver();
return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
expect(renderedWrapper.find('div.wrapper-insert')).toHaveLength(1);
expect(renderedWrapper.find('div.wrapper-insert').text()).toEqual('300x300');
expect(renderedWrapper.find('div.test-component')).toHaveLength(1);
expectDimension(renderedWrapper, 300, 300);
}, 100);
});
});
});