import {render, screen} from 'sentry-test/reactTestingLibrary'; import LazyLoad from 'sentry/components/lazyLoad'; type TestProps = { testProp?: boolean; }; function FooComponent({}: TestProps) { return
my foo component
; } function BarComponent({}: TestProps) { return
my bar component
; } type ResolvedComponent = {default: React.ComponentType}; type GetComponent = () => Promise; describe('LazyLoad', function () { it('renders with a loading indicator when promise is not resolved yet', function () { const importTest = new Promise(() => {}); const getComponent = () => importTest; render(); // Should be loading expect(screen.getByTestId('loading-indicator')).toBeInTheDocument(); }); it('renders when given a promise of a "foo" component', async function () { let doResolve: (c: ResolvedComponent) => void; const importFoo = new Promise(resolve => { doResolve = resolve; }); render( importFoo} />); // Should be loading expect(screen.getByTestId('loading-indicator')).toBeInTheDocument(); // resolve with foo doResolve!({default: FooComponent}); expect(await screen.findByText('my foo component')).toBeInTheDocument(); }); it('renders with error message when promise is rejected', async function () { // eslint-disable-next-line no-console jest.spyOn(console, 'error').mockImplementation(jest.fn()); const getComponent = jest.fn( () => new Promise((_resolve, reject) => reject(new Error('Could not load component')) ) ); try { render(); } catch (err) { // ignore } expect( await screen.findByText('There was an error loading a component.') ).toBeInTheDocument(); // eslint-disable-next-line no-console expect(console.error).toHaveBeenCalled(); // @ts-expect-error // eslint-disable-next-line no-console console.error.mockRestore(); }); it('refetches only when component changes', async function () { let doResolve: (c: ResolvedComponent) => void; const importFoo = new Promise(resolve => { doResolve = resolve; }); // First render Foo const {rerender} = render( importFoo} />); expect(screen.getByTestId('loading-indicator')).toBeInTheDocument(); // resolve with foo doResolve!({default: FooComponent}); expect(await screen.findByText('my foo component')).toBeInTheDocument(); // Re-render with Bar const importBar = new Promise(resolve => { doResolve = resolve; }); rerender( importBar} />); expect(screen.getByTestId('loading-indicator')).toBeInTheDocument(); // resolve with bar doResolve!({default: BarComponent}); expect(await screen.findByText('my bar component')).toBeInTheDocument(); // Update component prop to a mock to make sure it isn't re-called const getComponent2: GetComponent = jest.fn( () => new Promise(() => {}) ); rerender(); expect(getComponent2).toHaveBeenCalledTimes(1); // Does not refetch on other prop changes rerender(); expect(getComponent2).toHaveBeenCalledTimes(1); }); });