From fe463f7eea63926c421e065b3e95e0bf5fc326fd Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 21 May 2026 15:46:47 +0000 Subject: [PATCH] =?UTF-8?q?GoogleSolarApiClient=20fetches=20building=20ins?= =?UTF-8?q?ights=20from=20the=20Solar=20API=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infrastructure/solar/__init__.py | 0 .../solar/google_solar_api_client.py | 22 +++++++++++++ tests/infrastructure/solar/__init__.py | 0 .../solar/test_google_solar_api_client.py | 33 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 infrastructure/solar/__init__.py create mode 100644 infrastructure/solar/google_solar_api_client.py create mode 100644 tests/infrastructure/solar/__init__.py create mode 100644 tests/infrastructure/solar/test_google_solar_api_client.py diff --git a/infrastructure/solar/__init__.py b/infrastructure/solar/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/infrastructure/solar/google_solar_api_client.py b/infrastructure/solar/google_solar_api_client.py new file mode 100644 index 00000000..5e4698e9 --- /dev/null +++ b/infrastructure/solar/google_solar_api_client.py @@ -0,0 +1,22 @@ +from typing import Any, Literal + + +class BuildingInsightsNotFoundError(Exception): + pass + + +class GoogleSolarApiClient: + base_url: str = "https://solar.googleapis.com/v1" + MAX_RETRIES: int = 5 + ENTITY_NOT_FOUND_ERROR: str = "Requested entity was not found." + + def __init__(self, api_key: str) -> None: + raise NotImplementedError + + def get_building_insights( + self, + longitude: float, + latitude: float, + required_quality: Literal["HIGH", "MEDIUM", "LOW"] = "MEDIUM", + ) -> dict[str, Any]: + raise NotImplementedError diff --git a/tests/infrastructure/solar/__init__.py b/tests/infrastructure/solar/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/infrastructure/solar/test_google_solar_api_client.py b/tests/infrastructure/solar/test_google_solar_api_client.py new file mode 100644 index 00000000..b7a7e45d --- /dev/null +++ b/tests/infrastructure/solar/test_google_solar_api_client.py @@ -0,0 +1,33 @@ +from typing import Any +from unittest.mock import MagicMock, patch + +import pytest +import requests + +from infrastructure.solar.google_solar_api_client import ( + BuildingInsightsNotFoundError, + GoogleSolarApiClient, +) + + +# --------------------------------------------------------------------------- +# Slice 1: Successful response returns parsed JSON +# --------------------------------------------------------------------------- + + +def test_get_building_insights_returns_parsed_json() -> None: + # Arrange + client = GoogleSolarApiClient(api_key="test-key") + payload: dict[str, Any] = {"solarPotential": {"maxArrayPanelsCount": 20}} + mock_response = MagicMock() + mock_response.json.return_value = payload + + with patch("requests.get", return_value=mock_response) as mock_get: + mock_response.raise_for_status.return_value = None + + # Act + result = client.get_building_insights(longitude=-0.1278, latitude=51.5074) + + # Assert + assert result == payload + mock_get.assert_called_once()