Repository: facebook/react
File: packages/internal-test-utils/internalAct.js (JavaScript)

Code before:
  };

  // TODO: This would be way simpler if we used async/await.
  try {
    const result = scope();
    if (
      typeof result !== 'object' ||
      result === null ||
      typeof (result: any).then !== 'function'
    ) {
      throw new Error(
        'The internal version of `act` used in the React repo must be passed ' +
          "an async function, even if doesn't await anything. This is a " +
          'temporary limitation that will soon be fixed.',
      );
    }
    const thenableResult: Thenable<T> = (result: any);

    return {
      then(resolve: T => mixed, reject: mixed => mixed) {
        thenableResult.then(
          returnValue => {
            flushActWork(
              () => {
                unwind();
                resolve(returnValue);
              },
              error => {
                unwind();
                reject(error);
              },
            );
          },
          error => {
            unwind();
            reject(error);
          },
        );
      },
    };
  } catch (error) {
    unwind();
    throw error;
  }
}

function flushActWork(resolve: () => void, reject: (error: any) => void) {
  if (Scheduler.unstable_hasPendingWork()) {
    try {
      Scheduler.unstable_flushUntilNextPaint();
    } catch (error) {

Review comment (suggestion):
Might be overly pedantic but technically the timer queue isn't empty at this point. `jest.runOnlyPendingTimers()` does not run timers that were scheduled from pending timers. Don't know if that's relevant but I thought it was worth pointing out.

Code after:
  // public version of `act`, though we maybe should in the future.
  await waitForMicrotasks();

  try {
    const result = await scope();

    do {
      // Wait until end of current task/microtask.
      await waitForMicrotasks();

      // $FlowFixMe: Flow doesn't know about global Jest object
      if (jest.isEnvironmentTornDown()) {
        error.message =
          'The Jest environment was torn down before `act` completed. This ' +
          'probably means you forgot to `await` an `act` call.';
        throw error;
      }

      if (!Scheduler.unstable_hasPendingWork()) {
        // $FlowFixMe: Flow doesn't know about global Jest object
        jest.runOnlyPendingTimers();
        if (Scheduler.unstable_hasPendingWork()) {
          // Committing a fallback scheduled additional work. Continue flushing.
        } else {
          // There's no pending work, even after both the microtask queue
          // and the timer queue are empty. Stop flushing.
          break;
        }
      }
      // flushUntilNextPaint stops when React yields execution. Allow microtasks
      // queue to flush before continuing.
      Scheduler.unstable_flushUntilNextPaint();
    } while (true);

    return result;
  } finally {
    const depth = actingUpdatesScopeDepth;
    if (depth === 1) {
      global.IS_REACT_ACT_ENVIRONMENT = previousIsActEnvironment;
    }
    actingUpdatesScopeDepth = depth - 1;

    if (actingUpdatesScopeDepth !== previousActingUpdatesScopeDepth) {
      // if it's _less than_ previousActingUpdatesScopeDepth, then we can
      // assume the 'other' one has warned
      Scheduler.unstable_clearLog();
      error.message =
        'You seem to have overlapping act() calls, this is not supported. ' +
        'Be sure to await previous act() calls before making a new one. ';
      throw error;
    }