import { beforeAll, afterAll, describe, it, expect } from "vitest"; import request from "supertest"; import { PrismaClient } from "@prisma/client"; import type { FastifyInstance } from "fastify"; import { resetUser } from "./helpers"; // Ensure env BEFORE importing the server process.env.NODE_ENV = process.env.NODE_ENV || "test"; process.env.PORT = process.env.PORT || "0"; process.env.DATABASE_URL = process.env.DATABASE_URL || "postgres://app:app@localhost:5432/skymoney"; const prisma = new PrismaClient(); let app: FastifyInstance; beforeAll(async () => { // dynamic import AFTER env is set const { default: srv } = await import("../src/server"); // <-- needs `export default app` in server.ts app = srv; await app.ready(); const U = "demo-user-1"; await resetUser(U); await prisma.user.upsert({ where: { id: U }, update: {}, create: { id: U, email: `${U}@demo.local` }, }); await prisma.variableCategory.createMany({ data: [ { id: "c1", userId: U, name: "Groceries", percent: 60, priority: 1, isSavings: false, balanceCents: 0n }, { id: "c2", userId: U, name: "Saver", percent: 40, priority: 2, isSavings: true, balanceCents: 0n }, ], skipDuplicates: true, }); await prisma.fixedPlan.create({ data: { id: "p1", userId: U, name: "Rent", cycleStart: new Date().toISOString(), dueOn: new Date(Date.now() + 7 * 864e5).toISOString(), totalCents: 10000n, fundedCents: 0n, priority: 1, fundingMode: "auto-on-deposit", }, }); }); afterAll(async () => { await app.close(); await prisma.$disconnect(); }); describe("POST /income integration", () => { it("allocates funds and returns audit", async () => { const res = await request(app.server) .post("/income") .set("x-user-id", "demo-user-1") .send({ amountCents: 5000 }); expect(res.status).toBe(200); expect(res.body).toHaveProperty("fixedAllocations"); expect(res.body).toHaveProperty("variableAllocations"); expect(typeof res.body.remainingUnallocatedCents).toBe("number"); }); });