test: add initial unit integration and e2e coverage

Adds the initial testing baseline for the project:

   Unit coverage:
   - Zod schemas for items, assignments, movements, categories, auth, recipients, users, and assets
   - password hashing and verification helpers
   - auth role helper functions

   Integration coverage with PostgreSQL Testcontainers:
   - item use-cases: create, duplicate names, delete constraints
   - assignment use-cases: create, insufficient stock, return, double return
   - asset use-cases: available/assigned creation and lifecycle transitions
   - user use-cases: create/update, uniqueness, admin safeguards, password reset
   - category use-cases: create/update/delete constraints
   - recipient use-cases: create/update and uniqueness constraints

   E2E smoke coverage with Playwright:
   - unauthenticated redirect to login
   - seeded admin login
   - dashboard load
   - admin users page
   - inventory items page
   - assignments page

   Also configures:
   - Vitest
   - Playwright
   - PostgreSQL Testcontainers helpers
   - deterministic E2E admin bootstrap
   - test artifact ignores

   Validation:
   - bun run test: 9 files / 37 tests passed
   - bun run test:e2e: 3 passed
   - bunx tsc --noEmit: passed
   - bunx prisma validate: passed
This commit is contained in:
2026-06-07 04:14:01 +02:00
parent cb01f4f8ef
commit f2b9239d82
18 changed files with 2372 additions and 9 deletions
+95
View File
@@ -0,0 +1,95 @@
import type {
PrismaClient,
RecipientDepartment,
UserRole,
} from "@/generated/prisma/client"
let sequence = 0
function nextSuffix() {
sequence += 1
return `${Date.now()}-${sequence}`
}
export async function createTestUser(
prisma: PrismaClient,
overrides: Partial<{
username: string
email: string
name: string
role: UserRole
isActive: boolean
}> = {},
) {
const suffix = nextSuffix()
return prisma.user.create({
data: {
username: overrides.username ?? `test-user-${suffix}`,
email: overrides.email ?? `test-user-${suffix}@example.test`,
name: overrides.name ?? "Test User",
password: "hashed-password",
role: overrides.role ?? "ADMIN",
isActive: overrides.isActive ?? true,
},
})
}
export async function createTestCategory(
prisma: PrismaClient,
overrides: Partial<{ name: string }> = {},
) {
const suffix = nextSuffix()
return prisma.category.create({
data: {
name: overrides.name ?? `Test Category ${suffix}`,
},
})
}
export async function createTestRecipient(
prisma: PrismaClient,
overrides: Partial<{
username: string
firstName: string
lastName: string
department: RecipientDepartment
email: string | null
phone: string | null
}> = {},
) {
const suffix = nextSuffix()
return prisma.recipient.create({
data: {
username: overrides.username ?? `test-recipient-${suffix}`,
firstName: overrides.firstName ?? "Test",
lastName: overrides.lastName ?? "Recipient",
department: overrides.department ?? "OTHER",
email: overrides.email ?? null,
phone: overrides.phone ?? null,
},
})
}
export async function createTestItem(
prisma: PrismaClient,
overrides: Partial<{
name: string
stock: number
categoryId: string
}> = {},
) {
const categoryId =
overrides.categoryId ?? (await createTestCategory(prisma)).id
const suffix = nextSuffix()
return prisma.item.create({
data: {
name: overrides.name ?? `Test Item ${suffix}`,
stock: overrides.stock ?? 0,
category: { connect: { id: categoryId } },
},
})
}