From 092e05361a534a8f35d7b551afa77004e30cf201 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 30 Jun 2026 10:56:51 +0200 Subject: feat: HTTP client with auth and error surfacing --- tests/unit/test_client.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/unit/test_client.py (limited to 'tests') 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") -- cgit v1.2.3