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()
);
});