import { afterEach, describe, expect, test, vi } from "vitest"; import { prisma } from "@formbricks/database"; import { TActionClass } from "@formbricks/types/action-classes"; import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors"; import { deleteActionClass, getActionClass, getActionClassByEnvironmentIdAndName, getActionClasses, } from "./service"; vi.mock("@formbricks/database", () => ({ prisma: { actionClass: { findMany: vi.fn(), findFirst: vi.fn(), findUnique: vi.fn(), delete: vi.fn(), }, }, })); vi.mock("../utils/validate", () => ({ validateInputs: vi.fn(), })); describe("ActionClass Service", () => { afterEach(() => { vi.clearAllMocks(); }); describe("getActionClasses", () => { test("should return action classes for environment", async () => { const mockActionClasses = [ { id: "id1", createdAt: new Date(), updatedAt: new Date(), name: "Action 1", description: "desc", type: "code", key: "key1", noCodeConfig: {}, environmentId: "env1", }, ]; vi.mocked(prisma.actionClass.findMany).mockResolvedValue(mockActionClasses); const result = await getActionClasses("env1"); expect(result).toEqual(mockActionClasses); expect(prisma.actionClass.findMany).toHaveBeenCalledWith({ where: { environmentId: "env1" }, select: expect.any(Object), take: undefined, skip: undefined, orderBy: { createdAt: "asc" }, }); }); test("should throw DatabaseError when prisma throws", async () => { vi.mocked(prisma.actionClass.findMany).mockRejectedValue(new Error("fail")); await expect(getActionClasses("env1")).rejects.toThrow(DatabaseError); }); }); describe("getActionClassByEnvironmentIdAndName", () => { test("should return action class when found", async () => { const mockActionClass = { id: "id2", createdAt: new Date(), updatedAt: new Date(), name: "Action 2", description: "desc2", type: "noCode", key: null, noCodeConfig: {}, environmentId: "env2", }; if (!prisma.actionClass.findFirst) prisma.actionClass.findFirst = vi.fn(); vi.mocked(prisma.actionClass.findFirst).mockResolvedValue(mockActionClass); const result = await getActionClassByEnvironmentIdAndName("env2", "Action 2"); expect(result).toEqual(mockActionClass); expect(prisma.actionClass.findFirst).toHaveBeenCalledWith({ where: { name: "Action 2", environmentId: "env2" }, select: expect.any(Object), }); }); test("should return null when not found", async () => { if (!prisma.actionClass.findFirst) prisma.actionClass.findFirst = vi.fn(); vi.mocked(prisma.actionClass.findFirst).mockResolvedValue(null); const result = await getActionClassByEnvironmentIdAndName("env2", "Action 2"); expect(result).toBeNull(); }); test("should throw DatabaseError when prisma throws", async () => { if (!prisma.actionClass.findFirst) prisma.actionClass.findFirst = vi.fn(); vi.mocked(prisma.actionClass.findFirst).mockRejectedValue(new Error("fail")); await expect(getActionClassByEnvironmentIdAndName("env2", "Action 2")).rejects.toThrow(DatabaseError); }); }); describe("getActionClass", () => { test("should return action class when found", async () => { const mockActionClass = { id: "id3", createdAt: new Date(), updatedAt: new Date(), name: "Action 3", description: "desc3", type: "code", key: "key3", noCodeConfig: {}, environmentId: "env3", }; if (!prisma.actionClass.findUnique) prisma.actionClass.findUnique = vi.fn(); vi.mocked(prisma.actionClass.findUnique).mockResolvedValue(mockActionClass); const result = await getActionClass("id3"); expect(result).toEqual(mockActionClass); expect(prisma.actionClass.findUnique).toHaveBeenCalledWith({ where: { id: "id3" }, select: expect.any(Object), }); }); test("should return null when not found", async () => { if (!prisma.actionClass.findUnique) prisma.actionClass.findUnique = vi.fn(); vi.mocked(prisma.actionClass.findUnique).mockResolvedValue(null); const result = await getActionClass("id3"); expect(result).toBeNull(); }); test("should throw DatabaseError when prisma throws", async () => { if (!prisma.actionClass.findUnique) prisma.actionClass.findUnique = vi.fn(); vi.mocked(prisma.actionClass.findUnique).mockRejectedValue(new Error("fail")); await expect(getActionClass("id3")).rejects.toThrow(DatabaseError); }); }); describe("deleteActionClass", () => { test("should delete and return action class", async () => { const mockActionClass: TActionClass = { id: "id4", createdAt: new Date(), updatedAt: new Date(), name: "Action 4", description: null, type: "code", key: "key4", noCodeConfig: null, environmentId: "env4", }; if (!prisma.actionClass.delete) prisma.actionClass.delete = vi.fn(); vi.mocked(prisma.actionClass.delete).mockResolvedValue(mockActionClass); const result = await deleteActionClass("id4"); expect(result).toEqual(mockActionClass); expect(prisma.actionClass.delete).toHaveBeenCalledWith({ where: { id: "id4" }, select: expect.any(Object), }); }); test("should throw ResourceNotFoundError if action class is null", async () => { if (!prisma.actionClass.delete) prisma.actionClass.delete = vi.fn(); vi.mocked(prisma.actionClass.delete).mockResolvedValue(null as unknown as TActionClass); await expect(deleteActionClass("id4")).rejects.toThrow(ResourceNotFoundError); }); test("should rethrow unknown errors", async () => { if (!prisma.actionClass.delete) prisma.actionClass.delete = vi.fn(); const error = new Error("unknown"); vi.mocked(prisma.actionClass.delete).mockRejectedValue(error); await expect(deleteActionClass("id4")).rejects.toThrow("unknown"); }); }); });