64 lines
1.7 KiB
JavaScript
64 lines
1.7 KiB
JavaScript
/**
|
|
* This function replaces the existing `setTimeout` and `setInterval` with wrappers that
|
|
* discount the `ms` passed in by `boost`.
|
|
*
|
|
* For example, if a module has:
|
|
*
|
|
* ```
|
|
* setTimeout(cb, 100);
|
|
* ```
|
|
*
|
|
* But a test has:
|
|
*
|
|
* ```
|
|
* useOverclockTimers(25);
|
|
* ```
|
|
*
|
|
* Then the module's call to `setTimeout` effectively becomes:
|
|
*
|
|
* ```
|
|
* setTimeout(cb, 4);
|
|
* ```
|
|
*
|
|
* It's important to note that the timing for `setTimeout` and order of execution is non-deterministic
|
|
* and discounting the `ms` passed could make this very obvious and expose some underlying issues
|
|
* with flaky failures.
|
|
*
|
|
* WARNING: If flaky spec failures show up in a spec that is using this helper, please consider either:
|
|
*
|
|
* - Refactoring the production code so that it's reactive to state changes, not dependent on timers.
|
|
* - Removing the call to this helper from the spec.
|
|
*
|
|
* @param {Number} boost
|
|
*/
|
|
export const useOverclockTimers = (boost = 50) => {
|
|
if (boost <= 0) {
|
|
throw new Error(`[overclock_timers] boost (${boost}) cannot be <= 0`);
|
|
}
|
|
|
|
let origSetTimeout;
|
|
let origSetInterval;
|
|
const newSetTimeout = (fn, msParam = 0) => {
|
|
const ms = msParam > 0 ? Math.floor(msParam / boost) : msParam;
|
|
|
|
return origSetTimeout(fn, ms);
|
|
};
|
|
const newSetInterval = (fn, msParam = 0) => {
|
|
const ms = msParam > 0 ? Math.floor(msParam / boost) : msParam;
|
|
|
|
return origSetInterval(fn, ms);
|
|
};
|
|
|
|
beforeEach(() => {
|
|
origSetTimeout = global.setTimeout;
|
|
origSetInterval = global.setInterval;
|
|
|
|
global.setTimeout = newSetTimeout;
|
|
global.setInterval = newSetInterval;
|
|
});
|
|
|
|
afterEach(() => {
|
|
global.setTimeout = origSetTimeout;
|
|
global.setInterval = origSetInterval;
|
|
});
|
|
};
|