refactor(api): extract webhook router support

This commit is contained in:
2026-03-31 13:41:02 +02:00
parent 5e74d61902
commit 67b24443d0
3 changed files with 245 additions and 105 deletions
@@ -0,0 +1,89 @@
import { createHmac } from "node:crypto";
import { TRPCError } from "@trpc/server";
import { describe, expect, it, vi } from "vitest";
import {
buildWebhookCreateData,
buildWebhookTestRequest,
buildWebhookUpdateData,
loadWebhookOrThrow,
sendWebhookTestRequest,
} from "../router/webhook-support.js";
describe("webhook support", () => {
it("builds create and sparse update payloads", () => {
expect(buildWebhookCreateData({
name: "Primary",
url: "https://example.com/webhook",
secret: "secret",
events: ["project.created"],
isActive: true,
})).toEqual({
name: "Primary",
url: "https://example.com/webhook",
secret: "secret",
events: ["project.created"],
isActive: true,
});
expect(buildWebhookUpdateData({
isActive: false,
secret: null,
})).toEqual({
isActive: false,
secret: null,
});
});
it("loads a webhook or throws", async () => {
const db = {
webhook: {
findUnique: vi.fn().mockResolvedValue(null),
},
} as never;
await expect(loadWebhookOrThrow(db, "missing")).rejects.toBeInstanceOf(TRPCError);
});
it("builds a signed test request when a secret exists", async () => {
const timestamp = "2026-03-31T12:00:00.000Z";
const request = await buildWebhookTestRequest({
id: "wh_1",
name: "Primary",
secret: "topsecret",
}, timestamp);
const expectedBody = JSON.stringify({
event: "webhook.test",
timestamp,
payload: {
webhookId: "wh_1",
webhookName: "Primary",
message: "This is a test payload from CapaKraken.",
},
});
expect(request.body).toBe(expectedBody);
expect(request.headers["X-Webhook-Signature"]).toBe(
createHmac("sha256", "topsecret").update(expectedBody).digest("hex"),
);
});
it("reports fetch failures as unsuccessful test results", async () => {
const fetchImpl = vi.fn().mockRejectedValue(new Error("network down"));
await expect(sendWebhookTestRequest({
id: "wh_1",
name: "Primary",
url: "https://example.com/webhook",
secret: null,
}, {
fetchImpl,
timestamp: "2026-03-31T12:00:00.000Z",
timeoutMs: 10,
})).resolves.toEqual({
success: false,
statusCode: 0,
statusText: "network down",
});
});
});