1

Here's a Toast component that is displayed when a button is clicked and disappears after x seconds. For testing waitFor is used to change showToast state to true when API call is successful, then waitForElementToBeRemoved is used to check if the toast component has been removed from the screen.

Tests are passing, so the assumption is that showToast became false. But when I check the jest coverage, that line hide={() => setShowToast(false)} is still shown as uncovered.

What would be needed to cover that line using testing-library?

Toast component:

const Toast = props => {
  const { message, color, iconName, show, hide, background, timeoutDuration, ...rest } = props;

  useEffect(() => {
    if (show) {
      const timeout = setTimeout(() => {
        hide();
      }, timeoutDuration * 1000 + 1000);
      return () => clearTimeout(timeout);
    }
  }, [show, timeoutDuration]);

  return (
    <Box>
      <Container {...rest} show={show} timeoutDuration={timeoutDuration}>
        <StyledToast py={1} px={2} background={background} bgColor={colors[color]} role="alert">
          <StyledIcon name={iconName} color={color} />
          <StyledP color={color} fontSize={[14, 16]}>
            {message}
          </StyledP>
        </StyledToast>
      </Container>
    </Box>
  );
};

Component that uses Toast:

const [showToast, setShowToast] = useState(false);

{showToast && (
        <Toast
          message="Store Settings successfully updated!"
          color="green"
          iconName="check-circle"
          background={true}
          show={showToast}
          timeoutDuration={10}
          zIndex={10}
          hide={() => setShowToast(false)}
        />
      )}

Test:

import '@testing-library/jest-dom';
import { render, screen, fireEvent, waitFor, waitForElementToBeRemoved } from '@testing-library/preact';
    
test('Clicking OK displays Toast and it disappears', async () => {
        global.fetch = jest.fn(() =>
          Promise.resolve({
            json: () => Promise.resolve({ data: {}] } })
          })
        );
    
        const CheckBox = screen.getByTestId('some-id');
        fireEvent.click(CheckBox);
        const SaveButton = screen.getByText('Save');
        fireEvent.click(SaveButton);
        expect(screen.getByText('OK')).toBeTruthy();
        const OKButton = screen.getByText('OK');
        fireEvent.click(OKButton);
    
        await waitFor(() => {
          expect(screen.getByText('Store Settings successfully updated!')).toBeInTheDocument();
        }, { timeout: 11000 });
    
        waitForElementToBeRemoved(screen.getByText('Store Settings successfully updated!')).then(() =>
          expect(screen.queryByText('Store Settings successfully updated!')).not.toBeInTheDocument()
        );
        
      });

1 Answers1

0

Try

await waitForElementToBeRemoved(...)

since waitForElementToBeRemoved is an async function call