import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest" import type { PrismaClient } from "@/generated/prisma/client" import { createTestPerson, createTestUser } from "../helpers/factories" import { resetIntegrationTestDatabase, startIntegrationTestDatabase, stopIntegrationTestDatabase, } from "../helpers/test-db" let prisma: PrismaClient let createPersonUseCase: typeof import("@/use-cases/person.use-cases").createPersonUseCase let updatePersonUseCase: typeof import("@/use-cases/person.use-cases").updatePersonUseCase beforeAll(async () => { await startIntegrationTestDatabase() const prismaModule = await import("@/lib/prisma") const personUseCases = await import("@/use-cases/person.use-cases") prisma = prismaModule.prisma createPersonUseCase = personUseCases.createPersonUseCase updatePersonUseCase = personUseCases.updatePersonUseCase }) beforeEach(async () => { await resetIntegrationTestDatabase(prisma) }) afterAll(async () => { await prisma?.$disconnect() await stopIntegrationTestDatabase() }) describe("person use-cases", () => { it("creates a person and normalizes empty optional contact fields to null", async () => { await expect( createPersonUseCase({ firstName: "Person", lastName: "One", department: "IT", email: "", phone: "", }), ).resolves.toEqual({ success: true }) await expect( prisma.person.findFirstOrThrow({ where: { firstName: "Person", lastName: "One" }, }), ).resolves.toMatchObject({ firstName: "Person", lastName: "One", department: "IT", email: null, phone: null, userId: null, }) }) it("creates a person with linked userId", async () => { const user = await createTestUser(prisma) await expect( createPersonUseCase({ firstName: "Linked", lastName: "Person", department: "ENGINEERING", email: "linked@example.test", phone: null, userId: user.id, }), ).resolves.toEqual({ success: true }) await expect( prisma.person.findFirstOrThrow({ where: { firstName: "Linked" }, }), ).resolves.toMatchObject({ firstName: "Linked", lastName: "Person", department: "ENGINEERING", email: "linked@example.test", userId: user.id, }) }) it("rejects duplicate emails on create", async () => { await createTestPerson(prisma, { email: "existing@example.test", }) await expect( createPersonUseCase({ firstName: "Duplicate", lastName: "Email", department: "OTHER", email: "existing@example.test", phone: null, }), ).resolves.toEqual({ success: false, errors: { email: ["Email already exists"] }, }) await expect(prisma.person.count()).resolves.toBe(1) }) it("updates a person and rejects duplicate emails", async () => { const person = await createTestPerson(prisma, { email: "person@example.test", phone: "111111111", }) const other = await createTestPerson(prisma, { email: "other@example.test", }) await expect( updatePersonUseCase({ id: person.id, firstName: "Edited", lastName: "Person", department: "ENGINEERING", email: "edited@example.test", phone: "222222222", }), ).resolves.toEqual({ success: true }) await expect( prisma.person.findUniqueOrThrow({ where: { id: person.id } }), ).resolves.toMatchObject({ firstName: "Edited", lastName: "Person", department: "ENGINEERING", email: "edited@example.test", phone: "222222222", }) await expect( updatePersonUseCase({ id: person.id, firstName: "Edited", lastName: "Person", department: "ENGINEERING", email: other.email, phone: "222222222", }), ).resolves.toEqual({ success: false, errors: { email: ["Email already exists"] }, }) await expect( prisma.person.findUniqueOrThrow({ where: { id: person.id } }), ).resolves.toMatchObject({ email: "edited@example.test", }) await expect(prisma.person.count()).resolves.toBe(2) }) it("searches by email and name in paginated results", async () => { await createTestPerson(prisma, { firstName: "Alice", lastName: "Smith", email: "alice@company.com", }) await createTestPerson(prisma, { firstName: "Bob", lastName: "Jones", email: "bob@other.com", }) const { PersonService } = await import("@/services/person.service") const emailResults = await PersonService.findAllPaginated({ search: "company", page: 1, pageSize: 10, }) expect(emailResults.data).toHaveLength(1) expect(emailResults.data[0].firstName).toBe("Alice") const nameResults = await PersonService.findAllPaginated({ search: "Bob", page: 1, pageSize: 10, }) expect(nameResults.data).toHaveLength(1) expect(nameResults.data[0].firstName).toBe("Bob") }) })