import { beforeEach, describe, expect, it, vi } from "vitest" import { es } from "@/i18n/dictionaries/es" const mocks = vi.hoisted(() => ({ revalidatePath: vi.fn(), getI18n: vi.fn(), requireRole: vi.fn(), createUserUseCase: vi.fn(), updateUserUseCase: vi.fn(), setUserActiveUseCase: vi.fn(), resetUserPasswordUseCase: 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/user.use-cases", () => ({ createUserUseCase: mocks.createUserUseCase, updateUserUseCase: mocks.updateUserUseCase, setUserActiveUseCase: mocks.setUserActiveUseCase, resetUserPasswordUseCase: mocks.resetUserPasswordUseCase, })) import { createUserAction, resetUserPasswordAction, setUserActiveAction, updateUserAction, } from "@/actions/user.actions" describe("user actions localization", () => { beforeEach(() => { vi.clearAllMocks() mocks.getI18n.mockResolvedValue({ dictionary: es, locale: "es" }) mocks.requireRole.mockResolvedValue({ user: { id: "admin-1" }, }) }) describe("createUserAction", () => { it("returns localized schema validation errors for invalid create input", async () => { const result = await createUserAction({ name: "", email: "bad", password: "short", role: "ADMIN", isActive: true, }) expect(mocks.getI18n).toHaveBeenCalledOnce() expect(mocks.createUserUseCase).not.toHaveBeenCalled() expect(result).toEqual({ success: false, errors: { name: [es.admin.users.schema.nameRequired], email: [es.admin.users.schema.emailInvalid], password: [es.admin.users.schema.passwordMinLength], }, }) }) it("localizes mapped duplicate field errors for create failures", async () => { mocks.createUserUseCase.mockResolvedValue({ success: false, errors: { email: ["Email already exists"], }, }) const result = await createUserAction({ name: "Ada", email: "ada@example.test", password: "password1", role: "STAFF", isActive: true, }) expect(result).toEqual({ success: false, errors: { email: [es.admin.users.actions.duplicateEmail], }, message: es.admin.users.actions.createFailure, }) }) it("returns a localized create success message and revalidates", async () => { mocks.createUserUseCase.mockResolvedValue({ success: true }) const result = await createUserAction({ name: "Ada", email: "ada@example.test", password: "password1", role: "STAFF", isActive: true, }) expect(result).toEqual({ success: true, message: es.admin.users.actions.createSuccess, }) expect(mocks.revalidatePath).toHaveBeenCalledWith("/people") }) }) describe("updateUserAction", () => { it("returns localized schema validation errors for invalid update input", async () => { const result = await updateUserAction({ id: "", name: "", email: "bad", role: "ADMIN", isActive: true, }) expect(mocks.getI18n).toHaveBeenCalledOnce() expect(mocks.updateUserUseCase).not.toHaveBeenCalled() expect(result).toEqual({ success: false, errors: { id: [es.admin.users.schema.userIdRequired], name: [es.admin.users.schema.nameRequired], email: [es.admin.users.schema.emailInvalid], }, }) }) it("localizes mapped use-case errors for update failures", async () => { mocks.updateUserUseCase.mockResolvedValue({ success: false, errors: { id: [ "Cannot remove access from the last active administrator", "You cannot remove your own administrator access", ], }, }) const result = await updateUserAction({ id: "user-1", name: "Admin", email: "admin@example.test", role: "MANAGER", isActive: true, }) expect(result).toEqual({ success: false, errors: { id: [ es.admin.users.actions.lastActiveAdmin, es.admin.users.actions.selfAdminAccess, ], }, message: es.admin.users.actions.updateFailure, }) }) it("returns a localized update success message and revalidates", async () => { mocks.updateUserUseCase.mockResolvedValue({ success: true }) const result = await updateUserAction({ id: "user-1", name: "Admin", email: "admin@example.test", role: "ADMIN", isActive: true, }) expect(result).toEqual({ success: true, message: es.admin.users.actions.updateSuccess, }) expect(mocks.revalidatePath).toHaveBeenCalledWith("/people") }) }) describe("setUserActiveAction", () => { it("returns localized schema validation errors for invalid input", async () => { const result = await setUserActiveAction({ id: "", isActive: false, }) expect(mocks.getI18n).toHaveBeenCalledOnce() expect(mocks.setUserActiveUseCase).not.toHaveBeenCalled() expect(result).toEqual({ success: false, errors: { id: [es.admin.users.schema.userIdRequired], }, }) }) it("localizes mapped use-case errors for toggle failures", async () => { mocks.setUserActiveUseCase.mockResolvedValue({ success: false, errors: { id: ["You cannot deactivate your own user"], }, }) const result = await setUserActiveAction({ id: "user-1", isActive: false, }) expect(result).toEqual({ success: false, errors: { id: [es.admin.users.actions.selfDeactivate], }, message: es.admin.users.actions.toggleStatusFailure, }) }) it("returns a localized toggle status success message and revalidates", async () => { mocks.setUserActiveUseCase.mockResolvedValue({ success: true }) const result = await setUserActiveAction({ id: "user-1", isActive: false, }) expect(result).toEqual({ success: true, message: es.admin.users.actions.toggleStatusSuccess, }) expect(mocks.revalidatePath).toHaveBeenCalledWith("/people") }) }) describe("resetUserPasswordAction", () => { it("returns localized schema validation errors for invalid input", async () => { const result = await resetUserPasswordAction({ id: "", password: "short", }) expect(mocks.getI18n).toHaveBeenCalledOnce() expect(mocks.resetUserPasswordUseCase).not.toHaveBeenCalled() expect(result).toEqual({ success: false, errors: { id: [es.admin.users.schema.userIdRequired], password: [es.admin.users.schema.passwordMinLength], }, }) }) it("localizes mapped use-case errors for reset failures", async () => { mocks.resetUserPasswordUseCase.mockResolvedValue({ success: false, errors: { id: ["User not found"] }, }) const result = await resetUserPasswordAction({ id: "nonexistent", password: "newpassword1", }) expect(result).toEqual({ success: false, errors: { id: [es.admin.users.actions.notFound], }, message: es.admin.users.actions.resetPasswordFailure, }) }) it("returns a localized reset success message and revalidates", async () => { mocks.resetUserPasswordUseCase.mockResolvedValue({ success: true }) const result = await resetUserPasswordAction({ id: "user-1", password: "newpassword1", }) expect(result).toEqual({ success: true, message: es.admin.users.actions.resetPasswordSuccess, }) expect(mocks.revalidatePath).toHaveBeenCalledWith("/people") }) }) })