import { beforeEach, describe, expect, it, vi } from "vitest"; import { executeRegistryArtifactAddition } from "./artifact-execution"; const { addRegistryArtifactMock, confirmRegistryArtifactAdditionMock, trackAndPollTaskMock, } = vi.hoisted(() => ({ addRegistryArtifactMock: vi.fn(), confirmRegistryArtifactAdditionMock: vi.fn(), trackAndPollTaskMock: vi.fn(), })); vi.mock("@/actions/registry/registry", () => ({ addRegistryArtifact: addRegistryArtifactMock, confirmRegistryArtifactAddition: confirmRegistryArtifactAdditionMock, })); vi.mock("@/store/task-watcher/store", () => ({ TASK_WATCHER_STATUS: { READY: "ready", ERROR: "error" }, trackAndPollTask: trackAndPollTaskMock, })); const artifactInput = { normalizedName: "prowler-aws", versionSpec: "2.0.0" }; describe("executeRegistryArtifactAddition", () => { beforeEach(() => { vi.clearAllMocks(); addRegistryArtifactMock.mockResolvedValue({ status: "submitted", taskId: "artifact-task", }); trackAndPollTaskMock.mockResolvedValue({ status: "ready", result: { installed: true, error: null }, }); confirmRegistryArtifactAdditionMock.mockResolvedValue({ status: "confirmed", tenantArtifacts: [], }); }); it("persists an update target and confirms that version after the task completes", async () => { // Given / When await executeRegistryArtifactAddition({ ...artifactInput, operation: "update", }); // Then expect(trackAndPollTaskMock).toHaveBeenCalledWith( expect.objectContaining({ meta: { normalizedName: "prowler-aws", operation: "update", expectedVersion: "2.0.0", }, }), ); expect(confirmRegistryArtifactAdditionMock).toHaveBeenCalledWith( "prowler-aws", "2.0.0", ); }); it.each([ [ "This version cannot be installed.", "The artifact could not be installed.", ], [ "Private diagnostic: /srv/registry/customer", "The artifact could not be installed.", ], [null, "The artifact could not be installed."], ["", "The artifact could not be installed."], [" ", "The artifact could not be installed."], ])( "returns a safe task refusal for error %j without confirmation", async (error, message) => { // Given trackAndPollTaskMock.mockResolvedValue({ status: "ready", result: { installed: false, error }, }); // When const outcome = await executeRegistryArtifactAddition(artifactInput); // Then expect(outcome).toEqual({ status: "refused", message }); expect(confirmRegistryArtifactAdditionMock).not.toHaveBeenCalled(); }, ); it.each([ [ "an otherwise valid result with an extra field", { installed: true, error: null, reason: "private deployment detail" }, ], [ "an installed result with an error", { installed: true, error: "unexpected failure" }, ], ])("returns error for %s without confirmation", async (_case, result) => { // Given trackAndPollTaskMock.mockResolvedValue({ status: "ready", result }); // When const outcome = await executeRegistryArtifactAddition(artifactInput); // Then expect(outcome).toEqual({ status: "error" }); expect(confirmRegistryArtifactAdditionMock).not.toHaveBeenCalled(); }); it("maps failed tasks to unavailable without confirmation", async () => { // Given trackAndPollTaskMock.mockResolvedValue({ status: "error", error: "failed", }); // When const outcome = await executeRegistryArtifactAddition(artifactInput); // Then expect(outcome).toEqual({ status: "unavailable" }); expect(confirmRegistryArtifactAdditionMock).not.toHaveBeenCalled(); }); it("uses the error catch when polling throws", async () => { // Given trackAndPollTaskMock.mockRejectedValue(new Error("watcher crashed")); // When const outcome = await executeRegistryArtifactAddition(artifactInput); // Then expect(outcome).toEqual({ status: "error" }); expect(confirmRegistryArtifactAdditionMock).not.toHaveBeenCalled(); }); it("does not poll a synchronous 409 onboarding outcome", async () => { // Given addRegistryArtifactMock.mockResolvedValue({ status: "onboarding" }); // When const outcome = await executeRegistryArtifactAddition(artifactInput); // Then expect(outcome).toEqual({ status: "onboarding" }); expect(confirmRegistryArtifactAdditionMock).not.toHaveBeenCalled(); expect(trackAndPollTaskMock).not.toHaveBeenCalled(); }); it("confirms presence after a completed installed task", async () => { // Given // When const outcome = await executeRegistryArtifactAddition(artifactInput); // Then expect(outcome).toEqual({ status: "confirmed", tenantArtifacts: [] }); expect(trackAndPollTaskMock).toHaveBeenCalledWith({ taskId: "artifact-task", kind: "registry-artifact-add", meta: { normalizedName: "prowler-aws" }, notifyHandler: false, }); expect(confirmRegistryArtifactAdditionMock).toHaveBeenCalledOnce(); expect(confirmRegistryArtifactAdditionMock).toHaveBeenCalledWith( "prowler-aws", ); }); it("deduplicates concurrent submissions for the same artifact", async () => { await Promise.all([ executeRegistryArtifactAddition(artifactInput), executeRegistryArtifactAddition(artifactInput), ]); expect(addRegistryArtifactMock).toHaveBeenCalledOnce(); expect(confirmRegistryArtifactAdditionMock).toHaveBeenCalledOnce(); }); it("reports an unconfirmed update if the confirmation request throws", async () => { // Given confirmRegistryArtifactAdditionMock.mockRejectedValue( new Error("Network failure"), ); // When const result = await executeRegistryArtifactAddition({ ...artifactInput, operation: "update", }); // Then expect(result).toEqual({ status: "refresh_failed" }); }); });