describe("Timer", () => {
describe("Synchronous APIs", () => {
describe("setTimeout", () => {
it("should execute callback after delay", (done) => {
const start = Date.now();
const timeoutId = setTimeout(() => {
const elapsed = Date.now() - start;
assert.ok(
elapsed >= 100 && elapsed <= 150,
"setTimeout should wait between 100-150ms",
);
done();
}, 100);
assert.ok(
typeof timeoutId === "number",
"setTimeout should return a number id",
);
});
it("should handle clearing timeout", (done) => {
let called = false;
const timeoutId = setTimeout(() => {
called = true;
}, 50);
clearTimeout(timeoutId);
setTimeout(() => {
assert.ok(
!called,
"Callback should not be called after clearTimeout",
);
done();
}, 100);
});
});
describe("setInterval", () => {
it("should execute callback repeatedly", (done) => {
const results = [];
const intervalId = setInterval(() => {
results.push(Date.now());
if (results.length >= 3) {
clearInterval(intervalId);
for (let i = 1; i < results.length; i++) {
const diff = results[i] - results[i - 1];
assert.ok(
diff >= 45,
"Interval between values should be at least 45ms",
);
}
done();
}
}, 50);
assert.ok(
typeof intervalId === "number",
"setInterval should return a number id",
);
});
it("should handle clearing interval", (done) => {
let count = 0;
const intervalId = setInterval(() => {
count++;
}, 50);
setTimeout(() => {
clearInterval(intervalId);
const currentCount = count;
setTimeout(() => {
assert.equal(
count,
currentCount,
"Count should not increase after clearInterval",
);
done();
}, 100);
}, 125);
});
});
describe("edge cases", () => {
it("should handle clearing non-existent timers", () => {
clearTimeout(999999);
clearInterval(999999);
});
});
});
describe("Asynchronous APIs", () => {
describe("timers.setTimeout", () => {
it("should resolve after delay", async () => {
const start = Date.now();
const now = await timers.setTimeout(100);
const elapsed = Date.now() - start;
assert.ok(
elapsed >= 100 && elapsed <= 150,
"setTimeout should wait between 100-150ms",
);
assert.ok(
now >= start && now <= Date.now(),
"Resolved value should be a valid timestamp",
);
});
it("should handle zero delay", async () => {
const start = Date.now();
const now = await timers.setTimeout(0);
assert.ok(
now >= start && now <= Date.now(),
"Resolved value should be a valid timestamp",
);
});
it("should handle negative delay", async () => {
const start = Date.now();
const now = await timers.setTimeout(-100);
const elapsed = Date.now() - start;
assert.ok(elapsed >= 0, "Negative delay should be treated as 0");
assert.ok(
now >= start && now <= Date.now(),
"Resolved value should be a valid timestamp",
);
});
});
describe("timers.setImmediate", () => {
it("should execute on next tick", async () => {
const start = Date.now();
const now = await timers.setImmediate();
assert.ok(
now >= start && now <= Date.now(),
"Resolved value should be a valid timestamp",
);
});
it("should execute after current task", async () => {
const order = [];
const promise = timers.setImmediate();
order.push(1);
await promise;
order.push(2);
assert.equal(
order.join(","),
"1,2",
"setImmediate should execute after current task",
);
});
});
describe("timers.setInterval", () => {
it("should create async iterator with correct timing", async () => {
const start = Date.now();
const interval = timers.setInterval(50);
const times = [];
for await (const now of interval) {
assert.ok(
now >= start && now <= Date.now(),
"Iterator value should be a valid timestamp",
);
times.push(now);
if (times.length >= 3) break;
}
assert.equal(times.length, 3, "Should collect 3 interval values");
for (let i = 1; i < times.length; i++) {
const diff = times[i] - times[i - 1];
assert.ok(
diff >= 40, `Interval between values should be at least 40ms (got ${diff}ms)`,
);
}
});
it("should execute repeatedly", async () => {
const interval = timers.setInterval(50);
let count = 0;
for await (const _ of interval) {
count++;
if (count >= 3) break;
}
assert.equal(count, 3, "Should execute 3 times");
});
it("should handle break in loop", async () => {
const interval = timers.setInterval(50);
let count = 0;
for await (const _ of interval) {
count++;
break;
}
assert.equal(count, 1, "Should stop after break");
});
});
});
});