mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-04 02:04:06 +00:00
fix(jira): surface dispatch failures (#11918)
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const { pollTaskUntilSettledMock } = vi.hoisted(() => ({
|
||||
pollTaskUntilSettledMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/actions/task/poll", () => ({
|
||||
pollTaskUntilSettled: pollTaskUntilSettledMock,
|
||||
}));
|
||||
|
||||
vi.mock("@/lib", () => ({
|
||||
apiBaseUrl: "https://api.example.com/api/v1",
|
||||
getAuthHeaders: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/server-actions-helper", () => ({
|
||||
handleApiError: vi.fn(),
|
||||
}));
|
||||
|
||||
import { pollJiraDispatchTask } from "./jira-dispatch";
|
||||
|
||||
describe("pollJiraDispatchTask", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should return the backend error when a completed task has failed Jira dispatches", async () => {
|
||||
// Given
|
||||
pollTaskUntilSettledMock.mockResolvedValue({
|
||||
ok: true,
|
||||
state: "completed",
|
||||
result: {
|
||||
created_count: 0,
|
||||
failed_count: 1,
|
||||
error: "Jira project requires custom fields: Team is required",
|
||||
},
|
||||
});
|
||||
|
||||
// When
|
||||
const result = await pollJiraDispatchTask("task-123");
|
||||
|
||||
// Then
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: "Jira project requires custom fields: Team is required",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a fallback error when a completed task has failures without an error", async () => {
|
||||
// Given
|
||||
pollTaskUntilSettledMock.mockResolvedValue({
|
||||
ok: true,
|
||||
state: "completed",
|
||||
result: {
|
||||
created_count: 0,
|
||||
failed_count: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// When
|
||||
const result = await pollJiraDispatchTask("task-123");
|
||||
|
||||
// Then
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: "Failed to create Jira issue.",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a plural fallback error when a completed task has multiple failures without an error", async () => {
|
||||
// Given
|
||||
pollTaskUntilSettledMock.mockResolvedValue({
|
||||
ok: true,
|
||||
state: "completed",
|
||||
result: {
|
||||
created_count: 0,
|
||||
failed_count: 3,
|
||||
},
|
||||
});
|
||||
|
||||
// When
|
||||
const result = await pollJiraDispatchTask("task-123");
|
||||
|
||||
// Then
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: "Failed to create 3 Jira issues.",
|
||||
});
|
||||
});
|
||||
|
||||
it("should surface task failure result errors", async () => {
|
||||
// Given
|
||||
pollTaskUntilSettledMock.mockResolvedValue({
|
||||
ok: true,
|
||||
state: "failed",
|
||||
result: {
|
||||
error: "Jira credentials are invalid.",
|
||||
},
|
||||
});
|
||||
|
||||
// When
|
||||
const result = await pollJiraDispatchTask("task-123");
|
||||
|
||||
// Then
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: "Jira credentials are invalid.",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return success when a completed task has no failures", async () => {
|
||||
// Given
|
||||
pollTaskUntilSettledMock.mockResolvedValue({
|
||||
ok: true,
|
||||
state: "completed",
|
||||
result: {
|
||||
created_count: 1,
|
||||
failed_count: 0,
|
||||
},
|
||||
});
|
||||
|
||||
// When
|
||||
const result = await pollJiraDispatchTask("task-123");
|
||||
|
||||
// Then
|
||||
expect(result).toEqual({
|
||||
success: true,
|
||||
message: "Finding successfully sent to Jira!",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a fallback error when no Jira issue was created", async () => {
|
||||
// Given
|
||||
pollTaskUntilSettledMock.mockResolvedValue({
|
||||
ok: true,
|
||||
state: "completed",
|
||||
result: {
|
||||
created_count: 0,
|
||||
failed_count: 0,
|
||||
},
|
||||
});
|
||||
|
||||
// When
|
||||
const result = await pollJiraDispatchTask("task-123");
|
||||
|
||||
// Then
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: "Failed to create Jira issue.",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -159,12 +159,18 @@ export const pollJiraDispatchTask = async (
|
||||
const jiraResult = result as JiraTaskResult | undefined;
|
||||
|
||||
if (state === "completed") {
|
||||
if (!jiraResult?.error) {
|
||||
const createdCount = jiraResult?.created_count ?? 0;
|
||||
const failedCount = jiraResult?.failed_count ?? 0;
|
||||
if (!jiraResult?.error && failedCount === 0 && createdCount > 0) {
|
||||
return { success: true, message: "Finding successfully sent to Jira!" };
|
||||
}
|
||||
return {
|
||||
success: false,
|
||||
error: jiraResult?.error || "Failed to create Jira issue.",
|
||||
error:
|
||||
jiraResult?.error ||
|
||||
(failedCount > 1
|
||||
? `Failed to create ${failedCount} Jira issues.`
|
||||
: "Failed to create Jira issue."),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Jira dispatch polling now reports failed issue creation tasks instead of treating partial failures as successful
|
||||
@@ -64,6 +64,8 @@ export interface JiraDispatchResponse {
|
||||
message?: string;
|
||||
issue_url?: string;
|
||||
issue_key?: string;
|
||||
created_count?: number;
|
||||
failed_count?: number;
|
||||
} | null;
|
||||
task_args: Record<string, unknown> | null;
|
||||
metadata: Record<string, unknown> | null;
|
||||
|
||||
Reference in New Issue
Block a user