Files
prowler/ui/actions/integrations/jira-dispatch.test.ts
2026-07-22 12:58:12 +01:00

238 lines
6.5 KiB
TypeScript

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.",
});
});
});