import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest" import type { PrismaClient } from "@/generated/prisma/client" import { createTestCategory, createTestUser } from "../helpers/factories" import { resetIntegrationTestDatabase, startIntegrationTestDatabase, stopIntegrationTestDatabase, } from "../helpers/test-db" let prisma: PrismaClient let createItemUseCase: typeof import("@/use-cases/item.use-cases").createItemUseCase let deleteItemUseCase: typeof import("@/use-cases/item.use-cases").deleteItemUseCase beforeAll(async () => { await startIntegrationTestDatabase() const prismaModule = await import("@/lib/prisma") const itemUseCases = await import("@/use-cases/item.use-cases") prisma = prismaModule.prisma createItemUseCase = itemUseCases.createItemUseCase deleteItemUseCase = itemUseCases.deleteItemUseCase }) beforeEach(async () => { await resetIntegrationTestDatabase(prisma) }) afterAll(async () => { await prisma?.$disconnect() await stopIntegrationTestDatabase() }) describe("item use-cases", () => { it("creates an item with initial stock and records an IN movement", async () => { const actor = await createTestUser(prisma) const category = await createTestCategory(prisma) const result = await createItemUseCase({ actorId: actor.id, name: "Laptop", categoryId: category.id, stock: 3, }) expect(result).toEqual({ success: true }) const item = await prisma.item.findUnique({ where: { name: "Laptop" }, include: { movements: true }, }) expect(item).toMatchObject({ name: "Laptop", categoryId: category.id, stock: 3, deletedAt: null, }) expect(item?.movements).toHaveLength(1) expect(item?.movements[0]).toMatchObject({ type: "IN", quantity: 3, userId: actor.id, }) }) it("rejects duplicate item names", async () => { const actor = await createTestUser(prisma) const category = await createTestCategory(prisma) await createItemUseCase({ actorId: actor.id, name: "Monitor", categoryId: category.id, stock: 0, }) const duplicate = await createItemUseCase({ actorId: actor.id, name: "Monitor", categoryId: category.id, stock: 0, }) expect(duplicate).toEqual({ success: false, errors: { name: ["An item with this name already exists"], }, }) }) it("blocks deleting items with stock and soft deletes empty items", async () => { const actor = await createTestUser(prisma) const category = await createTestCategory(prisma) await createItemUseCase({ actorId: actor.id, name: "Keyboard", categoryId: category.id, stock: 2, }) const stockedItem = await prisma.item.findUniqueOrThrow({ where: { name: "Keyboard" }, }) await expect(deleteItemUseCase(stockedItem.id)).resolves.toEqual({ success: false, errors: { id: ["Item has stock, you cannot delete it"] }, }) await createItemUseCase({ actorId: actor.id, name: "Mouse", categoryId: category.id, stock: 0, }) const emptyItem = await prisma.item.findUniqueOrThrow({ where: { name: "Mouse" }, }) await expect(deleteItemUseCase(emptyItem.id)).resolves.toEqual({ success: true, }) const deletedItem = await prisma.item.findUniqueOrThrow({ where: { id: emptyItem.id }, }) expect(deletedItem.deletedAt).toBeInstanceOf(Date) }) })