diff options
| author | Danilo M. <danix@danix.xyz> | 2026-06-30 17:55:30 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-06-30 17:55:30 +0200 |
| commit | 38d7357f36e6eeb91216d1c5668fb29406c7e076 (patch) | |
| tree | c9215bfd05ae08198e5dd02b8f4e7c9762dcbc77 /tests | |
| parent | 39d9c808c4f599d0708eccdaf883147e6cd1e9b9 (diff) | |
| download | firefly-cli-38d7357f36e6eeb91216d1c5668fb29406c7e076.tar.gz firefly-cli-38d7357f36e6eeb91216d1c5668fb29406c7e076.zip | |
Implements ISSUES.md #1, the missing other half of an import tool:
correcting and removing mis-imported transactions without the web UI.
- tx edit <id>: PATCH a single-split journal; only the fields passed are
sent (--amount/--date/--desc/--from/--to/--category/--tags/--type). Errors
if no field is given. Accounts resolve to ids; category/tags pass raw.
- tx delete <id>: requires --yes (no interactive prompt, agent-first);
prints {"deleted": "<id>"} on success.
Also fix gen_completion.py: running it as a script put scripts/ on
sys.path[0] and imported the installed (stale) firefly_cli, so the
generated completion drifted (missing account balance/get, tx get/search).
Prepend the repo root so the documented regen command uses this tree. The
regenerated completion now reflects the full command surface.
MINOR bump per the contract-keyed scheme: new commands, no breaking change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/unit/test_commands_transaction.py | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tests/unit/test_commands_transaction.py b/tests/unit/test_commands_transaction.py index 7301002..325dcb7 100644 --- a/tests/unit/test_commands_transaction.py +++ b/tests/unit/test_commands_transaction.py @@ -67,6 +67,73 @@ class TestTxAdd(unittest.TestCase): self.assertEqual(split["category_name"], "Brand New Cat") resolver.category.assert_not_called() +class TestTxEdit(unittest.TestCase): + def test_edit_sends_only_provided_fields(self): + ctx, client, resolver = make_ctx() + client.request.return_value = {"data": {"id": "9", "attributes": {}}} + args = MagicMock(id="9", amount="12.00", date=None, desc="fixed", + source=None, dest=None, category=None, tags=None, type=None) + rc = tx.cmd_edit(args, ctx) + self.assertEqual(rc, 0) + method, path = client.request.call_args[0][:2] + split = client.request.call_args[1]["body"]["transactions"][0] + self.assertEqual((method, path), ("PUT", "/api/v1/transactions/9")) + self.assertEqual(split, {"amount": "12.00", "description": "fixed"}) + resolver.account.assert_not_called() + + def test_edit_resolves_accounts_when_given(self): + ctx, client, resolver = make_ctx() + resolver.account.side_effect = lambda n: { + "BBVA": {"id": "3", "name": "BBVA", "type": "asset"}, + "Medio": {"id": "4", "name": "Medio", "type": "asset"}, + }[n] + client.request.return_value = {"data": {"id": "9", "attributes": {}}} + args = MagicMock(id="9", amount=None, date=None, desc=None, + source="BBVA", dest="Medio", category=None, tags=None, type=None) + tx.cmd_edit(args, ctx) + split = client.request.call_args[1]["body"]["transactions"][0] + self.assertEqual(split, {"source_id": "3", "destination_id": "4"}) + + def test_edit_category_raw_and_tags_split(self): + ctx, client, resolver = make_ctx() + client.request.return_value = {"data": {"id": "9", "attributes": {}}} + args = MagicMock(id="9", amount=None, date=None, desc=None, source=None, + dest=None, category="Cat", tags="a, b", type="transfer") + tx.cmd_edit(args, ctx) + split = client.request.call_args[1]["body"]["transactions"][0] + self.assertEqual(split, + {"category_name": "Cat", "tags": ["a", "b"], "type": "transfer"}) + resolver.category.assert_not_called() + + def test_edit_with_no_fields_errors(self): + from firefly_cli.errors import FireflyError + ctx, client, _ = make_ctx() + args = MagicMock(id="9", amount=None, date=None, desc=None, source=None, + dest=None, category=None, tags=None, type=None) + with self.assertRaises(FireflyError): + tx.cmd_edit(args, ctx) + client.request.assert_not_called() + + +class TestTxDelete(unittest.TestCase): + def test_delete_requires_yes(self): + from firefly_cli.errors import FireflyError + ctx, client, _ = make_ctx() + args = MagicMock(id="9", yes=False) + with self.assertRaises(FireflyError): + tx.cmd_delete(args, ctx) + client.request.assert_not_called() + + def test_delete_with_yes(self): + ctx, client, _ = make_ctx() + client.request.return_value = {} + args = MagicMock(id="9", yes=True) + rc = tx.cmd_delete(args, ctx) + self.assertEqual(rc, 0) + method, path = client.request.call_args[0][:2] + self.assertEqual((method, path), ("DELETE", "/api/v1/transactions/9")) + + class TestTxList(unittest.TestCase): def test_list_passes_date_params(self): ctx, client, _ = make_ctx() |
