Skip to content

runWithRealTimers's setImmediate polyfill will still use the fake setTimeout #1767

Open
@edkimmel

Description

@edkimmel

Describe the bug

This happens for both the setimmediate node_module and RNTL's polyfill.

The root cause for both flows is the same - we are not capturing the underlying timer functions while the timers are real. When we actually call setImmediate (Like in the automatic cleanup), it's back to referencing fake timers.

For the setimmediate module case, you can see that registerImmediate doesn't capture the global functions it will use, it just pulls from global state on demand.

For the polyfill you can see the same issue, it will end up pulling the fake setTimeout when called later on, when fake timers are re-applied.

A potential fix for this is to only use RNTL's polyfill, and to capture setTimeout while inside the bind function.

function bindTimeFunctions() {
  // We need to capture setTimeout now, while jest timers are known to be real
  const setTimeout = globalObj.setTimeout
  function setImmediatePolyfill(fn) {
    return setTimeout(fn, 0);
  }
  return {
    clearTimeoutFn: globalObj.clearTimeout,
    setImmediateFn: setImmediatePolyfill,
    setTimeoutFn: setTimeout
  };
}

Expected behavior

I would expect the functions returned by runWithRealTimers to always use real timers, regardless of the future state.

Steps to Reproduce

Enable testEnvironment: 'jsdom' in jest.config.js
Use fake timers and the RNTL auto cleanup. The test will time out waiting for flushMicroTasks's setImmediate, which is using fake timers accidentally.

Screenshots

Versions

13.2 & 14.0 alpha

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions