import { describe, expect, it, vi, beforeEach } from "vitest"; const create = vi.hoisted(() => vi.fn()); vi.mock("@/lib/prisma", () => ({ prisma: { staffActivities: { create } }, })); vi.mock("@/env", () => ({ env: {} })); vi.mock("next/headers", () => ({ headers: () => new Promise((resolve) => resolve({ get: (key: string) => key === "x-real-client-ip" ? "192.168.1.1" : null, }), ), })); import { logStaffActivity } from "./staff-activity"; beforeEach(() => { vi.clearAllMocks(); }); describe("logStaffActivity", () => { it("creates a staff activity entry with ip", async () => { create.mockResolvedValue({ id: 1 }); await logStaffActivity({ staffId: 1, action: "test_action", description: "Test action performed", }); expect(create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ userId: BigInt(1), action: "test_action", description: "Test action performed", ipAddress: "192.168.1.1", }), }), ); }); it("truncates action to 50 chars", async () => { create.mockResolvedValue({ id: 1 }); const longAction = "a".repeat(100); await logStaffActivity({ staffId: 1, action: longAction, description: "test", }); const call = create.mock.calls[0][0]; expect(call.data.action.length).toBe(50); expect(call.data.action).toBe("a".repeat(50)); }); it("includes target type and target id when provided", async () => { create.mockResolvedValue({ id: 1 }); await logStaffActivity({ staffId: 1, action: "ban", description: "Banned user", targetType: "user", targetId: 42, }); const data = create.mock.calls[0][0].data; expect(data.targetType).toBe("user"); expect(data.targetId).toBe(BigInt(42)); }); it("does not throw on prisma error", async () => { create.mockRejectedValue(new Error("DB down")); await expect( logStaffActivity({ staffId: 1, action: "test", description: "test", }), ).resolves.toBeUndefined(); }); });