From 5337d167569216aed143b7658b5fdcefcfe6f24c Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 11 Sep 2023 15:00:57 +1000 Subject: [PATCH] chore: `fetchValues()` JSDocs and tests (#566) --- utils/http.ts | 16 ++++++++++++++ utils/http_test.ts | 52 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/utils/http.ts b/utils/http.ts index 3c0d5e2d3e41..2937cd3448b1 100644 --- a/utils/http.ts +++ b/utils/http.ts @@ -44,6 +44,22 @@ export function getCursor(url: URL) { return url.searchParams.get("cursor") ?? ""; } +/** + * Returns the values and cursor for the resource of a given endpoint. In the + * backend, the request handler collects these values and cursor by iterating + * through a {@linkcode Deno.KvListIterator} + * + * @example + * ```ts + * import { fetchValues } from "@/utils/http.ts"; + * import type { Item } from "@/utils/db.ts"; + * + * const body = await fetchValues("https://hunt.deno.land/api/items", "12345"); + * body.values[0].id; // Returns "13f34b7e-5563-4001-98ed-9ee04d7af717" + * body.values[0].url; // Returns "http://example.com" + * body.cursor; // Returns "12346" + * ``` + */ export async function fetchValues(endpoint: string, cursor: string) { let url = endpoint; if (cursor !== "") url += "?cursor=" + cursor; diff --git a/utils/http_test.ts b/utils/http_test.ts index 9645b06f4ad7..232c0adacb8c 100644 --- a/utils/http_test.ts +++ b/utils/http_test.ts @@ -1,6 +1,15 @@ // Copyright 2023 the Deno authors. All rights reserved. MIT license. -import { getCursor, redirect } from "./http.ts"; -import { assert, assertEquals } from "std/assert/mod.ts"; +import { + assertSpyCall, + assertSpyCalls, + returnsNext, + stub, +} from "std/testing/mock.ts"; +import { fetchValues, getCursor, redirect } from "./http.ts"; +import { assert, assertEquals, assertRejects } from "std/assert/mod.ts"; +import { Status } from "$fresh/server.ts"; +import { genNewItem } from "@/utils/db_test.ts"; +import { Item } from "@/utils/db.ts"; Deno.test("[http] redirect() defaults", () => { const location = "/hello-there"; @@ -27,3 +36,42 @@ Deno.test("[http] getCursor()", () => { assertEquals(getCursor(new URL("http://example.com")), ""); assertEquals(getCursor(new URL("http://example.com?cursor=here")), "here"); }); + +Deno.test("[http] fetchValues()", async () => { + const resp1 = Promise.resolve( + new Response(null, { status: Status.NotFound }), + ); + const resp2Body = { + values: [genNewItem(), genNewItem()], + cursor: crypto.randomUUID(), + }; + const resp2Cursor = crypto.randomUUID(); + const resp2 = Promise.resolve(Response.json(resp2Body)); + const fetchStub = stub( + globalThis, + "fetch", + returnsNext([resp1, resp2]), + ); + const endpoint = "http://localhost"; + await assertRejects( + async () => await fetchValues(endpoint, ""), + Error, + `Request failed: GET ${endpoint}`, + ); + assertEquals( + await fetchValues(endpoint + "/api/items", resp2Cursor), + resp2Body, + ); + + fetchStub.restore(); + + assertSpyCall(fetchStub, 0, { + args: [endpoint], + returned: resp1, + }); + assertSpyCall(fetchStub, 1, { + args: [endpoint + "/api/items?cursor=" + resp2Cursor], + returned: resp2, + }); + assertSpyCalls(fetchStub, 2); +});