diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-15 11:02:34 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-15 11:02:34 +0200 |
| commit | 07f4134d38e53bf6c9235f3ad18dd5b33e89d9ff (patch) | |
| tree | 65eed6420426560a7e8127baa3ea7a703d1223a0 /tests/integration | |
| parent | 50cb852130986249cacec411e23392a8610e12f1 (diff) | |
| download | firefly-cli-07f4134d38e53bf6c9235f3ad18dd5b33e89d9ff.tar.gz firefly-cli-07f4134d38e53bf6c9235f3ad18dd5b33e89d9ff.zip | |
New `piggy` group:
- `piggy list` lists piggy banks with saved/target amounts and linked
accounts.
- `piggy add|remove <name|id> <amount> [--account NAME]` changes the
saved amount on a linked account via PUT /piggy-banks/{id}.
Firefly syncs the whole account list on that PUT, so every linked account
is resent (others without current_amount, which keeps their value) or it
would be unlinked. Removing below zero is rejected before any write, and
the saved amount is read back so a refused add fails loudly instead of
returning 200 unchanged.
add/remove currently hit an upstream bug on Firefly III <= 6.7.9:
PiggyBankFactory::linkToAccountIds passes the pivot current_amount (an int
from the DB) to bcsub() uncast, so any PUT with "accounts" 500s
(firefly-iii/firefly-iii#13063). Documented in SKILL.md/README; the live
integration test skips on that error and runs once upstream is fixed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/integration')
| -rw-r--r-- | tests/integration/test_live.py | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/tests/integration/test_live.py b/tests/integration/test_live.py index a815b88..ec900d7 100644 --- a/tests/integration/test_live.py +++ b/tests/integration/test_live.py @@ -54,3 +54,46 @@ class TestLive(unittest.TestCase): self.assertEqual(got["data"]["id"], tx_id) finally: self.client.request("DELETE", f"/api/v1/transactions/{tx_id}") + + def test_piggy_add_remove_roundtrip(self): + # Create a piggy bank on the TEST account, drive it through the CLI + # handlers, then delete it. + import io, contextlib, json + from types import SimpleNamespace + from firefly_cli.commands import piggy + from firefly_cli.errors import FireflyError + accs = unwrap(self.client.request("GET", "/api/v1/accounts", + params={"type": "asset", "limit": 50})) + acc = next((a for a in accs if float(a.get("current_balance") or 0) >= 10), None) + if acc is None: + self.skipTest("test account has no asset account with >= 10 balance") + created = self.client.request("POST", "/api/v1/piggy-banks", body={ + "name": "firefly-cli integration piggy", "target_amount": "100", + "transaction_currency_code": acc.get("currency_code") or "EUR", + "start_date": "2026-01-01", + "accounts": [{"account_id": acc["id"], "current_amount": "0"}]}) + pb_id = created["data"]["id"] + ctx = SimpleNamespace(client=self.client, resolver=self.resolver, human=False) + + def run(fn, amount): + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + fn(SimpleNamespace(ref=pb_id, amount=amount, account=None), ctx) + return json.loads(buf.getvalue())["accounts"][0]["current_amount"] + try: + from firefly_cli.errors import ApiError + try: + first = run(piggy.cmd_add, "2.09") + except ApiError as e: + if "bcsub()" in str(e): + self.skipTest("firefly-iii/firefly-iii#13063: piggy PUT with accounts 500s") + raise + self.assertEqual(float(first), 2.09) + self.assertEqual(float(run(piggy.cmd_add, "0.91")), 3.00) + self.assertEqual(float(run(piggy.cmd_remove, "1")), 2.00) + with self.assertRaises(FireflyError): # more than the account holds + run(piggy.cmd_add, "99999999") + linked = unwrap(self.client.request("GET", f"/api/v1/piggy-banks/{pb_id}"))["accounts"] + self.assertEqual(len(linked), 1) # PUT did not unlink the account + finally: + self.client.request("DELETE", f"/api/v1/piggy-banks/{pb_id}") |
