"""Worker task tests (S5-T10).""" from unittest.mock import AsyncMock, MagicMock, patch from remodel_api.db.models import Scenario from remodel_api.workers.tasks import run_scenario_task def _make_session_mock(scenario: Scenario | None) -> tuple[AsyncMock, MagicMock]: session_mock = AsyncMock() session_mock.__aenter__ = AsyncMock(return_value=session_mock) session_mock.__aexit__ = AsyncMock(return_value=False) session_mock.get = AsyncMock(return_value=scenario) session_mock.commit = AsyncMock() factory_mock = MagicMock() factory_mock.return_value = session_mock return session_mock, factory_mock async def test_run_scenario_task_not_found() -> None: mock_redis = AsyncMock() mock_redis.publish = AsyncMock() mock_redis.aclose = AsyncMock() _, factory_mock = _make_session_mock(None) with ( patch("remodel_api.workers.tasks.aioredis.from_url", return_value=mock_redis), patch("remodel_api.workers.tasks.AsyncSessionLocal", factory_mock), ): result = await run_scenario_task({}, "missing-id") assert "error" in result async def test_run_scenario_task_with_engine() -> None: """Worker runs the engine and persists KPIs.""" mock_redis = AsyncMock() mock_redis.publish = AsyncMock() mock_redis.aclose = AsyncMock() scenario = Scenario( id="test-id", name="test", status="queued", inputs_json=( '{"solar": {"location_id": "RJ", "capacity_dc_mwp": 10.0, "capacity_ac_mw": 8.0}}' ), ) _, factory_mock = _make_session_mock(scenario) engine_output = { "status": "success", "kpis": {"equity_irr": 0.15}, "statements": {"pnl": [], "cfs": [], "bs": []}, "debt_schedule": [], "irr_metrics": {}, "runtime_s": 1.0, "warnings": [], } with ( patch("remodel_api.workers.tasks.aioredis.from_url", return_value=mock_redis), patch("remodel_api.workers.tasks.AsyncSessionLocal", factory_mock), patch("remodel_api.workers.tasks._run_engine", return_value=engine_output), ): result = await run_scenario_task({}, "test-id") assert result.get("status") == "success" assert mock_redis.publish.called