Skip to content

How to test useEffect with setInterval in React ? #1

@alamenai

Description

@alamenai

The next release will contain a feature of autohiding.

To do this, I've added a prop called autohide:

<Notification {...notification} darkmode autohide >
         <Media src={MEDIA_PATH} link='https://www.github.com' />
     </Notification>

To control autohide, I've created a state in the Notification component :


import React from "react"
import PropTypes from "prop-types"
import { Wrapper } from "./Styled"
import Header from "./Header"
import Body from "./Body"
import Action from "./Action"
import Media from "./Media"
import WithProvider from "./withProvider"

const AVAILABLE_TYPES = [
    "info",
    "warning",
    "success",
    "error"];

const Notification = ({ type, data, style, action, darkmode, autohide, children }) => {

    const [visible, setVisible] = React.useState(true);

    React.useEffect(() => {
        if (autohide) {
            setInterval(() => setVisible(false), 5000);
        }
        return () => {
            clearInterval();
        }
    }, [autohide]);

    const defaultStyle = {
        color: "rgb(0,151,255)",
        rounded: false,
        animation: "left2right",
        duration: 2
    }

    const { title, subtitle, message } = data;
    const { animation, rounded, duration, color } = style || defaultStyle;
    const { name, event } = action;


    if (!AVAILABLE_TYPES.includes(type)) {
        throw new Error(type + ' is not included in notification types');
    }

    if (duration && !(typeof duration === "number") && !Number(duration)) {
        throw new Error("duration should be a number");
    }

    return (visible ? <Wrapper
        type={type}
        animation={animation}
        rounded={rounded}
        color={color}
        darkmode={darkmode}
        duration={duration}>
        <Header title={title} subtitle={subtitle} />
        <Body message={message} />
        {children}
        <Action name={name} onClick={event} />
    </Wrapper> : null)
};

Notification.propTypes = {
    type: PropTypes.string.isRequired,
    data: PropTypes.object.isRequired,
    style: PropTypes.object,
    action: PropTypes.object.isRequired,
    darkmode: PropTypes.bool
};

Notification.defaultProps = {
    type: "info"
};

export default WithProvider(Notification)
export { Notification, Media }

Until now everything is well but when it comes to unit test, I could not test the effect of useEffect in other words how to know that the component will be hidden after 5 seconds :

I tried this code but it does not work :


it('should hide the Notification after 5 seconds', () => {
        jest.advanceTimersByTime(10000);
        expect(setInterval).toHaveBeenCalledTimes(1);
        expect(wrapper.isEmptyRender()).toBe(true);
    });

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions