diff options
| author | netop://ウィビ <paul@webb.page> | 2026-04-24 16:37:33 -0700 |
|---|---|---|
| committer | netop://ウィビ <paul@webb.page> | 2026-04-24 16:37:33 -0700 |
| commit | 510fd8cbe53abb39cba2c7cbaaefcf2783dc0066 (patch) | |
| tree | 8f753a33c475b285f2a297785d34cda3b0a8faed /tests/timing.test.ts | |
| parent | 261f3bdb77799009344aab4a60686b7186ebd3b0 (diff) | |
| download | graphiql-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.ts | 100 |
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(); +}); |