aboutsummaryrefslogtreecommitdiff
path: root/tests/timing.test.ts
diff options
context:
space:
mode:
authornetop://ウィビ <paul@webb.page>2026-04-24 16:37:33 -0700
committernetop://ウィビ <paul@webb.page>2026-04-24 16:37:33 -0700
commit510fd8cbe53abb39cba2c7cbaaefcf2783dc0066 (patch)
tree8f753a33c475b285f2a297785d34cda3b0a8faed /tests/timing.test.ts
parent261f3bdb77799009344aab4a60686b7186ebd3b0 (diff)
downloadgraphiql-510fd8cbe53abb39cba2c7cbaaefcf2783dc0066.tar.gz
graphiql-510fd8cbe53abb39cba2c7cbaaefcf2783dc0066.zip
Implement v0.6-1.0: shortcuts, format, export/import, splitter, timing, APQ
- v0.6: matchShortcut + format(); Cmd+Shift+Enter/W/F + Cmd+Alt+arrows - v0.7: SessionStore.exportAll/importTabs with version-1 validator - v0.8: Splitter component + four resize handles persisted under layout.* - v0.10: createApqFetcher (HTTP-only) wrapping shared http-body helpers - Drop .svelte re-exports from index.ts for multi-entry JSR/npm publishing
Diffstat (limited to 'tests/timing.test.ts')
-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();
+});