假计时器不会在 Jest 中正确触发 setTimeout 调用

我有一个简单的 React UI-less 组件,用于显示传递操作的状态。有 4 种状态 - 待处理、正在运行、已完成、失败。这里的主要问题是运行和完成状态必须至少持续一段时间(例如 2 秒)。我正在尝试使用 Jest (26.6.3) 及其假计时器来测试此行为,但我无法让它工作。


组件代码:


export const TaskState = {

    PENDING: "pending",

    RUNNING: "running",

    FINISHED: "finished",

    FAILED: "failed",

};


export default function Task({ action, minDelay = 2000, children }) {

    const [state, setState] = useState(TaskState.PENDING);

    const [error, setError] = useState(null);

    const timeoutHandle = useRef(null);


    useEffect(() => {

        return () => {

            if (timeoutHandle.current) {

                clearTimeout(timeoutHandle.current);

            }

        };

    }, []);


    const resetState = () => {

        setState(TaskState.PENDING);

        setError(null);

    };


    const onSuccess = () => {

        setState(TaskState.FINISHED);

        timeoutHandle.current = setTimeout(resetState, minDelay);

    };


    const onError = errMsg => {

        setState(TaskState.FAILED);

        setError(errMsg);

    };


    const startAction = () => {

        setState(TaskState.RUNNING);

        const start = performance.now();

        let err = null;

        try {

            action();

        } catch (e) {

            err = e.message;

        } finally {

            const end = performance.now();

            const elapsedTime = end - start;

            const delayTime = minDelay - elapsedTime;

            if (elapsedTime < minDelay && minDelay > 0) {

                timeoutHandle.current = setTimeout(() => {

                    err ? onError(err) : onSuccess();

                }, delayTime);

            } else {

                err ? onError(err) : onSuccess();

            }

        }

    };


    return children({

        state,

        error,

        startAction,

    });

}

Task.propTypes = {

    action: PropTypes.func.isRequired,

    minDelay: PropTypes.number,

    children: PropTypes.func.isRequired,

};

调用操作回调,执行从挂起到运行的状态转换,但不执行从运行到失败的下一个状态转换。当我手动测试它时它有效。


最小示例 - https://codesandbox.io/s/heuristic-khorana-7vygv?file=/src/App.js


暮色呼如
浏览 129回答 1
1回答

吃鸡游戏

在全局窗口对象上正确调用 setTimeout 解决了该问题。这在实际应用程序中并不重要,但对于专门修补 window.setTimeout 和其他函数的 jest 假定时器来说很重要。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript