aboutsummaryrefslogtreecommitdiffstats
path: root/tests/unit
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-06-30 10:56:51 +0200
committerDanilo M. <danix@danix.xyz>2026-06-30 10:56:51 +0200
commit092e05361a534a8f35d7b551afa77004e30cf201 (patch)
treeecbe8c664cd4ca0f2d64cca8e5999ded5919d3e6 /tests/unit
parent8e7cb60beaa6fe01c1e4de57d90f434bcb3bd6a7 (diff)
downloadfirefly-cli-092e05361a534a8f35d7b551afa77004e30cf201.tar.gz
firefly-cli-092e05361a534a8f35d7b551afa77004e30cf201.zip
feat: HTTP client with auth and error surfacing
Diffstat (limited to 'tests/unit')
-rw-r--r--tests/unit/test_client.py47
1 files changed, 47 insertions, 0 deletions
diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py
new file mode 100644
index 0000000..e63be08
--- /dev/null
+++ b/tests/unit/test_client.py
@@ -0,0 +1,47 @@
+import json, unittest
+from unittest.mock import patch, MagicMock
+from io import BytesIO
+import urllib.error
+from firefly_cli.client import Client
+from firefly_cli.errors import ApiError
+
+def fake_response(payload, status=200):
+ r = MagicMock()
+ r.read.return_value = json.dumps(payload).encode()
+ r.status = status
+ r.__enter__.return_value = r
+ r.__exit__.return_value = False
+ return r
+
+class TestClient(unittest.TestCase):
+ def setUp(self):
+ self.c = Client("https://f.example", "tok")
+
+ @patch("firefly_cli.client.urllib.request.urlopen")
+ def test_get_builds_url_and_headers(self, urlopen):
+ urlopen.return_value = fake_response({"data": []})
+ out = self.c.request("GET", "/api/v1/accounts", params={"type": "asset"})
+ req = urlopen.call_args[0][0]
+ self.assertEqual(req.full_url, "https://f.example/api/v1/accounts?type=asset")
+ self.assertEqual(req.get_header("Authorization"), "Bearer tok")
+ self.assertEqual(req.get_header("Accept"), "application/vnd.api+json")
+ self.assertEqual(out, {"data": []})
+
+ @patch("firefly_cli.client.urllib.request.urlopen")
+ def test_post_sends_json_body(self, urlopen):
+ urlopen.return_value = fake_response({"data": {"id": "9"}})
+ self.c.request("POST", "/api/v1/transactions", body={"x": 1})
+ req = urlopen.call_args[0][0]
+ self.assertEqual(req.get_method(), "POST")
+ self.assertEqual(json.loads(req.data), {"x": 1})
+ self.assertEqual(req.get_header("Content-type"), "application/json")
+
+ @patch("firefly_cli.client.urllib.request.urlopen")
+ def test_http_error_becomes_apierror(self, urlopen):
+ body = json.dumps({"message": "boom"}).encode()
+ urlopen.side_effect = urllib.error.HTTPError(
+ "u", 422, "Unprocessable", {}, BytesIO(body))
+ with self.assertRaises(ApiError) as ctx:
+ self.c.request("GET", "/api/v1/accounts")
+ self.assertEqual(ctx.exception.status, 422)
+ self.assertEqual(ctx.exception.body["message"], "boom")