diff --git a/src/flush-micro-tasks.ts b/src/flush-micro-tasks.ts new file mode 100644 index 000000000..08295740b --- /dev/null +++ b/src/flush-micro-tasks.ts @@ -0,0 +1,30 @@ +import { setImmediate } from './helpers/timers'; + +export function flushMicroTasks() { + return new Promise((resolve) => setImmediate(resolve)); +} + +/** + * @deprecated To be removed in the next major release. + */ +type Thenable = { then: (callback: () => T) => unknown }; + +/** + * This legacy implementation of `flushMicroTasks` is used for compatibility with + * older versions of React Native (pre 0.71) which uses Promise polyfil. + * + * For users with older version of React Native there is a workaround of using our own + * Jest preset instead the `react-native` one, but requiring such change would be a + * breaking change for existing users. + * + * @deprecated To be removed in the next major release. + */ +export function flushMicroTasksLegacy(): Thenable { + return { + // using "thenable" instead of a Promise, because otherwise it breaks when + // using "modern" fake timers + then(resolve) { + setImmediate(resolve); + }, + }; +} diff --git a/src/flushMicroTasks.ts b/src/flushMicroTasks.ts deleted file mode 100644 index 7b964a9d6..000000000 --- a/src/flushMicroTasks.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { setImmediate } from './helpers/timers'; - -type Thenable = { then: (callback: () => T) => unknown }; - -export function flushMicroTasks(): Thenable { - return { - // using "thenable" instead of a Promise, because otherwise it breaks when - // using "modern" fake timers - then(resolve) { - setImmediate(resolve); - }, - }; -} diff --git a/src/index.ts b/src/index.ts index f2f2f342c..4d699fcdd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import { cleanup } from './pure'; -import { flushMicroTasks } from './flushMicroTasks'; +import { flushMicroTasksLegacy } from './flush-micro-tasks'; import { getIsReactActEnvironment, setReactActEnvironment } from './act'; if (typeof process === 'undefined' || !process.env?.RNTL_SKIP_AUTO_CLEANUP) { @@ -11,7 +11,7 @@ if (typeof process === 'undefined' || !process.env?.RNTL_SKIP_AUTO_CLEANUP) { if (typeof afterEach === 'function') { // eslint-disable-next-line no-undef afterEach(async () => { - await flushMicroTasks(); + await flushMicroTasksLegacy(); cleanup(); }); } diff --git a/src/waitFor.ts b/src/waitFor.ts index ac515fe86..d28a80c63 100644 --- a/src/waitFor.ts +++ b/src/waitFor.ts @@ -1,12 +1,11 @@ /* globals jest */ import act, { setReactActEnvironment, getIsReactActEnvironment } from './act'; import { getConfig } from './config'; -import { flushMicroTasks } from './flushMicroTasks'; +import { flushMicroTasks, flushMicroTasksLegacy } from './flush-micro-tasks'; import { ErrorWithStack, copyStackTrace } from './helpers/errors'; import { setTimeout, clearTimeout, - setImmediate, jestFakeTimersAreEnabled, } from './helpers/timers'; import { checkReactVersionAtLeast } from './react-versions'; @@ -89,7 +88,7 @@ function waitForInternal( // of parallelization so we're fine. // https://stackoverflow.com/a/59243586/971592 // eslint-disable-next-line no-await-in-loop - await new Promise((resolve) => setImmediate(resolve)); + await flushMicroTasks(); } } else { overallTimeoutTimer = setTimeout(handleTimeout, timeout); @@ -207,7 +206,7 @@ export default async function waitFor( try { const result = await waitForInternal(expectation, optionsWithStackTrace); // Flush the microtask queue before restoring the `act` environment - await flushMicroTasks(); + await flushMicroTasksLegacy(); return result; } finally { setReactActEnvironment(previousActEnvironment);