Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/api/src/webhookDeliveryQueue.test.ts
T

125 lines
3.8 KiB
TypeScript

import { beforeEach, describe, expect, test, vi } from "vitest";
import { buildRetryJobOptions } from "@hivegrid/queue";
import { buildLegacyEventWebhookAttemptDeliveryJob, queueLegacyEventWebhookAttemptDelivery } from "./webhookDeliveryQueue.js";
import type { LegacyEventWebhookAttempt } from "@hivegrid/db/event-webhook-attempts.server";
const attempt = {
id: "attempt_123",
endpoint: "https://example.test/webhooks/events",
tenantId: "tenant_123",
} satisfies LegacyEventWebhookAttempt;
const body = {
id: "evt_123",
type: "member.created",
};
beforeEach(() => {
vi.clearAllMocks();
});
describe("buildLegacyEventWebhookAttemptDeliveryJob", () => {
test("builds a deliver-webhook descriptor for legacy attempts", () => {
expect(buildLegacyEventWebhookAttemptDeliveryJob(attempt, body, "req_webhook_123")).toEqual({
queueName: "hivegrid.email",
jobName: "deliver-webhook",
payload: {
kind: "webhook.deliver",
url: attempt.endpoint,
method: "POST",
eventName: "legacy.event_webhook_attempt",
body,
tenantId: attempt.tenantId,
metadata: {
legacyAttemptId: attempt.id,
legacyAttemptTenantId: attempt.tenantId,
requestId: "req_webhook_123",
},
},
});
});
test("omits requestId metadata when requestId is absent", () => {
expect(buildLegacyEventWebhookAttemptDeliveryJob(attempt, body).payload.metadata).toEqual({
legacyAttemptId: attempt.id,
legacyAttemptTenantId: attempt.tenantId,
});
});
});
describe("queueLegacyEventWebhookAttemptDelivery", () => {
test("returns typed non-enqueued result when Redis env is absent", async () => {
const result = await queueLegacyEventWebhookAttemptDelivery({
attempt,
body,
env: {},
});
expect(result).toEqual({
enqueued: false,
reason: "missing-redis-connection",
});
});
test("enqueues on an injected queue without touching process environment", async () => {
const queue = buildQueue();
const job = { id: "job_123" };
queue.add.mockResolvedValue(job);
const result = await queueLegacyEventWebhookAttemptDelivery({
attempt,
body,
requestId: "req_enqueue_123",
queue,
});
const descriptor = buildLegacyEventWebhookAttemptDeliveryJob(attempt, body, "req_enqueue_123");
expect(queue.add).toHaveBeenCalledWith(
"deliver-webhook",
descriptor.payload,
// priority is resolved from attempt.tenantId; without a registered
// plan lookup it falls back to NORMAL (5).
{ ...buildRetryJobOptions(descriptor), removeOnComplete: 10_000, jobId: attempt.id, priority: 5 }
);
expect(result).toEqual({
enqueued: true,
job,
});
expect(queue.close).not.toHaveBeenCalled();
});
test("propagates enqueue failures for injected queues", async () => {
const error = new Error("enqueue failed");
const queue = buildQueue();
queue.add.mockRejectedValue(error);
await expect(
queueLegacyEventWebhookAttemptDelivery({
attempt,
body,
queue,
})
).rejects.toThrow(error);
const descriptor = buildLegacyEventWebhookAttemptDeliveryJob(attempt, body);
expect(queue.add).toHaveBeenCalledWith(
"deliver-webhook",
expect.objectContaining({
kind: "webhook.deliver",
}),
{ ...buildRetryJobOptions(descriptor), removeOnComplete: 10_000, jobId: attempt.id, priority: 5 }
);
expect(queue.close).not.toHaveBeenCalled();
});
});
function buildQueue() {
return {
add: vi.fn(),
close: vi.fn().mockResolvedValue(undefined),
} as unknown as Parameters<typeof queueLegacyEventWebhookAttemptDelivery>[0]["queue"] & {
add: ReturnType<typeof vi.fn>;
close: ReturnType<typeof vi.fn>;
};
}