Public Access
DEVX-145: feat: extract reusable components from infra and grm into devx
This commit was merged in pull request #230.
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
"""Unit tests for devx.utils.api.APIClient."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from devx.utils.api import APIClient
|
||||
|
||||
|
||||
class TestAPIClient:
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_get(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {"Authorization": "Bearer token"})
|
||||
result = client.get("/users")
|
||||
assert result is mock_resp
|
||||
mock_req.assert_called_once_with(
|
||||
"GET",
|
||||
"https://api.example.com/users",
|
||||
headers={"Authorization": "Bearer token"},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_post(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {})
|
||||
client.post("/users", json={"name": "alice"})
|
||||
mock_req.assert_called_once_with(
|
||||
"POST",
|
||||
"https://api.example.com/users",
|
||||
headers={},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
json={"name": "alice"},
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_put(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {})
|
||||
client.put("/users/1", json={"name": "bob"})
|
||||
mock_req.assert_called_once_with(
|
||||
"PUT",
|
||||
"https://api.example.com/users/1",
|
||||
headers={},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
json={"name": "bob"},
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_delete(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {})
|
||||
client.delete("/users/1")
|
||||
mock_req.assert_called_once_with(
|
||||
"DELETE",
|
||||
"https://api.example.com/users/1",
|
||||
headers={},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_patch(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {})
|
||||
client.patch("/users/1", json={"name": "carol"})
|
||||
mock_req.assert_called_once_with(
|
||||
"PATCH",
|
||||
"https://api.example.com/users/1",
|
||||
headers={},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
json={"name": "carol"},
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_auth_tuple(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {}, auth=("admin", "pass"))
|
||||
client.get("/data")
|
||||
mock_req.assert_called_once_with(
|
||||
"GET",
|
||||
"https://api.example.com/data",
|
||||
headers={},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
auth=("admin", "pass"),
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_custom_timeout_and_verify(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {}, timeout=60, verify=False)
|
||||
client.get("/data")
|
||||
mock_req.assert_called_once_with(
|
||||
"GET",
|
||||
"https://api.example.com/data",
|
||||
headers={},
|
||||
timeout=60,
|
||||
verify=False,
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_raises_on_error(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.side_effect = requests.HTTPError("500")
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {})
|
||||
with pytest.raises(requests.HTTPError):
|
||||
client.get("/fail")
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_strips_trailing_slash(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com/", {})
|
||||
client.get("/users")
|
||||
mock_req.assert_called_once_with(
|
||||
"GET",
|
||||
"https://api.example.com/users",
|
||||
headers={},
|
||||
timeout=30,
|
||||
verify=True,
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_kwargs_override_defaults(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {}, timeout=30)
|
||||
client.get("/slow", timeout=120)
|
||||
mock_req.assert_called_once_with(
|
||||
"GET",
|
||||
"https://api.example.com/slow",
|
||||
headers={},
|
||||
timeout=120,
|
||||
verify=True,
|
||||
)
|
||||
|
||||
@patch("devx.utils.api.requests.request")
|
||||
def test_no_auth_when_not_set(self, mock_req):
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.raise_for_status.return_value = None
|
||||
mock_req.return_value = mock_resp
|
||||
client = APIClient("https://api.example.com", {})
|
||||
client.get("/data")
|
||||
call_kwargs = mock_req.call_args.kwargs
|
||||
assert "auth" not in call_kwargs
|
||||
Reference in New Issue
Block a user