Files
SkyMoney/api/tests/allocator.test.ts

66 lines
2.2 KiB
TypeScript

// tests/allocator.test.ts
import { describe, it, expect, beforeEach, afterAll } from "vitest";
import { prisma, resetUser, ensureUser, U, cid, pid, closePrisma } from "./helpers";
import { allocateIncome } from "../src/allocator";
describe("allocator — core behaviors", () => {
beforeEach(async () => {
await resetUser(U);
await ensureUser(U);
});
afterAll(async () => {
await closePrisma();
});
it("distributes remainder to variables by largest remainder with savings-first tie", async () => {
const c1 = cid("c1");
const c2 = cid("c2"); // make this savings to test the tiebreaker
await prisma.variableCategory.createMany({
data: [
{ id: c1, userId: U, name: "Groceries", percent: 60, priority: 2, isSavings: false, balanceCents: 0n },
{ id: c2, userId: U, name: "Saver", percent: 40, priority: 1, isSavings: true, balanceCents: 0n },
],
});
const p1 = pid("rent");
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",
},
});
// $100 income
const result = await allocateIncome(prisma as any, U, 10000, new Date().toISOString(), "inc1");
expect(result).toBeDefined();
// rent should be funded first up to need
const fixed = result.fixedAllocations ?? [];
const variable = result.variableAllocations ?? [];
// sanity
expect(Array.isArray(fixed)).toBe(true);
expect(Array.isArray(variable)).toBe(true);
});
it("handles zeros and single bucket", async () => {
const cOnly = cid("only");
await prisma.variableCategory.create({
data: { id: cOnly, userId: U, name: "Only", percent: 100, priority: 1, isSavings: false, balanceCents: 0n },
});
const result = await allocateIncome(prisma as any, U, 0, new Date().toISOString(), "inc2");
expect(result).toBeDefined();
const variable = result.variableAllocations ?? [];
const sum = variable.reduce((s, a: any) => s + (a.amountCents ?? 0), 0);
expect(sum).toBe(0);
});
});