Unable to test conditional rendering using react-testing-library and jest

182 Views Asked by At

When I try to test conditional rendering of my component I get fail as result, even though it should pass.

Here is my component:

import React, { useEffect, useState } from 'react';

export const Carousel = ({ skeleton }) => {
const [isLoading, setIsLoading] = useState(skeleton !== undefined);

useEffect(() => {
    setIsLoading(false);
}, [])

    return (
    <>
        <Skeleton data-testid="skeleton-wrapper" hidden={!isLoading} />
        <CarouselItem data-testid="carousel-wrapper" hidden={isLoading} />
    </>
  )
}

And this is the TEST:

  it('should switch display property', async () => {
    renderWithTheme(
      <Carousel skeleton={<div>Skeleton children</div>}>
        <CarouselItem>Item 1</CarouselItem>
      </Carousel>,
    );

    expect(screen.getByTestId('skeleton-children')).not.toHaveAttribute('hidden');
    expect(screen.getByTestId('carousel-wrapper')).toHaveAttribute('hidden');
    await waitFor(() => expect(screen.getByTestId('skeleton-wrapper')).toHaveAttribute('hidden'));
    expect(screen.getByTestId('carousel-wrapper')).toBeVisible();
  });

The test fail and it seems that skeleton-wrapper is already hidden, while carousel-wrapper already visibile.

The crazy part is that if I add a setTimeout, it works perfectly. So, if I add the code below, it works perfectly. I'd be appreciate if anyone has a clue that wants to share.

useEffect(() => {
  setTimeout(() => { 
    setIsLoading(false);
    }, 1
   )
}, [])

It's weird if I add the code below, it works perfectly. I'd be appreciate if anyone has a clue that wants to share.

useEffect(() => {
  setTimeout(() => { 
    setIsLoading(false);
    }, 1
   )
}, [])
1

There are 1 best solutions below

1
Chirag Swadia On

If you are setting isLoading to false on component mount, then it's expected that it won't appear when component is rendered by the test.

And it appears with setTimeout because then it becomes async (read event loop) instead of sync as it is now