0

I am trying to test my lazy initialized component, made with react-lazy-load-image-component using JestJS. Below are my tests:

const viewModel = new VehicleViewModel(vehicleData, {});

const mockOnClick = jest.fn();

const mockStore = configureStore();

let store: MockStore;

beforeEach(() => {
  jest.clearAllMocks();
  store = mockStore(storeInitialState);
});

describe('on component initialization', () => {
  it('renders', () => {
    const { container } = render(
      <Provider store={store}>
        <SearchResult vehicle={viewModel} onClick={mockOnClick} />
      </Provider>
    );
    expect(container).toMatchSnapshot();
  });
});

describe('when the user clicks on the result', () => {
  it('processes an onClick event', () => {
    const { container, getByTestId } = render(
      <Provider store={store}>
        <SearchResult vehicle={viewModel} onClick={mockOnClick} />
      </Provider>
    );
    await waitFor(() => {
      fireEvent.click(getByTestId('search-result'));
    });
    expect(container).toMatchSnapshot();
    expect(mockOnClick).toBeCalled();
  });
});

The component is coded as:

const SearchResult = ({ onClick, vehicle }: SearchResultProps): JSX.Element => {
  const {
    images,
    make,
    model,
    year,
    dealerName,
    city,
    state,
    timeOnMarket,
    mileage,
    price,
  } = vehicle;

  const monthlyPayment = useMonthlyPayment(price);

  return (
    <div className="search-result" data-testid="search-result" onClick={onClick}>
      <style jsx>{styles}</style>
      <div
        className="main-image"
        // replace multiple spaces, if any, with one
        title={`${year || ''} ${make || ''} ${model || ''} image`.replace(/  +/g, ' ')}
      >
        <Carousel images={images} year={year} make={make} model={model} />
        ...
    </div>
  );
};

While the <Carousel /> render is defined as:

  return (
    <LazyLoadComponent>
      <div
        className="carousel-container"
        onMouseEnter={handleMouseEnterEvent}
        onMouseLeave={handleMouseLeaveEvent}
      >
        ...
      </div>
    </LazyLoadComponent>
  );

Without lazy loading, my tests work fine.

Wrapper with lazy loading, my tests fail with: TypeError: Cannot read property 'prototype' of undefined. The error happens on const { container } = render(.... I tried to mock the scroll effect. Did not work for me, yet.

How do I add jest coverage to components using lazy load inside?

Igor Shmukler
  • 1,742
  • 3
  • 15
  • 48

2 Answers2

0

I ended up doing the below inside the actual code:

const TestLasyWrapper = ({ children }: any) => process.env.NODE_ENV !== 'test' ?
  <LazyLoadComponent>{children}</LazyLoadComponent> : 
    <>{children}</>;
Igor Shmukler
  • 1,742
  • 3
  • 15
  • 48
  • I'm having a similar issue but your solution doesn't look like a good option. If I'm not wrong, you have written your component to check if the you're using test environment or not. Isn't that bad? – EternalObserver May 10 '22 at 07:28
  • bad compared to what? – Igor Shmukler May 10 '22 at 12:47
  • I meant component code shouldn't contain code for tests right? I guess it's for the same reason we discourage use of data-testid. I'm fairly new to writing unit-tests so I might be wrong – EternalObserver May 10 '22 at 12:58
-1

You have to 'wait' for you component to be loaded, mounted and rendered. Are you using React Testing Library with Jest? If so, you can use waitFor, which would poll until the item is added to the DOM.

await waitFor(() => expect(screen.findByText('Foo')).toBeInTheDocument());
Steve -Cutter- Blades
  • 5,057
  • 2
  • 26
  • 40
  • my render returns `undefined` though. how do i deal with that? the error happens before the expect, right? how would this work? – Igor Shmukler Nov 16 '21 at 15:44