budget/BudgetApp.Tests/Domain/LedgerTests.cs
2026-01-03 10:29:03 -06:00

153 lines
5.0 KiB
C#

namespace BudgetApp.Tests.Domain;
using BudgetApp.Domain.Models;
using Xunit;
public class LedgerTests
{
[Fact]
public void Constructor_CreatesEmptyLedger()
{
// Arrange & Act
var ledger = new Ledger();
// Assert
Assert.Empty(ledger.Entries);
}
[Fact]
public void AddEntry_WithValidEntry_AddsToLedger()
{
// Arrange
var ledger = new Ledger();
var budgetAllocations = new Dictionary<Guid, Money>
{
{ Guid.NewGuid(), new Money(100m, "USD") }
};
var entry = new LedgerEntry(
DateTime.Now,
"Grocery Shopping",
new Money(100m, "USD"),
EntryType.Expense,
budgetAllocations);
// Act
ledger.AddEntry(entry);
// Assert
Assert.Single(ledger.Entries);
Assert.Equal(entry, ledger.Entries.First());
}
[Fact]
public void AddEntry_WithInvalidEntry_ThrowsException()
{
// Arrange
var ledger = new Ledger();
var budgetAllocations = new Dictionary<Guid, Money>
{
{ Guid.NewGuid(), new Money(50m, "USD") }
};
// Act & Assert - The exception is thrown during construction, not when adding
Assert.Throws<InvalidOperationException>(() => new LedgerEntry(
Guid.NewGuid(),
DateTime.Now,
"Grocery Shopping",
new Money(100m, "USD"),
EntryType.Expense,
budgetAllocations));
}
[Fact]
public void GetEntriesByType_ReturnsOnlyMatchingType()
{
// Arrange
var ledger = new Ledger();
var expenseAllocations = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(100m, "USD") } };
var incomeAllocations = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(1000m, "USD") } };
var expense = new LedgerEntry(DateTime.Now, "Expense", new Money(100m, "USD"), EntryType.Expense, expenseAllocations);
var income = new LedgerEntry(DateTime.Now, "Income", new Money(1000m, "USD"), EntryType.Income, incomeAllocations);
ledger.AddEntry(expense);
ledger.AddEntry(income);
// Act
var expenses = ledger.GetEntriesByType(EntryType.Expense);
var incomes = ledger.GetEntriesByType(EntryType.Income);
// Assert
Assert.Single(expenses);
Assert.Single(incomes);
Assert.Equal(EntryType.Expense, expenses.First().Type);
Assert.Equal(EntryType.Income, incomes.First().Type);
}
[Fact]
public void CalculateTotalByType_ReturnsCorrectTotal()
{
// Arrange
var ledger = new Ledger();
var expenseAllocations1 = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(100m, "USD") } };
var expenseAllocations2 = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(200m, "USD") } };
var expense1 = new LedgerEntry(DateTime.Now, "Expense 1", new Money(100m, "USD"), EntryType.Expense, expenseAllocations1);
var expense2 = new LedgerEntry(DateTime.Now, "Expense 2", new Money(200m, "USD"), EntryType.Expense, expenseAllocations2);
ledger.AddEntry(expense1);
ledger.AddEntry(expense2);
// Act
var total = ledger.CalculateTotalByType(EntryType.Expense, "USD");
// Assert
Assert.Equal(300m, total.Amount);
}
[Fact]
public void CalculateNetBalance_ReturnsIncomeMinusExpenses()
{
// Arrange
var ledger = new Ledger();
var expenseAllocations = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(100m, "USD") } };
var incomeAllocations = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(1000m, "USD") } };
var expense = new LedgerEntry(DateTime.Now, "Expense", new Money(100m, "USD"), EntryType.Expense, expenseAllocations);
var income = new LedgerEntry(DateTime.Now, "Income", new Money(1000m, "USD"), EntryType.Income, incomeAllocations);
ledger.AddEntry(expense);
ledger.AddEntry(income);
// Act
var netBalance = ledger.CalculateNetBalance("USD");
// Assert
Assert.Equal(900m, netBalance.Amount);
}
[Fact]
public void GetEntriesForBudget_ReturnsEntriesWithBudgetAllocation()
{
// Arrange
var budgetId = Guid.NewGuid();
var ledger = new Ledger();
var allocations1 = new Dictionary<Guid, Money> { { budgetId, new Money(100m, "USD") } };
var allocations2 = new Dictionary<Guid, Money> { { Guid.NewGuid(), new Money(200m, "USD") } };
var entry1 = new LedgerEntry(DateTime.Now, "Entry 1", new Money(100m, "USD"), EntryType.Expense, allocations1);
var entry2 = new LedgerEntry(DateTime.Now, "Entry 2", new Money(200m, "USD"), EntryType.Expense, allocations2);
ledger.AddEntry(entry1);
ledger.AddEntry(entry2);
// Act
var entries = ledger.GetEntriesForBudget(budgetId);
// Assert
Assert.Single(entries);
Assert.Equal(entry1, entries.First());
}
}