# Copyright (C) 2026 Danilo M. GPL-2.0-only import unittest from unittest.mock import MagicMock from types import SimpleNamespace import firefly_cli.commands.budget as budget def _ctx(client=None, resolver=None): return SimpleNamespace(client=client or MagicMock(), resolver=resolver or MagicMock(), human=False) class TestBudgetList(unittest.TestCase): def test_list_defaults_to_current_month(self): client = MagicMock() client.request.return_value = {"data": []} args = SimpleNamespace(start=None, end=None) rc = budget.cmd_list(args, _ctx(client=client)) self.assertEqual(rc, 0) _, kwargs = client.request.call_args params = kwargs["params"] self.assertTrue(params["start"].endswith("-01")) self.assertEqual(params["start"][:7], params["end"][:7]) def test_list_explicit_range(self): client = MagicMock() client.request.return_value = {"data": []} args = SimpleNamespace(start="2026-01-01", end="2026-01-31") budget.cmd_list(args, _ctx(client=client)) _, kwargs = client.request.call_args self.assertEqual(kwargs["params"], {"start": "2026-01-01", "end": "2026-01-31"}) class TestBudgetCreate(unittest.TestCase): def test_create_minimal_active(self): client = MagicMock() client.request.return_value = {"data": {"id": "9", "attributes": {"name": "Fun"}}} args = SimpleNamespace(name="Fun", active=True, currency=None, auto_budget_amount=None, auto_budget_period=None, auto_budget_type=None) rc = budget.cmd_create(args, _ctx(client=client)) self.assertEqual(rc, 0) method, path = client.request.call_args[0][:2] body = client.request.call_args[1]["body"] self.assertEqual((method, path), ("POST", "/api/v1/budgets")) self.assertEqual(body["name"], "Fun") self.assertTrue(body["active"]) def test_create_inactive_with_auto_budget(self): client = MagicMock() client.request.return_value = {"data": {"id": "9", "attributes": {}}} args = SimpleNamespace(name="Cap", active=False, currency="EUR", auto_budget_amount="500", auto_budget_period="monthly", auto_budget_type="reset") budget.cmd_create(args, _ctx(client=client)) body = client.request.call_args[1]["body"] self.assertFalse(body["active"]) self.assertEqual(body["auto_budget_amount"], "500") self.assertEqual(body["auto_budget_type"], "reset") self.assertEqual(body["currency_code"], "EUR") class TestBudgetSpent(unittest.TestCase): def test_human_mode_replaces_spent_with_scalar(self): client = MagicMock() client.request.return_value = {"data": [ {"id": "1", "attributes": {"name": "Food", "spent": [{"sum": "-12.50"}, {"sum": "-2.50"}]}}]} ctx = _ctx(client=client) ctx.human = True captured = {} import firefly_cli.output as output orig = output.emit def spy(data, human=False, stream=None): captured["rows"] = data output.emit = spy try: budget.cmd_list(SimpleNamespace(start=None, end=None), ctx) finally: output.emit = orig self.assertEqual(captured["rows"][0]["spent"], "-15.00") if __name__ == "__main__": unittest.main()