51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import { test, beforeEach, afterEach } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { ApiError, ControlPlaneClient } from "../src/api.js";
|
|
|
|
const originalFetch = globalThis.fetch;
|
|
|
|
beforeEach(() => {
|
|
globalThis.fetch = originalFetch;
|
|
});
|
|
|
|
afterEach(() => {
|
|
globalThis.fetch = originalFetch;
|
|
});
|
|
|
|
test("ControlPlaneClient reports non-JSON error bodies without rereading them", async () => {
|
|
globalThis.fetch = (async () =>
|
|
new Response("<h1>upstream unavailable</h1>", {
|
|
status: 502,
|
|
statusText: "Bad Gateway",
|
|
headers: { "content-type": "text/html" },
|
|
})) as typeof fetch;
|
|
|
|
await assert.rejects(
|
|
() => new ControlPlaneClient("https://api.example.test", "token").me(),
|
|
(err) => {
|
|
assert.ok(err instanceof ApiError);
|
|
assert.equal(err.status, 502);
|
|
assert.match(err.message, /upstream unavailable/);
|
|
assert.doesNotMatch(err.message, /Body is unusable/);
|
|
return true;
|
|
},
|
|
);
|
|
});
|
|
|
|
test("ControlPlaneClient forwards bearer tokens and extracts JSON error detail", async () => {
|
|
globalThis.fetch = (async (_input: RequestInfo | URL, init?: RequestInit) => {
|
|
const headers = init?.headers as Record<string, string>;
|
|
assert.equal(headers.authorization, "Bearer access-token");
|
|
return new Response(JSON.stringify({ detail: "keycloak email is not verified" }), {
|
|
status: 403,
|
|
headers: { "content-type": "application/json" },
|
|
});
|
|
}) as typeof fetch;
|
|
|
|
await assert.rejects(
|
|
() => new ControlPlaneClient("https://api.example.test", "access-token").me(),
|
|
/API 403: keycloak email is not verified/,
|
|
);
|
|
});
|