diff --git a/replay-ui/src/__tests__/api.test.ts b/replay-ui/src/__tests__/api.test.ts index 80235a6..d209811 100644 --- a/replay-ui/src/__tests__/api.test.ts +++ b/replay-ui/src/__tests__/api.test.ts @@ -1,10 +1,37 @@ import { describe, it, expect } from "bun:test"; -import { screenshotUrl } from "../api"; +import { getJson, screenshotUrl } from "../api"; describe("screenshotUrl", () => { - it("encodes runId and name", () => { - expect(screenshotUrl("run-1", "step-00001.png")).toBe( - "/api/runs/run-1/screenshots/step-00001.png", + it("percent-encodes runId and name with reserved characters", () => { + expect(screenshotUrl("run #1/a", "step 00001.png")).toBe( + "/api/runs/run%20%231%2Fa/screenshots/step%2000001.png", ); }); }); + +describe("getJson", () => { + it("returns the decoded body on a 200 response", async () => { + const server = Bun.serve({ + port: 0, + fetch: () => Response.json({ ok: true }), + }); + try { + const body = await getJson<{ ok: boolean }>(server.url.href); + expect(body).toEqual({ ok: true }); + } finally { + server.stop(true); + } + }); + + it("throws on a non-ok response instead of returning the error body", async () => { + const server = Bun.serve({ + port: 0, + fetch: () => new Response("boom", { status: 500 }), + }); + try { + await expect(getJson(server.url.href)).rejects.toThrow("500"); + } finally { + server.stop(true); + } + }); +}); diff --git a/replay-ui/src/api.ts b/replay-ui/src/api.ts index ba1e97a..77af9a9 100644 --- a/replay-ui/src/api.ts +++ b/replay-ui/src/api.ts @@ -1,6 +1,6 @@ import type { Run, RunSummary, Step } from "./types"; -async function getJson(path: string): Promise { +export async function getJson(path: string): Promise { const response = await fetch(path, { headers: { Accept: "application/json" } }); if (!response.ok) { throw new Error(`request failed: ${response.status} ${response.statusText} (${path})`);