aboutsummaryrefslogtreecommitdiff
path: root/tests/timing.test.ts
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/timing.test.ts100
1 files changed, 100 insertions, 0 deletions
diff --git a/tests/timing.test.ts b/tests/timing.test.ts
new file mode 100644
index 0000000..e2a0a06
--- /dev/null
+++ b/tests/timing.test.ts
@@ -0,0 +1,100 @@
+
+
+
+
+/*** IMPORT ------------------------------------------- ***/
+
+import { expect, test } from "vitest";
+
+/*** UTILITY ------------------------------------------ ***/
+
+import type { Fetcher, FetcherResult } from "../source/library/fetcher/types.ts";
+import { SessionStore } from "../source/library/state/session.svelte.ts";
+import { createMemoryStorage } from "../source/library/state/storage.ts";
+
+function delay(ms: number): Promise<void> {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
+
+/*** TESTS -------------------------------------------- ***/
+
+test("run() populates timing for a one-shot fetcher", async () => {
+ const store = new SessionStore(createMemoryStorage());
+ const tab = store.active;
+
+ expect(tab).toBeDefined();
+
+ if (!tab)
+ return;
+
+ const fetcher: Fetcher = () => Promise.resolve({ data: { hello: "world" } });
+ const ok = await store.run(fetcher);
+
+ expect(ok).toBe(true);
+ expect(tab.timing).not.toBeNull();
+
+ if (tab.timing === null)
+ return;
+
+ expect(tab.timing.startMs <= tab.timing.firstByteMs).toBe(true);
+ expect(tab.timing.firstByteMs <= tab.timing.endMs).toBe(true);
+ expect(tab.timing.endMs - tab.timing.startMs >= 0).toBe(true);
+ expect(tab.streamIntervals.length).toEqual(0);
+});
+
+test("run() records intervals between async iterable payloads", async () => {
+ const store = new SessionStore(createMemoryStorage());
+ const tab = store.active;
+
+ expect(tab).toBeDefined();
+
+ if (!tab)
+ return;
+
+ async function* stream(): AsyncGenerator<FetcherResult> {
+ yield { data: { n: 1 } };
+ await delay(5);
+ yield { data: { n: 2 } };
+ await delay(5);
+ yield { data: { n: 3 } };
+ }
+
+ const fetcher: Fetcher = () => stream();
+ const ok = await store.run(fetcher);
+
+ expect(ok).toBe(true);
+ expect(tab.streamIntervals.length).toEqual(2);
+ expect(tab.timing).not.toBeNull();
+
+ if (tab.timing === null)
+ return;
+
+ expect(tab.timing.firstByteMs >= tab.timing.startMs).toBe(true);
+ expect(tab.timing.endMs >= tab.timing.firstByteMs).toBe(true);
+
+ for (const delta of tab.streamIntervals)
+ expect(delta >= 0).toBe(true);
+});
+
+test("run() resets timing and streamIntervals on each invocation", async () => {
+ const store = new SessionStore(createMemoryStorage());
+ const tab = store.active;
+
+ expect(tab).toBeDefined();
+
+ if (!tab)
+ return;
+
+ async function* stream(): AsyncGenerator<FetcherResult> {
+ yield { data: { n: 1 } };
+ await delay(5);
+ yield { data: { n: 2 } };
+ }
+
+ await store.run(() => stream());
+ expect(tab.streamIntervals.length).toEqual(1);
+
+ await store.run(() => Promise.resolve({ data: {} }));
+ expect(tab.streamIntervals.length).toEqual(0);
+ expect(tab.timing).not.toBeNull();
+});