Ledgerly/tests/test_budgets_service.py

62 lines
1.7 KiB
Python
Raw Normal View History

2026-10-27 16:04:50 +00:00
"""Tests for ledgerly.services.budgets (R2, R7)."""
import pytest
from ledgerly.errors import NotFoundError, ValidationError
from ledgerly.money import Money
from ledgerly.repository import SqliteRepository
from ledgerly.services import BudgetService
@pytest.fixture()
def service():
repo = SqliteRepository(":memory:")
yield BudgetService(repo)
repo.close()
def test_set_budget(service):
budget = service.set_budget("Rent", Money(150000))
assert budget.category == "Rent"
assert budget.amount == Money(150000)
assert service.list_budgets() == [budget]
def test_set_budget_replaces(service):
service.set_budget("Rent", Money(100))
service.set_budget("Rent", Money(200))
assert [b.amount for b in service.list_budgets()] == [Money(200)]
def test_set_budget_rejects_zero(service):
with pytest.raises(ValidationError, match="greater than zero"):
service.set_budget("Rent", Money(0))
def test_set_budget_unknown_category(service):
with pytest.raises(NotFoundError):
service.set_budget("Nope", Money(100))
def test_set_budget_rejects_income_category(service):
with pytest.raises(ValidationError, match="expense"):
service.set_budget("Salary", Money(100))
def test_delete_budget_missing_category(service):
with pytest.raises(NotFoundError):
service.delete_budget("Nope")
def test_delete_budget_not_set(service):
with pytest.raises(NotFoundError, match="no budget"):
service.delete_budget("Rent")
def test_delete_budget_ok(service):
service.set_budget("Rent", Money(100))
deleted = service.delete_budget("rent")
assert deleted.category == "Rent"
assert deleted.amount == Money(100)
assert service.list_budgets() == []