Skip to content

Commit

Permalink
test_runner: preserve original property descriptor
Browse files Browse the repository at this point in the history
PR-URL: #49433
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Raz Luvaton <rluvaton@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
  • Loading branch information
ErickWendel authored and UlisesGascon committed Sep 10, 2023
1 parent 83fc4dc commit 36763fa
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 35 deletions.
196 changes: 161 additions & 35 deletions lib/internal/test_runner/mock/mock_timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const {
DateNow,
FunctionPrototypeApply,
FunctionPrototypeBind,
ObjectDefineProperty,
ObjectGetOwnPropertyDescriptor,
Promise,
SymbolAsyncIterator,
SymbolDispose,
Expand Down Expand Up @@ -239,11 +241,7 @@ class MockTimers {
toFake: {
__proto__: null,
setTimeout: () => {
this.#realSetTimeout = globalThis.setTimeout;
this.#realClearTimeout = globalThis.clearTimeout;
this.#realTimersSetTimeout = nodeTimers.setTimeout;
this.#realTimersClearTimeout = nodeTimers.clearTimeout;
this.#realPromisifiedSetTimeout = nodeTimersPromises.setTimeout;
this.#storeOriginalSetTimeout();

globalThis.setTimeout = this.#setTimeout;
globalThis.clearTimeout = this.#clearTimeout;
Expand All @@ -257,11 +255,7 @@ class MockTimers {
);
},
setInterval: () => {
this.#realSetInterval = globalThis.setInterval;
this.#realClearInterval = globalThis.clearInterval;
this.#realTimersSetInterval = nodeTimers.setInterval;
this.#realTimersClearInterval = nodeTimers.clearInterval;
this.#realPromisifiedSetInterval = nodeTimersPromises.setInterval;
this.#storeOriginalSetInterval();

globalThis.setInterval = this.#setInterval;
globalThis.clearInterval = this.#clearInterval;
Expand All @@ -275,10 +269,7 @@ class MockTimers {
);
},
setImmediate: () => {
this.#realSetImmediate = globalThis.setImmediate;
this.#realClearImmediate = globalThis.clearImmediate;
this.#realTimersSetImmediate = nodeTimers.setImmediate;
this.#realTimersClearImmediate = nodeTimers.clearImmediate;
this.#storeOriginalSetImmediate();

globalThis.setImmediate = this.#setImmediate;
globalThis.clearImmediate = this.#clearImmediate;
Expand All @@ -295,31 +286,13 @@ class MockTimers {
toReal: {
__proto__: null,
setTimeout: () => {
globalThis.setTimeout = this.#realSetTimeout;
globalThis.clearTimeout = this.#realClearTimeout;

nodeTimers.setTimeout = this.#realTimersSetTimeout;
nodeTimers.clearTimeout = this.#realTimersClearTimeout;

nodeTimersPromises.setTimeout = this.#realPromisifiedSetTimeout;
this.#restoreOriginalSetTimeout();
},
setInterval: () => {
globalThis.setInterval = this.#realSetInterval;
globalThis.clearInterval = this.#realClearInterval;

nodeTimers.setInterval = this.#realTimersSetInterval;
nodeTimers.clearInterval = this.#realTimersClearInterval;

nodeTimersPromises.setInterval = this.#realPromisifiedSetInterval;
this.#restoreOriginalSetInterval();
},
setImmediate: () => {
globalThis.setImmediate = this.#realSetImmediate;
globalThis.clearImmediate = this.#realClearImmediate;

nodeTimers.setImmediate = this.#realTimersSetImmediate;
nodeTimers.clearImmediate = this.#realTimersClearImmediate;

nodeTimersPromises.setImmediate = this.#realPromisifiedSetImmediate;
this.#restoreSetImmediate();
},
},
};
Expand All @@ -329,6 +302,159 @@ class MockTimers {
this.#isEnabled = activate;
}

#restoreSetImmediate() {
ObjectDefineProperty(
globalThis,
'setImmediate',
this.#realSetImmediate,
);
ObjectDefineProperty(
globalThis,
'clearImmediate',
this.#realClearImmediate,
);
ObjectDefineProperty(
nodeTimers,
'setImmediate',
this.#realTimersSetImmediate,
);
ObjectDefineProperty(
nodeTimers,
'clearImmediate',
this.#realTimersClearImmediate,
);
ObjectDefineProperty(
nodeTimersPromises,
'setImmediate',
this.#realPromisifiedSetImmediate,
);
}

#restoreOriginalSetInterval() {
ObjectDefineProperty(
globalThis,
'setInterval',
this.#realSetInterval,
);
ObjectDefineProperty(
globalThis,
'clearInterval',
this.#realClearInterval,
);
ObjectDefineProperty(
nodeTimers,
'setInterval',
this.#realTimersSetInterval,
);
ObjectDefineProperty(
nodeTimers,
'clearInterval',
this.#realTimersClearInterval,
);
ObjectDefineProperty(
nodeTimersPromises,
'setInterval',
this.#realPromisifiedSetInterval,
);
}

#restoreOriginalSetTimeout() {
ObjectDefineProperty(
globalThis,
'setTimeout',
this.#realSetTimeout,
);
ObjectDefineProperty(
globalThis,
'clearTimeout',
this.#realClearTimeout,
);
ObjectDefineProperty(
nodeTimers,
'setTimeout',
this.#realSetTimeout,
);
ObjectDefineProperty(
nodeTimers,
'clearTimeout',
this.#realTimersClearTimeout,
);
ObjectDefineProperty(
nodeTimersPromises,
'setTimeout',
this.#realPromisifiedSetTimeout,
);
}

#storeOriginalSetImmediate() {
this.#realSetImmediate = ObjectGetOwnPropertyDescriptor(
globalThis,
'setImmediate',
);
this.#realClearImmediate = ObjectGetOwnPropertyDescriptor(
globalThis,
'clearImmediate',
);
this.#realTimersSetImmediate = ObjectGetOwnPropertyDescriptor(
nodeTimers,
'setImmediate',
);
this.#realTimersClearImmediate = ObjectGetOwnPropertyDescriptor(
nodeTimers,
'clearImmediate',
);
this.#realPromisifiedSetImmediate = ObjectGetOwnPropertyDescriptor(
nodeTimersPromises,
'setImmediate',
);
}

#storeOriginalSetInterval() {
this.#realSetInterval = ObjectGetOwnPropertyDescriptor(
globalThis,
'setInterval',
);
this.#realClearInterval = ObjectGetOwnPropertyDescriptor(
globalThis,
'clearInterval',
);
this.#realTimersSetInterval = ObjectGetOwnPropertyDescriptor(
nodeTimers,
'setInterval',
);
this.#realTimersClearInterval = ObjectGetOwnPropertyDescriptor(
nodeTimers,
'clearInterval',
);
this.#realPromisifiedSetInterval = ObjectGetOwnPropertyDescriptor(
nodeTimersPromises,
'setInterval',
);
}

#storeOriginalSetTimeout() {
this.#realSetTimeout = ObjectGetOwnPropertyDescriptor(
globalThis,
'setTimeout',
);
this.#realClearTimeout = ObjectGetOwnPropertyDescriptor(
globalThis,
'clearTimeout',
);
this.#realTimersSetTimeout = ObjectGetOwnPropertyDescriptor(
nodeTimers,
'setTimeout',
);
this.#realTimersClearTimeout = ObjectGetOwnPropertyDescriptor(
nodeTimers,
'clearTimeout',
);
this.#realPromisifiedSetTimeout = ObjectGetOwnPropertyDescriptor(
nodeTimersPromises,
'setTimeout',
);
}

tick(time = 1) {
if (!this.#isEnabled) {
throw new ERR_INVALID_STATE(
Expand Down
46 changes: 46 additions & 0 deletions test/parallel/test-runner-mock-timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,52 @@ describe('Mock Timers Test Suite', () => {
});
});

it('should check that propertyDescriptor gets back after reseting timers', (t) => {
const getDescriptor = (ctx, fn) => Object.getOwnPropertyDescriptor(ctx, fn);
const getCurrentTimersDescriptors = () => {
const timers = [
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'setImmediate',
'clearImmediate',
];

const globalTimersDescriptors = timers.map((fn) => getDescriptor(global, fn));
const nodeTimersDescriptors = timers.map((fn) => getDescriptor(nodeTimers, fn));
const nodeTimersPromisesDescriptors = timers
.filter((fn) => !fn.includes('clear'))
.map((fn) => getDescriptor(nodeTimersPromises, fn));

return {
global: globalTimersDescriptors,
nodeTimers: nodeTimersDescriptors,
nodeTimersPromises: nodeTimersPromisesDescriptors,
};
};
const before = getCurrentTimersDescriptors();
t.mock.timers.enable();
const during = getCurrentTimersDescriptors();
t.mock.timers.reset();
const after = getCurrentTimersDescriptors();

assert.deepStrictEqual(
before,
after,
);

assert.notDeepStrictEqual(
before,
during,
);

assert.notDeepStrictEqual(
during,
after,
);
});

it('should reset all timers when calling .reset function', (t) => {
t.mock.timers.enable();
const fn = t.mock.fn();
Expand Down

0 comments on commit 36763fa

Please sign in to comment.