6

I need a way to test a component in which two other components are lazy loaded.

We are using webpack module federation. So here ComponentOne and ComponentTwo are micro-frontends that are lazy loaded inside the App component. So the App component here is the container application that contains both apps and provides routing between them.

My App.tsx looks like this:

import { Suspense, lazy } from 'react';
import { Route, Routes } from 'react-router-dom';

const ComponentOne = lazy(() => import('components/ComponentOne));
const ComponentTwo = lazy(() => import('components/ComponeentTwo'));

export const App = () => {
  return (
    <Suspense fallback={<div>FallbackDummy</div>}>
      <Routes>
        <Route path="/" element={<ComponentOne />} />
        <Route path="/two" element={<ComponentTwo />} />
      </Routes>
    </Suspense>
  );
};

This App component is used within my bootstrap.tsx file like this:

import { render } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

import { App } from './app/app';

render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root'),
);

My App.test.tsx looks like this:

import { Suspense } from 'react';
import {
  render,
  RenderResult,
} from '@testing-library/react';
import { App } from './App';
import '@testing-library/jest-dom';

describe('App component', () => {
  let testedComponent: RenderResult;

  beforeEach(() => {
    testedComponent= render(
      <Suspense fallback={<div>FallbackDummy</div>}>
        <App />
      </Suspense>
    );
  });

  test('should match snapshot', () => {
    expect(testedComponent).toMatchSnapshot();
  });
});

The test runs without the <Routes> and <Route> components (so only wrapped in ). But I can't manage to use the router in my tests.

0

1 Answer 1

2

I found this question while trying to test a regular lazy-loaded component, and I found this answer here that worked for me. Basically, you need to use the waitFor function in react-testing-library so that everything loads up before completing your expect call.

Here are the relevant snippets from the answer linked above:

LazyLoad.jsx:

import React, {lazy} from 'react'
const LazyComponent = lazy(() => import('./LazyComponent'))
const LazyLoad = () => {
   return (
      <div>
         <div> Lazy component is here: </div>
         <React.Suspense fallback={null}>
             <LazyComponent />
         </React.Suspense>
      </div>
   )
}
export default LazyLoad

LazyComponent.jsx:

import React from 'react'
export default () => <div>I am lazy ! </div>

LazyLoad.spec.jsx:

import React from 'react'
import {render, waitFor } from 'react-testing-library'
import LazyLoad from 'LazyLoad'

test('renders lazy component', async () => {
    const { getByText } = render(<LazyLoad />)
    await waitFor(() => expect(getByText('I am lazy !' )).toBeInTheDocument())
})

Not the answer you're looking for? Browse other questions tagged or ask your own question.