Fake Clock For Deterministic Timer Tests
A controllable clock that makes timer dependent logic testable without real waiting, and drives pending callbacks in exact order.
Code
export class FakeClock {
constructor(start = 0) {
if (!Number.isFinite(start)) throw new TypeError("start must be a finite number");
this.now = start;
this.timers = [];
this.seq = 0;
}
setTimeout(fn, delay) {
if (!Number.isFinite(delay) || delay <= 0) {
throw new RangeError("delay must be a positive number");
}
const entry = { id: ++this.seq, due: this.now + delay, fn };
this.timers.push(entry);
this.timers.sort((a, b) => a.due - b.due || a.id - b.id);
return entry.id;
}
clearTimeout(id) {
this.timers = this.timers.filter((t) => t.id !== id);
}
advance(ms) {
if (!Number.isFinite(ms) || ms < 0) throw new RangeError("ms must be >= 0");
const target = this.now + ms;
for (;;) {
const next = this.timers[0];
if (!next || next.due > target) break;
this.timers.shift();
this.now = next.due;
next.fn();
}
this.now = target;
}
get pending() {
return this.timers.length;
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.