import 'package:flutter_test/flutter_test.dart'; import 'package:own_ledger/src/services/balance_calculator.dart'; void main() { group('computeBalance', () { test('happy path with realistic month data', () { final result = computeBalance( month: MonthSnapshot( openingBalanceCents: 0, paychecks: [ PaycheckSnapshot( label: 'Paycheck', amountCents: 324000, items: [ const ItemSnapshot(label: 'Gas', amountCents: 8500), const ItemSnapshot(label: 'Groceries', amountCents: 14230), const ItemSnapshot(label: 'Other', amountCents: 4300), ], ), ], priorityPayouts: [ const ItemSnapshot(label: 'Owed to friend', amountCents: 4500), ], bills: [ const BillSnapshot(id: 1, label: 'Rent', defaultAmountCents: 185000), const BillSnapshot(id: 2, label: 'Electric', defaultAmountCents: 12743), const BillSnapshot(id: 3, label: 'Internet', defaultAmountCents: 7499), const BillSnapshot(id: 4, label: 'Phone', defaultAmountCents: 8500), const BillSnapshot(id: 5, label: 'Car Insurance', defaultAmountCents: 16400), const BillSnapshot(id: 6, label: 'Student Loan', defaultAmountCents: 31250), const BillSnapshot(id: 10, label: 'CC Chase', defaultAmountCents: 32537), const BillSnapshot(id: 11, label: 'CC Discover', defaultAmountCents: 7500), ], notablePayouts: [ const ItemSnapshot(label: 'Concert tickets', amountCents: 8900), ], ), ); // opening = 0 // + Paycheck 324000 → 324000 // - Gas 8500 → 315500 // - Groceries 14230 → 301270 // - Other 4300 → 296970 // - Owed to friend 4500 → 292470 // - Rent 185000 → 107470 // - Electric 12743 → 94727 // - Internet 7499 → 87228 // - Phone 8500 → 78728 // - Car Insurance 16400 → 62328 // - Student Loan 31250 → 31078 // - CC Chase 32537 → -1459 // - CC Discover 7500 → -8959 ← balanceBeforeCc (after all bills) // - Concert 8900 → -17859 expect(result.balanceBeforeCcCents, -8959); expect(result.remainingCents, -17859); expect(result.entries.length, 15); // opening + 14 items }); test('empty month — returns opening balance', () { final result = computeBalance( month: const MonthSnapshot(openingBalanceCents: 50000), ); expect(result.remainingCents, 50000); expect(result.balanceBeforeCcCents, 50000); expect(result.entries.length, 1); expect(result.entries.first.runningBalanceCents, 50000); }); test('single paycheck, no bills', () { final result = computeBalance( month: MonthSnapshot( openingBalanceCents: 0, paychecks: [ const PaycheckSnapshot(label: 'Pay', amountCents: 300000, items: []), ], ), ); expect(result.remainingCents, 300000); expect(result.balanceBeforeCcCents, 300000); }); test('negative balance — bills exceed income', () { final result = computeBalance( month: MonthSnapshot( openingBalanceCents: 0, paychecks: [ const PaycheckSnapshot(label: 'Pay', amountCents: 100000, items: []), ], bills: [ const BillSnapshot(id: 1, label: 'Rent', defaultAmountCents: 185000), ], ), ); expect(result.remainingCents, -85000); }); test('zero opening balance is default', () { final result = computeBalance( month: MonthSnapshot( openingBalanceCents: 0, bills: [ const BillSnapshot(id: 1, label: 'Phone', defaultAmountCents: 8500), ], ), ); expect(result.remainingCents, -8500); expect(result.entries.first.runningBalanceCents, 0); }); test('bill with amount override uses override', () { final result = computeBalance( month: MonthSnapshot( openingBalanceCents: 100000, bills: [ const BillSnapshot( id: 1, label: 'Electric', defaultAmountCents: 12000, amountOverrideCents: 15000, ), ], ), ); expect(result.remainingCents, 85000); }); test('all bills deducted uniformly', () { final result = computeBalance( month: MonthSnapshot( openingBalanceCents: 100000, bills: [ const BillSnapshot(id: 1, label: 'Rent', defaultAmountCents: 50000), const BillSnapshot(id: 2, label: 'CC', defaultAmountCents: 20000), ], ), ); // 100000 - 50000 - 20000 = 30000 expect(result.remainingCents, 30000); }); }); }