From 75b76f68b66eb452dd37b2922f1e6b75fe29364e Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 3 Oct 2023 10:28:02 +0200 Subject: [PATCH] Unify advanceTimersByTime and flushPromises Ports https://github.com/testing-library/dom-testing-library/pull/1229 --- src/__tests__/waitFor.test.js | 8 +------- src/__tests__/waitForDOM.test.js | 15 ++++++--------- .../{waitForNode.js => waitForNode.test.js} | 14 ++++---------- src/waitFor.ts | 11 ++--------- 4 files changed, 13 insertions(+), 35 deletions(-) rename src/__tests__/{waitForNode.js => waitForNode.test.js} (96%) diff --git a/src/__tests__/waitFor.test.js b/src/__tests__/waitFor.test.js index 7fa247b..1533de0 100644 --- a/src/__tests__/waitFor.test.js +++ b/src/__tests__/waitFor.test.js @@ -176,15 +176,9 @@ test('does not work after it resolves', async () => { /** @type {import('../').FakeClock} */ const jestFakeClock = { - advanceTimersByTime: timeoutMS => { + advanceTimersByTime: async timeoutMS => { jest.advanceTimersByTime(timeoutMS) }, - flushPromises: () => { - return new Promise(r => { - setTimeout(r, 0) - jest.advanceTimersByTime(0) - }) - }, } describe.each([ ['real timers', {useTimers: () => jest.useRealTimers(), clock: undefined}], diff --git a/src/__tests__/waitForDOM.test.js b/src/__tests__/waitForDOM.test.js index b2b22c8..0ab9d17 100644 --- a/src/__tests__/waitForDOM.test.js +++ b/src/__tests__/waitForDOM.test.js @@ -65,6 +65,11 @@ function waitFor( return error } + /** + * @template T + * @param {() => T} cb + * @returns T + */ function advanceTimersWrapper(cb) { // /dom config. /react uses act() here return cb() @@ -78,16 +83,8 @@ function waitFor( /** @type {import('../').FakeClock} */ const jestFakeClock = { advanceTimersByTime: timeoutMS => { - advanceTimersWrapper(() => { - jest.advanceTimersByTime(timeoutMS) - }) - }, - flushPromises: () => { return advanceTimersWrapper(async () => { - await new Promise(r => { - setTimeout(r, 0) - jest.advanceTimersByTime(0) - }) + jest.advanceTimersByTime(timeoutMS) }) }, } diff --git a/src/__tests__/waitForNode.js b/src/__tests__/waitForNode.test.js similarity index 96% rename from src/__tests__/waitForNode.js rename to src/__tests__/waitForNode.test.js index c5c8d83..2bbc744 100644 --- a/src/__tests__/waitForNode.js +++ b/src/__tests__/waitForNode.test.js @@ -37,15 +37,9 @@ function jestFakeTimersAreEnabled() { function waitFor(callback, options) { /** @type {import('../').FakeClock} */ const jestFakeClock = { - advanceTimersByTime: timeoutMS => { + advanceTimersByTime: async timeoutMS => { jest.advanceTimersByTime(timeoutMS) }, - flushPromises: () => { - return new Promise(r => { - setTimeout(r, 0) - jest.advanceTimersByTime(0) - }) - }, } const clock = jestFakeTimersAreEnabled() ? jestFakeClock : undefined @@ -210,15 +204,15 @@ describe('using fake modern timers', () => { // An actual test would not have any frames pointing to this test. expect(waitForError.stack).toMatchInlineSnapshot(` Error: Timed out in waitFor. - at handleTimeout (/src/waitFor.ts:146:17) + at handleTimeout (/src/waitFor.ts:139:17) at callTimer (/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:729:24) at doTickInner (/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:1289:29) at doTick (/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:1370:20) at Object.tick (/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:1378:20) at FakeTimers.advanceTimersByTime (/node_modules/@jest/fake-timers/build/modernFakeTimers.js:101:19) at Object.advanceTimersByTime (/node_modules/jest-runtime/build/index.js:2228:26) - at Object.advanceTimersByTime (/src/__tests__/waitForNode.js:41:12) - at /src/waitFor.ts:80:15 + at Object.advanceTimersByTime (/src/__tests__/waitForNode.test.js:41:12) + at /src/waitFor.ts:85:21 at new Promise () `) }) diff --git a/src/waitFor.ts b/src/waitFor.ts index 5b662bf..0d7a633 100644 --- a/src/waitFor.ts +++ b/src/waitFor.ts @@ -7,7 +7,7 @@ function copyStackTrace(target: Error, source: Error) { } export interface FakeClock { - advanceTimersByTime: (timeoutMS: number) => void + advanceTimersByTime: (timeoutMS: number) => Promise flushPromises: () => Promise } @@ -77,19 +77,12 @@ function waitForImpl( // waiting or when we've timed out. // eslint-disable-next-line no-unmodified-loop-condition, @typescript-eslint/no-unnecessary-condition while (!finished && !signal?.aborted) { - clock.advanceTimersByTime(interval) - - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- No it isn't - if (finished) { - break - } - // In this rare case, we *need* to wait for in-flight promises // to resolve before continuing. We don't need to take advantage // of parallelization so we're fine. // https://stackoverflow.com/a/59243586/971592 // eslint-disable-next-line no-await-in-loop - await clock.flushPromises() + await clock.advanceTimersByTime(interval) } }