refactor: consolidate admin/users management under /people
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
import { describe, expect, it } from "vitest"
|
||||
|
||||
import {
|
||||
buildUnifiedUpdateSchema,
|
||||
type UnifiedSchemaCopy,
|
||||
} from "@/schemas/user.schema"
|
||||
|
||||
const enCopy: UnifiedSchemaCopy = {
|
||||
firstNameRequired: "First name is required",
|
||||
lastNameRequired: "Last name is required",
|
||||
departmentRequired: "Department is required",
|
||||
emailInvalid: "Invalid email",
|
||||
passwordMinLength: "Password must be at least 8 characters",
|
||||
nameRequired: "Name is required",
|
||||
userIdRequired: "User id is required",
|
||||
idRequired: "ID is required",
|
||||
userIdInvalid: "User ID must be a valid UUID",
|
||||
}
|
||||
|
||||
const esCopy: UnifiedSchemaCopy = {
|
||||
firstNameRequired: "El nombre es obligatorio",
|
||||
lastNameRequired: "El apellido es obligatorio",
|
||||
departmentRequired: "El departamento es obligatorio",
|
||||
emailInvalid: "Correo electrónico no válido",
|
||||
passwordMinLength: "La contraseña debe tener al menos 8 caracteres",
|
||||
nameRequired: "El nombre es obligatorio",
|
||||
userIdRequired: "El ID de usuario es obligatorio",
|
||||
idRequired: "El ID es obligatorio",
|
||||
userIdInvalid: "El ID de usuario debe ser un UUID válido",
|
||||
}
|
||||
|
||||
const validPersonOnly = {
|
||||
id: "person-1",
|
||||
firstName: "John",
|
||||
lastName: "Doe",
|
||||
department: "IT",
|
||||
email: "john@example.test",
|
||||
phone: null,
|
||||
}
|
||||
|
||||
const validPersonWithUser = {
|
||||
...validPersonOnly,
|
||||
role: "ADMIN" as const,
|
||||
isActive: true,
|
||||
}
|
||||
|
||||
describe("buildUnifiedUpdateSchema", () => {
|
||||
describe("person-only update (no user fields provided)", () => {
|
||||
it("accepts person fields without role/isActive/password when person has no User", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse(validPersonOnly)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
if (result.success) {
|
||||
expect(result.data.id).toBe("person-1")
|
||||
expect(result.data.firstName).toBe("John")
|
||||
expect(result.data.role).toBeUndefined()
|
||||
expect(result.data.isActive).toBeUndefined()
|
||||
expect(result.data.password).toBeUndefined()
|
||||
}
|
||||
})
|
||||
|
||||
it("accepts person fields with isActive=false when person has no User", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({ ...validPersonOnly, isActive: false })
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
it("rejects empty id", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
id: "",
|
||||
firstName: "John",
|
||||
lastName: "Doe",
|
||||
department: "IT",
|
||||
email: "john@example.test",
|
||||
phone: null,
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.id).toContain(
|
||||
enCopy.idRequired,
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("person+user update (when person has User linked)", () => {
|
||||
it("accepts person and user fields with role and isActive when no password change", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse(validPersonWithUser)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
if (result.success) {
|
||||
expect(result.data.role).toBe("ADMIN")
|
||||
expect(result.data.isActive).toBe(true)
|
||||
expect(result.data.password).toBeUndefined()
|
||||
}
|
||||
})
|
||||
|
||||
it("accepts password reset (>= 8 chars) when role is provided", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonWithUser,
|
||||
password: "newpassword1",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
if (result.success) {
|
||||
expect(result.data.password).toBe("newpassword1")
|
||||
}
|
||||
})
|
||||
|
||||
it("rejects short password when role is provided and password is non-empty", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonWithUser,
|
||||
password: "short",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.password).toContain(
|
||||
enCopy.passwordMinLength,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("accepts empty password string as 'do not change' (ignored)", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonWithUser,
|
||||
password: "",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
it("rejects invalid role enum", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonWithUser,
|
||||
role: "SUPER_ADMIN",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
it("rejects NO_USER role on update (cannot remove user from existing person)", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonWithUser,
|
||||
role: "NO_USER" as unknown as "ADMIN",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
it("uses localized password error message", () => {
|
||||
const schema = buildUnifiedUpdateSchema(esCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonWithUser,
|
||||
password: "corta",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.password).toContain(
|
||||
esCopy.passwordMinLength,
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("email validation", () => {
|
||||
it("rejects invalid email format", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({
|
||||
...validPersonOnly,
|
||||
email: "not-an-email",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.email).toContain(
|
||||
enCopy.emailInvalid,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("accepts null email (person can have no email)", () => {
|
||||
const schema = buildUnifiedUpdateSchema(enCopy)
|
||||
const result = schema.safeParse({ ...validPersonOnly, email: null })
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user