"""Unit tests for api_client module.""" from unittest.mock import MagicMock, patch import pytest from gitea_runner_manager.api_client import GiteaAPIClient from gitea_runner_manager.exceptions import GiteaAPIError, RunnerNotFoundError class TestGiteaAPIClient: def test_init(self) -> None: client = GiteaAPIClient("https://git.example.com", "token123") assert client.base_url == "https://git.example.com" assert client.token == "token123" assert client.session.headers["Authorization"] == "token token123" def test_init_strips_trailing_slash(self) -> None: client = GiteaAPIClient("https://git.example.com/", "token123") assert client.base_url == "https://git.example.com" def test_from_env_success(self) -> None: with patch.dict("os.environ", {"GITEA_URL": "https://git.example.com", "GITEA_TOKEN": "tok"}): client = GiteaAPIClient.from_env() assert client.base_url == "https://git.example.com" assert client.token == "tok" def test_from_env_missing_url(self) -> None: with patch.dict("os.environ", {"GITEA_URL": "", "GITEA_TOKEN": "tok"}, clear=True): with pytest.raises(GiteaAPIError, match="GITEA_URL and GITEA_TOKEN must be set"): GiteaAPIClient.from_env() def test_from_env_missing_token(self) -> None: with patch.dict("os.environ", {"GITEA_URL": "https://git.example.com", "GITEA_TOKEN": ""}, clear=True): with pytest.raises(GiteaAPIError, match="GITEA_URL and GITEA_TOKEN must be set"): GiteaAPIClient.from_env() def test_request_success(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.status_code = 200 with patch.object(client.session, "request", return_value=mock_response) as mock_req: resp = client._request("GET", "/test") assert resp == mock_response mock_req.assert_called_once_with("GET", "https://git.example.com/api/v1/test", params=None, json=None) def test_request_failure(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = False mock_response.status_code = 404 mock_response.text = "Not Found" with patch.object(client.session, "request", return_value=mock_response): with pytest.raises(GiteaAPIError, match="404 Not Found") as exc_info: client._request("GET", "/test") assert exc_info.value.status_code == 404 def test_get_runners(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {"runners": [{"id": 1, "name": "r1"}]} with patch.object(client.session, "request", return_value=mock_response): runners = client.get_runners() assert runners == [{"id": 1, "name": "r1"}] def test_get_runners_empty(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {} with patch.object(client.session, "request", return_value=mock_response): runners = client.get_runners() assert runners == [] def test_create_registration_token(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {"token": "reg-token-123"} with patch.object(client.session, "request", return_value=mock_response): token = client.create_registration_token() assert token == "reg-token-123" def test_create_registration_token_no_token(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {} with patch.object(client.session, "request", return_value=mock_response): with pytest.raises(GiteaAPIError, match="No token in response"): client.create_registration_token() def test_wait_for_runner_success(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {"runners": [{"name": "runner1", "status": "online"}]} with patch.object(client.session, "request", return_value=mock_response): runner = client.wait_for_runner("runner1", timeout=5) assert runner["name"] == "runner1" def test_wait_for_runner_not_online(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {"runners": [{"name": "runner1", "status": "offline"}]} with patch.object(client.session, "request", return_value=mock_response): with pytest.raises(RunnerNotFoundError, match="is not online"): client.wait_for_runner("runner1", timeout=5) def test_wait_for_runner_timeout(self) -> None: client = GiteaAPIClient("https://git.example.com", "token") mock_response = MagicMock() mock_response.ok = True mock_response.json.return_value = {"runners": []} with patch.object(client.session, "request", return_value=mock_response): with pytest.raises(RunnerNotFoundError, match="did not appear within"): client.wait_for_runner("runner1", timeout=1, interval=1)