Skip to main content
Module

std/testing/time_test.ts

Deno standard library
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.import { assert, assertEquals, assertInstanceOf, assertNotEquals, assertRejects, assertStrictEquals,} from "./asserts.ts";import { FakeTime } from "./time.ts";import { _internals } from "./_time.ts";import { assertSpyCall, spy, SpyCall } from "./mock.ts";
function fromNow(): () => number { const start: number = Date.now(); return () => Date.now() - start;}
Deno.test("Date unchanged if FakeTime is uninitialized", () => { assertStrictEquals(Date, _internals.Date);});
Deno.test("Date is fake if FakeTime is initialized", () => { const time = new FakeTime(9001); try { assertNotEquals(Date, _internals.Date); } finally { time.restore(); } assertStrictEquals(Date, _internals.Date);});
Deno.test("Fake Date parse and UTC behave the same", () => { const expectedUTC = Date.UTC(96, 1, 2, 3, 4, 5); const expectedParse = Date.parse("04 Dec 1995 00:12:00 GMT");
const time = new FakeTime(); try { assertEquals( Date.UTC(96, 1, 2, 3, 4, 5), expectedUTC, ); assertEquals( Date.parse("04 Dec 1995 00:12:00 GMT"), expectedParse, ); } finally { time.restore(); }});
Deno.test("Fake Date.now returns current fake time", () => { const time: FakeTime = new FakeTime(9001); const now = spy(_internals.Date, "now"); try { assertEquals(Date.now(), 9001); assertEquals(now.calls.length, 0); time.tick(1523); assertEquals(Date.now(), 10524); assertEquals(now.calls.length, 0); } finally { time.restore(); now.restore(); }});
Deno.test("Fake Date instance methods passthrough to real Date instance methods", () => { const time = new FakeTime(); try { const now = new Date("2020-05-25T05:00:00.12345Z"); assertEquals(now.toISOString(), "2020-05-25T05:00:00.123Z");
const func1 = spy( _internals.Date.prototype, "toISOString", ); try { now.toISOString(); assertSpyCall(func1, 0, { args: [], returned: "2020-05-25T05:00:00.123Z", }); assertInstanceOf(func1.calls[0].self, _internals.Date); } finally { func1.restore(); }
const func2 = spy( _internals.Date.prototype, Symbol.toPrimitive, ); try { Number(now); assertSpyCall(func2, 0, { args: ["number"], returned: 1590382800123, }); } finally { func2.restore(); } } finally { time.restore(); }});
Deno.test("timeout functions unchanged if FakeTime is uninitialized", () => { assertStrictEquals(setTimeout, _internals.setTimeout); assertStrictEquals(clearTimeout, _internals.clearTimeout);});
Deno.test("timeout functions are fake if FakeTime is initialized", () => { const time: FakeTime = new FakeTime(); try { assertNotEquals(setTimeout, _internals.setTimeout); assertNotEquals(clearTimeout, _internals.clearTimeout); } finally { time.restore(); } assertStrictEquals(setTimeout, _internals.setTimeout); assertStrictEquals(clearTimeout, _internals.clearTimeout);});
Deno.test("FakeTime only ticks forward when setting now or calling tick", () => { const time: FakeTime = new FakeTime(); const start: number = Date.now();
try { assertEquals(Date.now(), start); time.tick(5); assertEquals(Date.now(), start + 5); time.now = start + 1000; assertEquals(Date.now(), start + 1000); assert(_internals.Date.now() < start + 1000); } finally { time.restore(); }});
Deno.test("FakeTime controls timeouts", () => { const time: FakeTime = new FakeTime(); const start: number = Date.now(); const cb = spy(fromNow()); const expected: SpyCall[] = [];
try { setTimeout(cb, 1000); time.tick(250); assertEquals(cb.calls, expected); time.tick(250); assertEquals(cb.calls, expected); time.tick(500); expected.push({ args: [], returned: 1000 }); assertEquals(cb.calls, expected); time.tick(2500); assertEquals(cb.calls, expected);
setTimeout(cb, 1000, "a"); setTimeout(cb, 2000, "b"); setTimeout(cb, 1500, "c"); assertEquals(cb.calls, expected); time.tick(2500); expected.push({ args: ["a"], returned: 4500 }); expected.push({ args: ["c"], returned: 5000 }); expected.push({ args: ["b"], returned: 5500 }); assertEquals(cb.calls, expected);
setTimeout(cb, 1000, "a"); setTimeout(cb, 1500, "b"); const timeout: number = setTimeout(cb, 1750, "c"); setTimeout(cb, 2000, "d"); time.tick(1250); expected.push({ args: ["a"], returned: 7000 }); assertEquals(cb.calls, expected); assertEquals(Date.now(), start + 7250); clearTimeout(timeout); time.tick(500); expected.push({ args: ["b"], returned: 7500 }); assertEquals(cb.calls, expected); assertEquals(Date.now(), start + 7750); time.tick(250); expected.push({ args: ["d"], returned: 8000 }); assertEquals(cb.calls, expected); } finally { time.restore(); }});
Deno.test("interval functions unchanged if FakeTime is uninitialized", () => { assertStrictEquals(setInterval, _internals.setInterval); assertStrictEquals(clearInterval, _internals.clearInterval);});
Deno.test("interval functions are fake if FakeTime is initialized", () => { const time: FakeTime = new FakeTime(); try { assertNotEquals(setInterval, _internals.setInterval); assertNotEquals(clearInterval, _internals.clearInterval); } finally { time.restore(); } assertStrictEquals(setInterval, _internals.setInterval); assertStrictEquals(clearInterval, _internals.clearInterval);});
Deno.test("FakeTime controls intervals", () => { const time: FakeTime = new FakeTime(); const cb = spy(fromNow()); const expected: SpyCall[] = []; try { const interval: number = setInterval(cb, 1000); time.tick(250); assertEquals(cb.calls, expected); time.tick(250); assertEquals(cb.calls, expected); time.tick(500); expected.push({ args: [], returned: 1000 }); assertEquals(cb.calls, expected); time.tick(2500); expected.push({ args: [], returned: 2000 }); expected.push({ args: [], returned: 3000 }); assertEquals(cb.calls, expected);
clearInterval(interval); time.tick(1000); assertEquals(cb.calls, expected); } finally { time.restore(); }});
Deno.test("FakeTime calls timeout and interval callbacks in correct order", () => { const time: FakeTime = new FakeTime(); const cb = spy(fromNow()); const timeoutCb = spy(cb); const intervalCb = spy(cb); const expected: SpyCall[] = []; const timeoutExpected: SpyCall[] = []; const intervalExpected: SpyCall[] = []; try { const interval: number = setInterval(intervalCb, 1000); setTimeout(timeoutCb, 500); time.tick(250); assertEquals(intervalCb.calls, intervalExpected); time.tick(250); setTimeout(timeoutCb, 1000); let expect: SpyCall = { args: [], returned: 500 }; expected.push(expect); timeoutExpected.push(expect); assertEquals(cb.calls, expected); assertEquals(timeoutCb.calls, timeoutExpected); assertEquals(cb.calls, expected); assertEquals(intervalCb.calls, intervalExpected); time.tick(500); expect = { args: [], returned: 1000 }; expected.push(expect); intervalExpected.push(expect); assertEquals(cb.calls, expected); assertEquals(intervalCb.calls, intervalExpected); time.tick(2500); expect = { args: [], returned: 1500 }; expected.push(expect); timeoutExpected.push(expect); expect = { args: [], returned: 2000 }; expected.push(expect); intervalExpected.push(expect); expect = { args: [], returned: 3000 }; expected.push(expect); intervalExpected.push(expect); assertEquals(cb.calls, expected); assertEquals(timeoutCb.calls, timeoutExpected); assertEquals(intervalCb.calls, intervalExpected);
clearInterval(interval); time.tick(1000); assertEquals(cb.calls, expected); assertEquals(timeoutCb.calls, timeoutExpected); assertEquals(intervalCb.calls, intervalExpected); } finally { time.restore(); }});
Deno.test("FakeTime restoreFor restores real time temporarily", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now();
try { assertEquals(Date.now(), start); time.tick(1000); assertEquals(Date.now(), start + 1000); assert(_internals.Date.now() < start + 1000); await FakeTime.restoreFor(() => { assert(Date.now() < start + 1000); }); assertEquals(Date.now(), start + 1000); assert(_internals.Date.now() < start + 1000); } finally { time.restore(); }});
Deno.test("delay uses real time", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now();
try { assertEquals(Date.now(), start); await time.delay(20); assert(_internals.Date.now() >= start + 20); assertEquals(Date.now(), start); } finally { time.restore(); }});
Deno.test("delay runs all microtasks before resolving", async () => { const time: FakeTime = new FakeTime();
try { const seq = []; queueMicrotask(() => seq.push(2)); queueMicrotask(() => seq.push(3)); seq.push(1); await time.delay(20); seq.push(4); assertEquals(seq, [1, 2, 3, 4]); } finally { time.restore(); }});
Deno.test("delay with abort", async () => { const time: FakeTime = new FakeTime();
try { const seq = []; const abort = new AbortController(); const { signal } = abort; const delayedPromise = time.delay(100, { signal }); seq.push(1); await FakeTime.restoreFor(() => { setTimeout(() => { seq.push(2); abort.abort(); }, 0); }); await assertRejects( () => delayedPromise, DOMException, "Delay was aborted", ); seq.push(3); assertEquals(seq, [1, 2, 3]); } finally { time.restore(); }});
Deno.test("runMicrotasks runs all microtasks before resolving", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now();
try { const seq = []; queueMicrotask(() => seq.push(2)); queueMicrotask(() => seq.push(3)); seq.push(1); await time.runMicrotasks(); seq.push(4); assertEquals(seq, [1, 2, 3, 4]); assertEquals(Date.now(), start); } finally { time.restore(); }});
Deno.test("tickAsync runs all microtasks and runs timers if ticks past due", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now(); const cb = spy(fromNow()); const expected: SpyCall[] = []; const seq: number[] = [];
try { setTimeout(cb, 1000); queueMicrotask(() => seq.push(2)); queueMicrotask(() => seq.push(3)); seq.push(1); await time.tickAsync(250); seq.push(4); assertEquals(cb.calls, expected); await time.tickAsync(250); assertEquals(cb.calls, expected); queueMicrotask(() => seq.push(6)); seq.push(5); await time.tickAsync(500); seq.push(7); expected.push({ args: [], returned: 1000 }); assertEquals(cb.calls, expected); assertEquals(Date.now(), start + 1000); assertEquals(seq, [1, 2, 3, 4, 5, 6, 7]); } finally { time.restore(); }});
Deno.test("runNext runs next timer without running microtasks", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now(); const cb = spy(fromNow()); const seq: number[] = [];
try { setTimeout(cb, 1000); queueMicrotask(() => seq.push(3)); queueMicrotask(() => seq.push(4)); seq.push(1); time.next(); seq.push(2); const expectedCalls = [{ args: [] as [], returned: 1000 }]; assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1000); await time.runMicrotasks();
queueMicrotask(() => seq.push(7)); queueMicrotask(() => seq.push(8)); seq.push(5); time.next(); seq.push(6); await time.runMicrotasks();
assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1000); assertEquals(seq, [1, 2, 3, 4, 5, 6, 7, 8]); } finally { time.restore(); }});
Deno.test("runNextAsync runs all microtasks and next timer", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now(); const cb = spy(fromNow()); const seq: number[] = [];
try { setTimeout(cb, 1000); queueMicrotask(() => seq.push(2)); queueMicrotask(() => seq.push(3)); seq.push(1); await time.nextAsync(); seq.push(4); const expectedCalls = [{ args: [] as [], returned: 1000 }]; assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1000);
queueMicrotask(() => seq.push(6)); queueMicrotask(() => seq.push(7)); seq.push(5); await time.nextAsync(); seq.push(8);
assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1000); assertEquals(seq, [1, 2, 3, 4, 5, 6, 7, 8]); } finally { time.restore(); }});
Deno.test("runAll runs all timers without running microtasks", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now(); const cb = spy(fromNow()); const seq: number[] = [];
try { setTimeout(cb, 1000); setTimeout(cb, 1500); queueMicrotask(() => seq.push(3)); queueMicrotask(() => seq.push(4)); seq.push(1); time.runAll(); seq.push(2); const expectedCalls = [ { args: [] as [], returned: 1000 }, { args: [] as [], returned: 1500 }, ]; assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1500); await time.runMicrotasks();
queueMicrotask(() => seq.push(7)); queueMicrotask(() => seq.push(8)); seq.push(5); time.runAll(); seq.push(6); await time.runMicrotasks();
assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1500); assertEquals(seq, [1, 2, 3, 4, 5, 6, 7, 8]); } finally { time.restore(); }});
Deno.test("runAllAsync runs all microtasks and timers", async () => { const time: FakeTime = new FakeTime(); const start: number = Date.now(); const cb = spy(fromNow()); const seq: number[] = [];
try { setTimeout(cb, 1000); setTimeout(cb, 1500); queueMicrotask(() => seq.push(2)); queueMicrotask(() => seq.push(3)); seq.push(1); await time.runAllAsync(); seq.push(4); const expectedCalls = [ { args: [] as [], returned: 1000 }, { args: [] as [], returned: 1500 }, ]; assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1500);
queueMicrotask(() => seq.push(6)); queueMicrotask(() => seq.push(7)); seq.push(5); await time.runAllAsync(); seq.push(8);
assertEquals(cb.calls, expectedCalls); assertEquals(Date.now(), start + 1500); assertEquals(seq, [1, 2, 3, 4, 5, 6, 7, 8]); } finally { time.restore(); }});