import { beforeEach, describe, expect, it, vi } from "vitest" import { en } from "@/i18n/dictionaries/en" import { es } from "@/i18n/dictionaries/es" const mocks = vi.hoisted(() => ({ revalidatePath: vi.fn(), getI18n: vi.fn(), requireRole: vi.fn(), updatePersonUserUseCase: vi.fn(), })) vi.mock("next/cache", () => ({ revalidatePath: mocks.revalidatePath, })) vi.mock("@/i18n/server", () => ({ getI18n: mocks.getI18n, })) vi.mock("@/services/auth.service", () => ({ requireRole: mocks.requireRole, })) vi.mock("@/use-cases/person.use-cases", () => ({ updatePersonUserUseCase: mocks.updatePersonUserUseCase, })) import { updatePersonUserAction } from "@/actions/person.actions" describe("updatePersonUserAction", () => { beforeEach(() => { vi.clearAllMocks() mocks.getI18n.mockResolvedValue({ dictionary: es, locale: "es" }) mocks.requireRole.mockResolvedValue({ user: { id: "admin-1" } }) }) describe("schema validation", () => { it("rejects empty id with localized idRequired error", async () => { const result = await updatePersonUserAction({ id: "", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, }) expect(result).toEqual({ success: false, errors: { id: [es.inventory.people.schema.idRequired], }, }) expect(mocks.updatePersonUserUseCase).not.toHaveBeenCalled() }) it("rejects invalid email with localized emailInvalid error", async () => { const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "not-an-email", phone: null, }) expect(result).toEqual({ success: false, errors: { email: [es.inventory.people.schema.emailInvalid], }, }) expect(mocks.updatePersonUserUseCase).not.toHaveBeenCalled() }) it("rejects short password when role is provided", async () => { const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, role: "ADMIN", isActive: true, password: "corta", }) expect(result).toEqual({ success: false, errors: { password: [es.admin.users.schema.passwordMinLength], }, }) expect(mocks.updatePersonUserUseCase).not.toHaveBeenCalled() }) it("rejects NO_USER role on update", async () => { const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, role: "NO_USER" as unknown as "ADMIN", isActive: true, }) expect(result.success).toBe(false) expect(mocks.updatePersonUserUseCase).not.toHaveBeenCalled() }) it("rejects invalid role enum on update", async () => { const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, role: "SUPER_ADMIN" as unknown as "ADMIN", isActive: true, }) expect(result.success).toBe(false) expect(mocks.updatePersonUserUseCase).not.toHaveBeenCalled() }) }) describe("use-case failure", () => { it("localizes duplicate email errors from the use case", async () => { mocks.updatePersonUserUseCase.mockResolvedValue({ success: false, errors: { email: ["Email already exists"] }, }) const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "duplicate@example.test", phone: null, }) expect(result).toEqual({ success: false, errors: { email: [es.inventory.people.actions.duplicateEmail], }, message: es.inventory.people.actions.updateFailure, }) }) it("localizes person-not-found error from the use case", async () => { mocks.updatePersonUserUseCase.mockResolvedValue({ success: false, errors: { id: ["Person not found"] }, }) const result = await updatePersonUserAction({ id: "missing", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, }) expect(result.success).toBe(false) if (!result.success && result.errors) { expect(result.errors.id).toBeDefined() } }) }) describe("success", () => { it("returns success and revalidates /people on happy path", async () => { mocks.updatePersonUserUseCase.mockResolvedValue({ success: true }) const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, }) expect(result).toEqual({ success: true, message: es.inventory.people.actions.updateSuccess, }) expect(mocks.revalidatePath).toHaveBeenCalledWith("/people") }) it("uses English copy in en locale", async () => { mocks.getI18n.mockResolvedValue({ dictionary: en, locale: "en" }) mocks.updatePersonUserUseCase.mockResolvedValue({ success: true }) const result = await updatePersonUserAction({ id: "person-1", firstName: "Ada", lastName: "Lovelace", department: "ENGINEERING", email: "ada@example.test", phone: null, }) expect(result).toEqual({ success: true, message: en.inventory.people.actions.updateSuccess, }) }) }) })