createLoadableRenderer.test.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. import '@testing-library/jest-dom';
  20. import { ComponentType } from 'react';
  21. import mockConsole, { RestoreConsole } from 'jest-mock-console';
  22. import { render as renderTestComponent, screen } from '@testing-library/react';
  23. import createLoadableRenderer, {
  24. LoadableRenderer as LoadableRendererType,
  25. } from '../../../src/chart/components/createLoadableRenderer';
  26. describe('createLoadableRenderer', () => {
  27. function TestComponent() {
  28. return <div className="test-component">test</div>;
  29. }
  30. let loadChartSuccess = jest.fn(() => Promise.resolve(TestComponent));
  31. let render: (loaded: { Chart: ComponentType }) => JSX.Element;
  32. let loading: () => JSX.Element;
  33. let LoadableRenderer: LoadableRendererType<{}>;
  34. let restoreConsole: RestoreConsole;
  35. beforeEach(() => {
  36. restoreConsole = mockConsole();
  37. loadChartSuccess = jest.fn(() => Promise.resolve(TestComponent));
  38. render = jest.fn(loaded => {
  39. const { Chart } = loaded;
  40. return <Chart />;
  41. });
  42. loading = jest.fn(() => <div>Loading</div>);
  43. LoadableRenderer = createLoadableRenderer({
  44. loader: {
  45. Chart: loadChartSuccess,
  46. },
  47. loading,
  48. render,
  49. });
  50. });
  51. afterEach(() => {
  52. restoreConsole();
  53. });
  54. describe('returns a LoadableRenderer class', () => {
  55. it('LoadableRenderer.preload() preloads the lazy-load components', () => {
  56. expect(LoadableRenderer.preload).toBeInstanceOf(Function);
  57. LoadableRenderer.preload();
  58. expect(loadChartSuccess).toHaveBeenCalledTimes(1);
  59. });
  60. it('calls onRenderSuccess when succeeds', async () => {
  61. const onRenderSuccess = jest.fn();
  62. const onRenderFailure = jest.fn();
  63. renderTestComponent(
  64. <LoadableRenderer
  65. onRenderSuccess={onRenderSuccess}
  66. onRenderFailure={onRenderFailure}
  67. />,
  68. );
  69. expect(loadChartSuccess).toHaveBeenCalled();
  70. jest.useRealTimers();
  71. await new Promise(resolve => setTimeout(resolve, 10));
  72. expect(render).toHaveBeenCalledTimes(1);
  73. expect(onRenderSuccess).toHaveBeenCalledTimes(1);
  74. expect(onRenderFailure).not.toHaveBeenCalled();
  75. });
  76. it('calls onRenderFailure when fails', () =>
  77. new Promise(done => {
  78. const loadChartFailure = jest.fn(() =>
  79. Promise.reject(new Error('Invalid chart')),
  80. );
  81. const FailedRenderer = createLoadableRenderer({
  82. loader: {
  83. Chart: loadChartFailure,
  84. },
  85. loading,
  86. render,
  87. });
  88. const onRenderSuccess = jest.fn();
  89. const onRenderFailure = jest.fn();
  90. renderTestComponent(
  91. <FailedRenderer
  92. onRenderSuccess={onRenderSuccess}
  93. onRenderFailure={onRenderFailure}
  94. />,
  95. );
  96. expect(loadChartFailure).toHaveBeenCalledTimes(1);
  97. setTimeout(() => {
  98. expect(render).not.toHaveBeenCalled();
  99. expect(onRenderSuccess).not.toHaveBeenCalled();
  100. expect(onRenderFailure).toHaveBeenCalledTimes(1);
  101. done(undefined);
  102. }, 10);
  103. }));
  104. it('onRenderFailure is optional', () =>
  105. new Promise(done => {
  106. const loadChartFailure = jest.fn(() =>
  107. Promise.reject(new Error('Invalid chart')),
  108. );
  109. const FailedRenderer = createLoadableRenderer({
  110. loader: {
  111. Chart: loadChartFailure,
  112. },
  113. loading,
  114. render,
  115. });
  116. renderTestComponent(<FailedRenderer />);
  117. expect(loadChartFailure).toHaveBeenCalledTimes(1);
  118. setTimeout(() => {
  119. expect(render).not.toHaveBeenCalled();
  120. done(undefined);
  121. }, 10);
  122. }));
  123. it('renders the lazy-load components', () =>
  124. new Promise(done => {
  125. renderTestComponent(<LoadableRenderer />);
  126. // lazy-loaded component not rendered immediately
  127. expect(screen.queryByText('test')).not.toBeInTheDocument();
  128. setTimeout(() => {
  129. // but rendered after the component is loaded.
  130. expect(screen.queryByText('test')).toBeInTheDocument();
  131. done(undefined);
  132. }, 10);
  133. }));
  134. it('does not throw if loaders are empty', () => {
  135. const NeverLoadingRenderer = createLoadableRenderer({
  136. loader: {},
  137. loading,
  138. render: () => <div />,
  139. });
  140. expect(() => renderTestComponent(<NeverLoadingRenderer />)).not.toThrow();
  141. });
  142. });
  143. });