"""Tests for economy survey routes.""" from unittest.mock import patch, AsyncMock import pytest from httpx import AsyncClient, ASGITransport from main import app @pytest.fixture async def client(): transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as c: yield c # --- Michigan Consumer Sentiment --- @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_michigan", new_callable=AsyncMock) async def test_survey_michigan_happy_path(mock_fn, client): mock_fn.return_value = [ {"date": "2026-03-01", "consumer_sentiment": 76.5, "inflation_expectation_1yr": 3.1} ] resp = await client.get("/api/v1/economy/surveys/michigan") assert resp.status_code == 200 data = resp.json() assert data["success"] is True assert data["data"][0]["consumer_sentiment"] == 76.5 @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_michigan", new_callable=AsyncMock) async def test_survey_michigan_empty(mock_fn, client): mock_fn.return_value = [] resp = await client.get("/api/v1/economy/surveys/michigan") assert resp.status_code == 200 assert resp.json()["data"] == [] @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_michigan", new_callable=AsyncMock) async def test_survey_michigan_service_error_returns_502(mock_fn, client): mock_fn.side_effect = RuntimeError("FRED unavailable") resp = await client.get("/api/v1/economy/surveys/michigan") assert resp.status_code == 502 # --- SLOOS --- @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_sloos", new_callable=AsyncMock) async def test_survey_sloos_happy_path(mock_fn, client): mock_fn.return_value = [ {"date": "2026-01-01", "c_i_tightening_pct": 25.0, "consumer_tightening_pct": 10.0} ] resp = await client.get("/api/v1/economy/surveys/sloos") assert resp.status_code == 200 data = resp.json() assert data["success"] is True assert data["data"][0]["c_i_tightening_pct"] == 25.0 @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_sloos", new_callable=AsyncMock) async def test_survey_sloos_empty(mock_fn, client): mock_fn.return_value = [] resp = await client.get("/api/v1/economy/surveys/sloos") assert resp.status_code == 200 assert resp.json()["data"] == [] @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_sloos", new_callable=AsyncMock) async def test_survey_sloos_service_error_returns_502(mock_fn, client): mock_fn.side_effect = RuntimeError("FRED down") resp = await client.get("/api/v1/economy/surveys/sloos") assert resp.status_code == 502 # --- Nonfarm Payrolls --- @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_nonfarm_payrolls", new_callable=AsyncMock) async def test_survey_nfp_happy_path(mock_fn, client): mock_fn.return_value = [ {"date": "2026-03-07", "value": 275000, "industry": "total_nonfarm"} ] resp = await client.get("/api/v1/economy/surveys/nonfarm-payrolls") assert resp.status_code == 200 data = resp.json() assert data["success"] is True assert data["data"][0]["value"] == 275000 @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_nonfarm_payrolls", new_callable=AsyncMock) async def test_survey_nfp_empty(mock_fn, client): mock_fn.return_value = [] resp = await client.get("/api/v1/economy/surveys/nonfarm-payrolls") assert resp.status_code == 200 assert resp.json()["data"] == [] @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_nonfarm_payrolls", new_callable=AsyncMock) async def test_survey_nfp_service_error_returns_502(mock_fn, client): mock_fn.side_effect = RuntimeError("BLS unavailable") resp = await client.get("/api/v1/economy/surveys/nonfarm-payrolls") assert resp.status_code == 502 # --- Empire State Manufacturing --- @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_empire_state", new_callable=AsyncMock) async def test_survey_empire_state_happy_path(mock_fn, client): mock_fn.return_value = [ {"date": "2026-03-01", "general_business_conditions": -7.58} ] resp = await client.get("/api/v1/economy/surveys/empire-state") assert resp.status_code == 200 data = resp.json() assert data["success"] is True assert data["data"][0]["general_business_conditions"] == -7.58 @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_empire_state", new_callable=AsyncMock) async def test_survey_empire_state_empty(mock_fn, client): mock_fn.return_value = [] resp = await client.get("/api/v1/economy/surveys/empire-state") assert resp.status_code == 200 assert resp.json()["data"] == [] @pytest.mark.asyncio @patch("routes_surveys.surveys_service.get_empire_state", new_callable=AsyncMock) async def test_survey_empire_state_service_error_returns_502(mock_fn, client): mock_fn.side_effect = RuntimeError("FRED connection error") resp = await client.get("/api/v1/economy/surveys/empire-state") assert resp.status_code == 502 # --- BLS Search --- @pytest.mark.asyncio @patch("routes_surveys.surveys_service.bls_search", new_callable=AsyncMock) async def test_survey_bls_search_happy_path(mock_fn, client): mock_fn.return_value = [ {"series_id": "CES0000000001", "series_title": "All employees, thousands, total nonfarm"}, {"series_id": "CES1000000001", "series_title": "All employees, thousands, mining and logging"}, ] resp = await client.get("/api/v1/economy/surveys/bls-search?query=nonfarm+payrolls") assert resp.status_code == 200 data = resp.json() assert data["success"] is True assert len(data["data"]) == 2 assert data["data"][0]["series_id"] == "CES0000000001" mock_fn.assert_called_once_with(query="nonfarm payrolls") @pytest.mark.asyncio async def test_survey_bls_search_missing_query(client): resp = await client.get("/api/v1/economy/surveys/bls-search") assert resp.status_code == 422 @pytest.mark.asyncio @patch("routes_surveys.surveys_service.bls_search", new_callable=AsyncMock) async def test_survey_bls_search_empty(mock_fn, client): mock_fn.return_value = [] resp = await client.get("/api/v1/economy/surveys/bls-search?query=nothingtofind") assert resp.status_code == 200 assert resp.json()["data"] == [] @pytest.mark.asyncio @patch("routes_surveys.surveys_service.bls_search", new_callable=AsyncMock) async def test_survey_bls_search_service_error_returns_502(mock_fn, client): mock_fn.side_effect = RuntimeError("BLS API down") resp = await client.get("/api/v1/economy/surveys/bls-search?query=wages") assert resp.status_code == 502