summaryrefslogtreecommitdiffstats
path: root/tests/unit/test_commands_transaction.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-07-01 12:13:42 +0200
committerDanilo M. <danix@danix.xyz>2026-07-01 12:13:42 +0200
commit941ccb2cb34944e1321b3dc23731bfa93018d74f (patch)
tree72f5ccb1c9c0d90c320aa17dda4ddb4b8a444f40 /tests/unit/test_commands_transaction.py
parent60e15f9ced98c270a48d58ac000738afb78c2d7e (diff)
downloadfirefly-cli-941ccb2cb34944e1321b3dc23731bfa93018d74f.tar.gz
firefly-cli-941ccb2cb34944e1321b3dc23731bfa93018d74f.zip
feat: tx list --flat, account create --if-not-exists, --since/--until doc (v0.3.6)v0.3.6
Three smaller ISSUES.md items, one PATCH (two optional flags + a doc fix; no existing caller or JSON shape changes). - tx list --flat: emit one top-level object per split (journal id repeated), dropping the transactions[] nesting so single-split journals script cleanly. JSON-only; --human already explodes splits into a table. - account create --if-not-exists: resolve the name first; on a clash return the existing account with "existed": true (exit 0) instead of surfacing Firefly's 422, so import scripts are idempotent. Detects via resolver, not by parsing the error string. - SKILL.md documents that --since/--until filter on the transaction date (the value date); Firefly journals have a single date field, no separate book date (verified against firefly-iii TimeCollection setRange). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'tests/unit/test_commands_transaction.py')
-rw-r--r--tests/unit/test_commands_transaction.py45
1 files changed, 41 insertions, 4 deletions
diff --git a/tests/unit/test_commands_transaction.py b/tests/unit/test_commands_transaction.py
index 0fa02ac..28882d3 100644
--- a/tests/unit/test_commands_transaction.py
+++ b/tests/unit/test_commands_transaction.py
@@ -264,7 +264,7 @@ class TestTxList(unittest.TestCase):
ctx, client, _ = make_ctx()
client.request.return_value = {"data": []}
args = MagicMock(since="2026-06-01", until="2026-06-30",
- account=None, limit=10, all=False)
+ account=None, limit=10, all=False, flat=False)
tx.cmd_list(args, ctx)
params = client.request.call_args[1]["params"]
self.assertEqual(params["start"], "2026-06-01")
@@ -280,7 +280,7 @@ class TestTxList(unittest.TestCase):
"meta": {"pagination": {"total": 90, "count": 20,
"current_page": 1, "total_pages": 5}},
}
- args = MagicMock(since=None, until=None, account=None, limit=20, all=False)
+ args = MagicMock(since=None, until=None, account=None, limit=20, all=False, flat=False)
buf = io.StringIO()
with redirect_stderr(buf):
tx.cmd_list(args, ctx)
@@ -296,12 +296,49 @@ class TestTxList(unittest.TestCase):
"meta": {"pagination": {"total": 1, "count": 1,
"current_page": 1, "total_pages": 1}},
}
- args = MagicMock(since=None, until=None, account=None, limit=20, all=False)
+ args = MagicMock(since=None, until=None, account=None, limit=20, all=False, flat=False)
buf = io.StringIO()
with redirect_stderr(buf):
tx.cmd_list(args, ctx)
self.assertEqual(buf.getvalue(), "")
+ def test_list_flat_explodes_splits_json(self):
+ import io, json
+ from contextlib import redirect_stdout
+ ctx, client, _ = make_ctx()
+ client.request.return_value = {
+ "data": [{"id": "7", "type": "transactions", "attributes": {
+ "transactions": [{"amount": "5", "source_name": "A"}]}}],
+ "meta": {"pagination": {"total": 1, "count": 1, "total_pages": 1}},
+ }
+ args = MagicMock(since=None, until=None, account=None, limit=20,
+ all=False, flat=True)
+ buf = io.StringIO()
+ with redirect_stdout(buf):
+ tx.cmd_list(args, ctx)
+ out = json.loads(buf.getvalue())
+ self.assertEqual(out, [{"amount": "5", "source_name": "A", "id": "7"}])
+
+ def test_list_flat_skipped_for_human(self):
+ # --human path must keep nested rows so the table renderer explodes them.
+ import io
+ from contextlib import redirect_stdout
+ ctx, client, _ = make_ctx()
+ ctx = Context(client=client, resolver=ctx.resolver, human=True)
+ client.request.return_value = {
+ "data": [{"id": "7", "attributes": {
+ "transactions": [{"amount": "5", "source_name": "A",
+ "destination_name": "B", "type": "withdrawal"}]}}],
+ "meta": {"pagination": {"total": 1, "count": 1, "total_pages": 1}},
+ }
+ args = MagicMock(since=None, until=None, account=None, limit=20,
+ all=False, flat=True)
+ buf = io.StringIO()
+ with redirect_stdout(buf):
+ tx.cmd_list(args, ctx)
+ # human table shows the exploded split value; not raw JSON
+ self.assertIn("5", buf.getvalue())
+
def test_list_all_paginates(self):
ctx, client, _ = make_ctx()
def page(method, path, params=None, body=None):
@@ -312,7 +349,7 @@ class TestTxList(unittest.TestCase):
"current_page": p, "total_pages": 2}},
}
client.request.side_effect = page
- args = MagicMock(since=None, until=None, account=None, limit=2, all=True)
+ args = MagicMock(since=None, until=None, account=None, limit=2, all=True, flat=False)
rc = tx.cmd_list(args, ctx)
self.assertEqual(rc, 0)
self.assertEqual(client.request.call_count, 2)