import { describe, it, expect } from "vitest"; import { previewAllocation } from "../src/utils/allocatorPreview"; /** * Test case: Regular income user with payment plans * Budget: $2,000 per paycheck (weekly) * Fixed expenses: * 1. Rent: $1,200 (due in 4 weeks, payment plan enabled) - should fund $300/week * 2. Insurance: $400 (due in 2 weeks, payment plan enabled) - should fund $200/week * Variable categories: * 1. Groceries: 40% * 2. Entertainment: 30% * 3. Savings: 30% * * Expected allocation this paycheck: * - Fixed: $500 ($300 + $200) * - Variable: $1,500 (remaining after fixed) * - Groceries: $600 (40% of $1,500) * - Entertainment: $450 (30% of $1,500) * - Savings: $450 (30% of $1,500) */ describe("OnboardingTracker vs API Allocator", () => { it("should allocate budget correctly with payment plans", () => { const budgetCents = 200000; // $2,000 // Today's date for testing const now = new Date("2025-11-26"); // Fixed plans with payment plans enabled const fixedPlans = [ { id: "rent", name: "Rent", totalCents: 120000, // $1,200 fundedCents: 0, // Not yet funded dueOn: "2025-12-24", // 4 weeks from now (28 days) priority: 1, cycleStart: "2025-11-26", }, { id: "insurance", name: "Insurance", totalCents: 40000, // $400 fundedCents: 0, // Not yet funded dueOn: "2025-12-10", // 2 weeks from now (14 days) priority: 2, cycleStart: "2025-11-26", }, ]; // Variable categories const variableCategories = [ { id: "groceries", name: "Groceries", percent: 40, balanceCents: 0, isSavings: false, priority: 1, }, { id: "entertainment", name: "Entertainment", percent: 30, balanceCents: 0, isSavings: false, priority: 2, }, { id: "savings", name: "Savings", percent: 30, balanceCents: 0, isSavings: true, priority: 3, }, ]; // Calculate allocation using previewAllocation const result = previewAllocation(budgetCents, fixedPlans, variableCategories); console.log("\n=== ONBOARDING TRACKER TEST CASE ==="); console.log("Budget:", budgetCents / 100, "($2,000)"); console.log("\nFixed Expenses:"); result.fixed.forEach((f) => { const original = fixedPlans.find((fp) => fp.id === f.id); const daysUntilDue = Math.ceil( (new Date(original!.dueOn).getTime() - now.getTime()) / (24 * 60 * 60 * 1000) ); const weeksUntilDue = Math.ceil(daysUntilDue / 7); const expectedPerPaycheck = original!.totalCents / weeksUntilDue; console.log(` ${f.name}: $${f.amountCents / 100} allocated`); console.log(` Total needed: $${original!.totalCents / 100}`); console.log(` Due in: ${daysUntilDue} days (${weeksUntilDue} weeks)`); console.log(` Expected per paycheck: $${expectedPerPaycheck / 100}`); console.log(` Percentage funded: ${Math.round((f.amountCents / original!.totalCents) * 100)}%`); }); const totalFixedAllocated = result.fixed.reduce((sum, f) => sum + f.amountCents, 0); console.log(` Total Fixed Allocated: $${totalFixedAllocated / 100}`); console.log("\nVariable Categories:"); const totalVariableAllocated = result.variable.reduce((sum, v) => sum + v.amountCents, 0); console.log(` Total Available: $${totalVariableAllocated / 100}`); result.variable.forEach((v) => { const original = variableCategories.find((vc) => vc.id === v.id); const percentage = original?.percent || 0; const expectedAmount = Math.floor((totalVariableAllocated * percentage) / 100); console.log(` ${v.name}: $${v.amountCents / 100} (${percentage}%)`); console.log(` Expected: $${expectedAmount / 100}`); }); console.log("\nUnallocated:", result.unallocatedCents / 100); // Assertions // 1. Rent should get $300 (1200/4 weeks) const rentAllocation = result.fixed.find((f) => f.id === "rent"); expect(rentAllocation?.amountCents).toBe(30000); // $300 // 2. Insurance should get $200 (400/2 weeks) const insuranceAllocation = result.fixed.find((f) => f.id === "insurance"); expect(insuranceAllocation?.amountCents).toBe(20000); // $200 // 3. Total fixed should be $500 expect(totalFixedAllocated).toBe(50000); // 4. Variable budget should be $1,500 (2000 - 500) expect(totalVariableAllocated).toBe(150000); // 5. Groceries should get $600 (40% of $1,500) const groceriesAllocation = result.variable.find((v) => v.id === "groceries"); expect(groceriesAllocation?.amountCents).toBe(60000); // $600 // 6. Entertainment should get $450 (30% of $1,500) const entertainmentAllocation = result.variable.find((v) => v.id === "entertainment"); expect(entertainmentAllocation?.amountCents).toBe(45000); // $450 // 7. Savings should get $450 (30% of $1,500) const savingsAllocation = result.variable.find((v) => v.id === "savings"); expect(savingsAllocation?.amountCents).toBe(45000); // $450 // 8. No unallocated funds expect(result.unallocatedCents).toBe(0); console.log("\nāœ“ All assertions passed!"); }); it("should handle partial funding correctly", () => { const budgetCents = 100000; // $1,000 // Fixed plan that needs $600 total, already has $300 funded const fixedPlans = [ { id: "expense1", name: "Expense 1", totalCents: 60000, // $600 total fundedCents: 30000, // $300 already funded dueOn: "2025-12-10", priority: 1, cycleStart: "2025-11-26", }, ]; // Variable categories const variableCategories = [ { id: "cat1", name: "Category 1", percent: 50, balanceCents: 0, isSavings: false, priority: 1, }, { id: "cat2", name: "Category 2", percent: 50, balanceCents: 0, isSavings: false, priority: 2, }, ]; const result = previewAllocation(budgetCents, fixedPlans, variableCategories); console.log("\n=== PARTIAL FUNDING TEST ==="); console.log("Budget: $1,000"); console.log("Fixed expense needs: $600 total, $300 already funded"); console.log("Should allocate: $300 to fixed, $700 to variable"); const totalFixedAllocated = result.fixed.reduce((sum, f) => sum + f.amountCents, 0); const totalVariableAllocated = result.variable.reduce((sum, v) => sum + v.amountCents, 0); console.log("\nFixed allocated:", totalFixedAllocated / 100); console.log("Variable allocated:", totalVariableAllocated / 100); // Fixed should only get $300 (remaining need) expect(totalFixedAllocated).toBe(30000); // Variable should get $700 expect(totalVariableAllocated).toBe(70000); // Category 1 should get $350 (50% of $700) const cat1 = result.variable.find((v) => v.id === "cat1"); expect(cat1?.amountCents).toBe(35000); // Category 2 should get $350 (50% of $700) const cat2 = result.variable.find((v) => v.id === "cat2"); expect(cat2?.amountCents).toBe(35000); console.log("āœ“ Partial funding test passed!"); }); });