from typing import Any from unittest.mock import MagicMock, patch import pytest from pydantic import ValidationError from applications.magic_plan.handler import handler ADDRESS = "2 Laburnum Way Bromley BR2 8BZ" PLAN_UID = "a7285ed1-878d-47eb-8aa6-85ef9e187516" _ENV = {"MAGICPLAN_CUSTOMER_ID": "cust-123", "MAGICPLAN_API_KEY": "key-abc"} def _call_handler(body: dict[str, Any]) -> Any: return handler.__wrapped__(body, None) # type: ignore[attr-defined] @pytest.fixture() def mock_plan() -> MagicMock: plan = MagicMock() plan.uid = PLAN_UID return plan @pytest.fixture() def mock_orchestrator(mock_plan: MagicMock) -> MagicMock: orchestrator = MagicMock() orchestrator.run.return_value = mock_plan return orchestrator # --- request validation --- def test_handler_raises_on_missing_address(mock_plan: MagicMock) -> None: body: dict[str, Any] = {} with patch("applications.magic_plan.handler.os.environ", _ENV), \ patch("applications.magic_plan.handler.MagicPlanClient"), \ patch("applications.magic_plan.handler.MagicPlanOrchestrator"): with pytest.raises(ValidationError): _call_handler(body) # --- client construction --- def test_handler_constructs_client_from_env(mock_orchestrator: MagicMock) -> None: body = {"address": ADDRESS, "hubspot_deal_id": "deal-123"} env = {"MAGICPLAN_CUSTOMER_ID": "cust-xyz", "MAGICPLAN_API_KEY": "key-xyz"} with patch("applications.magic_plan.handler.os.environ", env), \ patch("applications.magic_plan.handler.MagicPlanClient") as MockClient, \ patch("applications.magic_plan.handler.MagicPlanOrchestrator", return_value=mock_orchestrator): _call_handler(body) MockClient.assert_called_once_with(customer_id="cust-xyz", api_key="key-xyz") # --- orchestrator orchestration --- def test_handler_calls_orchestrator_run_with_address(mock_orchestrator: MagicMock) -> None: body = {"address": ADDRESS, "hubspot_deal_id": "deal-123"} with patch("applications.magic_plan.handler.os.environ", _ENV), \ patch("applications.magic_plan.handler.MagicPlanClient"), \ patch("applications.magic_plan.handler.MagicPlanOrchestrator", return_value=mock_orchestrator): _call_handler(body) mock_orchestrator.run.assert_called_once() request = mock_orchestrator.run.call_args.args[0] assert request.address == ADDRESS assert request.uprn is None def test_handler_passes_uprn_to_orchestrator(mock_orchestrator: MagicMock) -> None: body = {"address": ADDRESS, "uprn": "100023336956", "hubspot_deal_id": "deal-123"} with patch("applications.magic_plan.handler.os.environ", _ENV), \ patch("applications.magic_plan.handler.MagicPlanClient"), \ patch("applications.magic_plan.handler.MagicPlanOrchestrator", return_value=mock_orchestrator): _call_handler(body) mock_orchestrator.run.assert_called_once() request = mock_orchestrator.run.call_args.args[0] assert request.address == ADDRESS assert request.uprn == "100023336956" def test_handler_returns_plan_uid(mock_orchestrator: MagicMock) -> None: body = {"address": ADDRESS, "hubspot_deal_id": "deal-123"} with patch("applications.magic_plan.handler.os.environ", _ENV), \ patch("applications.magic_plan.handler.MagicPlanClient"), \ patch("applications.magic_plan.handler.MagicPlanOrchestrator", return_value=mock_orchestrator): result = _call_handler(body) assert result == PLAN_UID