| 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); |
| }); |
| }); |
| }); |