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[0]["queue"] & { add: ReturnType; close: ReturnType; }; }