diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/utils/test_sharepoint_client_error_handling.py b/tests/utils/test_sharepoint_client_error_handling.py new file mode 100644 index 000000000..aa52d4bd7 --- /dev/null +++ b/tests/utils/test_sharepoint_client_error_handling.py @@ -0,0 +1,58 @@ +import logging +from typing import Any, Optional + +import pytest + +from utils.sharepoint.sharepoint_client import ( + ResourceNotFoundError, + api_call_decorator, +) + + +class _FakeResponse: + def __init__(self, status_code: int, error_code: str, message: str) -> None: + self.status_code = status_code + self._error_code = error_code + self._message = message + self.headers: dict[str, str] = {} + + def json(self) -> dict[str, Any]: + return {"error": {"code": self._error_code, "message": self._message}} + + +class _FakeClient: + headers: Optional[dict[str, str]] = {} + + def is_access_token_expired(self) -> bool: + return False + + @api_call_decorator + def fetch(self, path: str) -> Any: + return "GET", f"https://graph.example.invalid/root:/{path}:/children", None + + +def _patch_response( + monkeypatch: pytest.MonkeyPatch, response: _FakeResponse +) -> None: + monkeypatch.setattr( + "utils.sharepoint.sharepoint_client.requests.request", + lambda *args, **kwargs: response, + ) + + +def test_404_raises_resource_not_found_without_error_logs( + monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture +) -> None: + # Arrange + _patch_response( + monkeypatch, + _FakeResponse(404, "itemNotFound", "The resource could not be found."), + ) + + # Act + with pytest.raises(ResourceNotFoundError): + _FakeClient().fetch("missing/folder") + + # Assert + error_records = [r for r in caplog.records if r.levelno >= logging.ERROR] + assert error_records == [] diff --git a/utils/sharepoint/sharepoint_client.py b/utils/sharepoint/sharepoint_client.py index 38107dbfc..976b47831 100644 --- a/utils/sharepoint/sharepoint_client.py +++ b/utils/sharepoint/sharepoint_client.py @@ -21,6 +21,10 @@ from utils.logger import setup_logger logger = setup_logger() +class ResourceNotFoundError(ValueError): + """Raised when the API returns 404 — an expected miss, not a failure.""" + + def handle_error(response): """ Handle errors based on HTTP status codes and log detailed information.