diff --git a/tests/jetstream_webhooks_test.ts b/tests/jetstream_webhooks_test.ts new file mode 100644 index 0000000..2b6c1f6 --- /dev/null +++ b/tests/jetstream_webhooks_test.ts @@ -0,0 +1,94 @@ +import { assertEquals } from "@std/assert"; +import { dispatchAll } from "../src/jetstream/webhooks.ts"; +import { installFetchStub, jsonResponse } from "./_helpers/fetch_stub.ts"; + +Deno.test("dispatchAll is a noop on empty webhook list", async () => { + const stub = installFetchStub(() => + jsonResponse({ should: "not be called" }) + ); + try { + await dispatchAll([], { event: "create" }, "label"); + assertEquals(stub.calls.length, 0); + } finally { + stub.restore(); + } +}); + +Deno.test( + "dispatchAll sends Authorization Bearer only when token is present", + async () => { + const stub = installFetchStub(() => new Response(null, { status: 204 })); + try { + await dispatchAll( + [ + { method: "POST", url: "https://a.example/hook" }, + { + method: "POST", + url: "https://b.example/hook", + token: "shh", + }, + ], + { event: "create" }, + "label", + ); + assertEquals(stub.calls.length, 2); + const [first, second] = stub.calls; + assertEquals(first.headers.get("Authorization"), null); + assertEquals(second.headers.get("Authorization"), "Bearer shh"); + assertEquals(first.headers.get("Content-Type"), "application/json"); + } finally { + stub.restore(); + } + }, +); + +Deno.test( + "dispatchAll omits body and Content-Type for GET and HEAD", + async () => { + const stub = installFetchStub(() => new Response(null, { status: 204 })); + try { + await dispatchAll( + [ + { method: "GET", url: "https://a.example/ping" }, + { method: "HEAD", url: "https://b.example/ping" }, + ], + { event: "create", data: "ignored" }, + "label", + ); + assertEquals(stub.calls.length, 2); + for (const call of stub.calls) { + assertEquals(call.body, ""); + assertEquals(call.headers.get("Content-Type"), null); + } + } finally { + stub.restore(); + } + }, +); + +Deno.test( + "dispatchAll uses Promise.allSettled — one rejection does not abort others", + async () => { + const stub = installFetchStub((req) => { + if (req.url === "https://reject.example/hook") { + return Promise.reject(new Error("connection refused")); + } + return Promise.resolve(new Response(null, { status: 204 })); + }); + try { + await dispatchAll( + [ + { method: "POST", url: "https://reject.example/hook" }, + { method: "POST", url: "https://ok.example/hook" }, + ], + { event: "create" }, + "label", + ); + assertEquals(stub.calls.length, 2); + const urls = stub.calls.map((c) => c.url); + assertEquals(urls.includes("https://ok.example/hook"), true); + } finally { + stub.restore(); + } + }, +);