import { beforeEach, describe, expect, it, vi } from "vitest"; const { fetchMock, pollTaskUntilSettledMock } = vi.hoisted(() => ({ fetchMock: vi.fn(), pollTaskUntilSettledMock: vi.fn(), })); vi.mock("@/lib", () => ({ apiBaseUrl: "https://api.example.com/api/v1", getAuthHeaders: vi.fn().mockResolvedValue({ Authorization: "Bearer token" }), })); vi.mock("@/lib/server-actions-helper", () => ({ handleApiError: () => ({ error: "An error occurred" }), })); vi.mock("@/actions/task/poll", () => ({ pollTaskUntilSettled: pollTaskUntilSettledMock, })); import { pollJiraDispatchTask, sendJiraDispatch } from "./jira-dispatch"; describe("sendJiraDispatch", () => { beforeEach(() => { vi.clearAllMocks(); vi.stubGlobal("fetch", fetchMock); fetchMock.mockResolvedValue( new Response( JSON.stringify({ data: { id: "task-1", type: "tasks", attributes: { result: null }, }, }), { status: 202 }, ), ); }); it("should send grouped dispatch mode with multiple finding IDs", async () => { // Given / When await sendJiraDispatch({ integrationId: "jira-1", targetIds: ["finding-1", "finding-2"], filter: "finding_id", projectKey: "SEC", issueType: "Task", dispatchMode: "grouped", }); // Then const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit]; expect(url).toBe( "https://api.example.com/api/v1/integrations/jira-1/jira/dispatches?filter%5Bfinding_id__in%5D=finding-1%2Cfinding-2", ); expect(JSON.parse(init.body as string)).toMatchObject({ data: { attributes: { dispatch_mode: "grouped", issue_type: "Task", project_key: "SEC", }, }, }); }); it("should send grouped dispatch mode with a finding group check ID", async () => { // Given / When await sendJiraDispatch({ integrationId: "jira-1", targetIds: ["s3_bucket_public_access"], filter: "check_id", projectKey: "SEC", issueType: "Task", dispatchMode: "grouped", }); // Then const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit]; expect(url).toBe( "https://api.example.com/api/v1/integrations/jira-1/jira/dispatches?filter%5Bcheck_id%5D=s3_bucket_public_access", ); expect(JSON.parse(init.body as string)).toMatchObject({ data: { attributes: { dispatch_mode: "grouped" } }, }); }); it("should preserve partial success when Jira dispatch has created and failed issues", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: { created_count: 2, failed_count: 1, failed_finding_ids: ["finding-3"], error: "Jira rejected one Finding.", }, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(result).toEqual({ success: true, message: "2 Jira issues were created or updated successfully.", warning: "Jira rejected one Finding. Jira dispatch completed with 1 failed and 2 created/updated issues.", failedFindingIds: ["finding-3"], }); }); it("should include updated issues in partial failure summaries", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: { created_count: 0, updated_count: 2, failed_count: 1 }, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(result).toEqual({ success: true, message: "2 Jira issues were created or updated successfully.", warning: "Jira dispatch completed with 1 failed and 2 created/updated issues.", }); }); it("should fail completed task polling when grouped dispatch reports failed groups", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: { created_count: 1, failed_groups: [{ check_id: "check-a" }] }, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(result).toEqual({ success: true, message: "Finding successfully sent to Jira!", warning: "Jira dispatch completed with 1 failed and 1 created/updated issue.", }); }); it("should succeed completed task polling when grouped dispatch reports no failed groups", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: { created_count: 1, failed_groups: [] }, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(result).toEqual({ success: true, message: "Finding successfully sent to Jira!", }); }); it("should succeed completed task polling with grouped created and updated issue result shape", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: { created_count: 1, updated_count: 1, failed_count: 0, created_issues: [{ key: "SEC-1" }], updated_issues: [{ key: "SEC-2" }], failed_groups: [], }, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(pollTaskUntilSettledMock).toHaveBeenCalledWith("task-1", { maxAttempts: 5, delayMs: 2000, }); expect(result).toEqual({ success: true, message: "2 Jira issues were created or updated successfully.", }); }); it("should fail completed task polling when Jira dispatch completed as a no-op", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: { created_count: 0, updated_count: 0, failed_count: 0 }, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(result).toEqual({ success: false, error: "Jira dispatch completed but did not create or update any issues.", }); }); it("should fail completed task polling when Jira dispatch has no result payload", async () => { // Given pollTaskUntilSettledMock.mockResolvedValue({ ok: true, state: "completed", result: null, }); // When const result = await pollJiraDispatchTask("task-1"); // Then expect(result).toEqual({ success: false, error: "Jira dispatch completed but did not create or update any issues.", }); }); });