feat(teams): add team service and use-cases with integration tests
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest"
|
||||
import type { PrismaClient } from "@/generated/prisma/client"
|
||||
import { createTestPerson, createTestTeam } from "../helpers/factories"
|
||||
import {
|
||||
resetIntegrationTestDatabase,
|
||||
startIntegrationTestDatabase,
|
||||
stopIntegrationTestDatabase,
|
||||
} from "../helpers/test-db"
|
||||
|
||||
let prisma: PrismaClient
|
||||
let createTeamUseCase: typeof import("@/use-cases/team.use-cases").createTeamUseCase
|
||||
let updateTeamUseCase: typeof import("@/use-cases/team.use-cases").updateTeamUseCase
|
||||
let deleteTeamUseCase: typeof import("@/use-cases/team.use-cases").deleteTeamUseCase
|
||||
let listTeamsUseCase: typeof import("@/use-cases/team.use-cases").listTeamsUseCase
|
||||
let TeamService: typeof import("@/services/team.service").TeamService
|
||||
|
||||
beforeAll(async () => {
|
||||
await startIntegrationTestDatabase()
|
||||
|
||||
const prismaModule = await import("@/lib/prisma")
|
||||
const teamUseCases = await import("@/use-cases/team.use-cases")
|
||||
const teamService = await import("@/services/team.service")
|
||||
|
||||
prisma = prismaModule.prisma
|
||||
createTeamUseCase = teamUseCases.createTeamUseCase
|
||||
updateTeamUseCase = teamUseCases.updateTeamUseCase
|
||||
deleteTeamUseCase = teamUseCases.deleteTeamUseCase
|
||||
listTeamsUseCase = teamUseCases.listTeamsUseCase
|
||||
TeamService = teamService.TeamService
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await resetIntegrationTestDatabase(prisma)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await prisma?.$disconnect()
|
||||
await stopIntegrationTestDatabase()
|
||||
})
|
||||
|
||||
describe("team use-cases", () => {
|
||||
it("creates a team and rejects duplicate names", async () => {
|
||||
expect(await createTeamUseCase({ name: "Engineering" })).toEqual({
|
||||
success: true,
|
||||
})
|
||||
|
||||
expect(
|
||||
await prisma.team.findFirst({ where: { name: "Engineering" } }),
|
||||
).toMatchObject({ name: "Engineering" })
|
||||
|
||||
expect(await createTeamUseCase({ name: "Engineering" })).toEqual({
|
||||
success: false,
|
||||
errors: { name: ["Team already exists"] },
|
||||
})
|
||||
|
||||
expect(await prisma.team.count()).toBe(1)
|
||||
})
|
||||
|
||||
it("rejects duplicate names case-insensitively and trims whitespace", async () => {
|
||||
await createTestTeam(prisma, { name: "Engineering" })
|
||||
|
||||
expect(await createTeamUseCase({ name: "engineering" })).toEqual({
|
||||
success: false,
|
||||
errors: { name: ["Team already exists"] },
|
||||
})
|
||||
|
||||
expect(await createTeamUseCase({ name: " ENGINEERING " })).toEqual({
|
||||
success: false,
|
||||
errors: { name: ["Team already exists"] },
|
||||
})
|
||||
|
||||
expect(await prisma.team.count()).toBe(1)
|
||||
})
|
||||
|
||||
it("trims the name before saving", async () => {
|
||||
await createTeamUseCase({ name: " Engineering " })
|
||||
|
||||
const team = await prisma.team.findFirst({
|
||||
where: { name: "Engineering" },
|
||||
})
|
||||
|
||||
expect(team).not.toBeNull()
|
||||
expect(team?.name).toBe("Engineering")
|
||||
})
|
||||
|
||||
it("updates a team and rejects unchanged or duplicate names", async () => {
|
||||
const team = await createTestTeam(prisma, { name: "Peripherals" })
|
||||
const other = await createTestTeam(prisma, { name: "Networking" })
|
||||
|
||||
expect(
|
||||
await updateTeamUseCase({ id: team.id, name: "Accessories" }),
|
||||
).toEqual({ success: true })
|
||||
|
||||
expect(
|
||||
await prisma.team.findUniqueOrThrow({ where: { id: team.id } }),
|
||||
).toMatchObject({ name: "Accessories" })
|
||||
|
||||
expect(
|
||||
await updateTeamUseCase({ id: team.id, name: "Accessories" }),
|
||||
).toEqual({
|
||||
success: false,
|
||||
errors: { name: ["Team name is the same"] },
|
||||
})
|
||||
|
||||
expect(
|
||||
await updateTeamUseCase({ id: team.id, name: other.name }),
|
||||
).toEqual({
|
||||
success: false,
|
||||
errors: { name: ["Team already exists"] },
|
||||
})
|
||||
|
||||
expect(
|
||||
await prisma.team.findUniqueOrThrow({ where: { id: team.id } }),
|
||||
).toMatchObject({ name: "Accessories" })
|
||||
})
|
||||
|
||||
it("returns not found when updating a missing team", async () => {
|
||||
expect(
|
||||
await updateTeamUseCase({
|
||||
id: "00000000-0000-0000-0000-000000000000",
|
||||
name: "Ghost",
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
errors: { id: ["Team not found"] },
|
||||
})
|
||||
})
|
||||
|
||||
it("hard deletes a team", async () => {
|
||||
const team = await createTestTeam(prisma, { name: "Legacy" })
|
||||
|
||||
expect(await deleteTeamUseCase(team.id)).toEqual({ success: true })
|
||||
|
||||
expect(await prisma.team.findUnique({ where: { id: team.id } })).toBeNull()
|
||||
})
|
||||
|
||||
it("returns not found when deleting a missing team", async () => {
|
||||
expect(
|
||||
await deleteTeamUseCase("00000000-0000-0000-0000-000000000000"),
|
||||
).toEqual({
|
||||
success: false,
|
||||
errors: { id: ["Team not found"] },
|
||||
})
|
||||
})
|
||||
|
||||
it("nulls linked Person.teamId when a team is deleted", async () => {
|
||||
const team = await createTestTeam(prisma, { name: "Assigned" })
|
||||
const person = await createTestPerson(prisma)
|
||||
|
||||
await prisma.person.update({
|
||||
where: { id: person.id },
|
||||
data: { teamId: team.id },
|
||||
})
|
||||
|
||||
expect(await deleteTeamUseCase(team.id)).toEqual({ success: true })
|
||||
|
||||
const updatedPerson = await prisma.person.findUnique({
|
||||
where: { id: person.id },
|
||||
})
|
||||
|
||||
expect(updatedPerson).not.toBeNull()
|
||||
expect(updatedPerson?.teamId).toBeNull()
|
||||
})
|
||||
|
||||
it("lists all teams ordered by name", async () => {
|
||||
await createTestTeam(prisma, { name: "Beta" })
|
||||
await createTestTeam(prisma, { name: "Alpha" })
|
||||
await createTestTeam(prisma, { name: "Gamma" })
|
||||
|
||||
const teams = await listTeamsUseCase()
|
||||
|
||||
expect(teams).toHaveLength(3)
|
||||
expect(teams.map((team) => team.name)).toEqual(["Alpha", "Beta", "Gamma"])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user