diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dd152ef8534..8d40be406241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Fixes +- `[jest-fake-timers]` `getTimerCount` will not include cancelled immediates ([#8764](https://github.com/facebook/jest/pull/8764)) + ### Chore & Maintenance ### Performance diff --git a/packages/jest-fake-timers/src/__tests__/jestFakeTimers.test.ts b/packages/jest-fake-timers/src/__tests__/jestFakeTimers.test.ts index d011eee66d2d..56171b64251f 100644 --- a/packages/jest-fake-timers/src/__tests__/jestFakeTimers.test.ts +++ b/packages/jest-fake-timers/src/__tests__/jestFakeTimers.test.ts @@ -1303,5 +1303,22 @@ describe('FakeTimers', () => { expect(timers.getTimerCount()).toEqual(3); }); + + it('not includes cancelled immediates', () => { + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); + + timers.useFakeTimers(); + + global.setImmediate(() => {}); + expect(timers.getTimerCount()).toEqual(1); + timers.clearAllTimers(); + + expect(timers.getTimerCount()).toEqual(0); + }); }); }); diff --git a/packages/jest-fake-timers/src/jestFakeTimers.ts b/packages/jest-fake-timers/src/jestFakeTimers.ts index aea098eadf3d..11e20e7b7ebb 100644 --- a/packages/jest-fake-timers/src/jestFakeTimers.ts +++ b/packages/jest-fake-timers/src/jestFakeTimers.ts @@ -53,7 +53,6 @@ const setGlobal = ( }; export default class FakeTimers { - private _cancelledImmediates!: Record; private _cancelledTicks!: Record; private _config: StackTraceConfig; private _disposed?: boolean; @@ -105,9 +104,7 @@ export default class FakeTimers { } clearAllTimers() { - this._immediates.forEach(immediate => - this._fakeClearImmediate(immediate.uuid), - ); + this._immediates = []; this._timers.clear(); } @@ -118,7 +115,6 @@ export default class FakeTimers { reset() { this._cancelledTicks = {}; - this._cancelledImmediates = {}; this._now = 0; this._ticks = []; this._immediates = []; @@ -177,10 +173,10 @@ export default class FakeTimers { } private _runImmediate(immediate: Tick) { - if (!this._cancelledImmediates.hasOwnProperty(immediate.uuid)) { - // Callback may throw, so update the map prior calling. - this._cancelledImmediates[immediate.uuid] = true; + try { immediate.callback(); + } finally { + this._fakeClearImmediate(immediate.uuid); } } @@ -402,7 +398,9 @@ export default class FakeTimers { } private _fakeClearImmediate(uuid: TimerID) { - this._cancelledImmediates[uuid] = true; + this._immediates = this._immediates.filter( + immediate => immediate.uuid !== uuid, + ); } private _fakeNextTick(callback: Callback, ...args: Array) { @@ -432,19 +430,20 @@ export default class FakeTimers { return null; } - const uuid = this._uuidCounter++; + const uuid = String(this._uuidCounter++); this._immediates.push({ callback: () => callback.apply(null, args), - uuid: String(uuid), + uuid, }); - const cancelledImmediates = this._cancelledImmediates; this._timerAPIs.setImmediate(() => { - if (!cancelledImmediates.hasOwnProperty(uuid)) { - // Callback may throw, so update the map prior calling. - cancelledImmediates[String(uuid)] = true; - callback.apply(null, args); + if (this._immediates.find(x => x.uuid === uuid)) { + try { + callback.apply(null, args); + } finally { + this._fakeClearImmediate(uuid); + } } });