"""Tests for MacroClient.""" from __future__ import annotations from datetime import UTC, datetime, timedelta import pytest from pytest_httpx import HTTPXMock from cerbero_bite.clients._base import HttpToolClient from cerbero_bite.clients.macro import MacroClient def _client() -> MacroClient: http = HttpToolClient( service="macro", base_url="http://mcp-macro:9013", token="t", retry_max=1, ) return MacroClient(http) @pytest.mark.asyncio async def test_get_calendar_parses_events(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( url="http://mcp-macro:9013/tools/get_macro_calendar", json={ "events": [ { "name": "FOMC Meeting", "country_code": "US", "importance": "high", "datetime_utc": "2026-05-05T18:00:00+00:00", }, { "event": "ECB rate decision", "country_code": "EU", "importance": "high", "datetime_utc": "2026-05-08T12:00:00Z", }, ] }, ) events = await _client().get_calendar(days=18) assert [e.name for e in events] == ["FOMC Meeting", "ECB rate decision"] assert events[0].country_code == "US" assert events[0].importance == "high" assert events[0].datetime_utc == datetime(2026, 5, 5, 18, 0, tzinfo=UTC) @pytest.mark.asyncio async def test_get_calendar_skips_non_dict_entries(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(json={"events": ["not-a-dict", None]}) assert await _client().get_calendar(days=18) == [] @pytest.mark.asyncio async def test_next_high_severity_returns_min_days(httpx_mock: HTTPXMock) -> None: now = datetime(2026, 4, 27, 14, 0, tzinfo=UTC) httpx_mock.add_response( json={ "events": [ { "name": "FOMC", "country_code": "US", "importance": "high", "datetime_utc": (now + timedelta(days=10, hours=4)).isoformat(), }, { "name": "ECB", "country_code": "EU", "importance": "high", "datetime_utc": (now + timedelta(days=3, hours=1)).isoformat(), }, ] } ) days = await _client().next_high_severity_within( days=18, countries=["US", "EU"], now=now ) assert days == 3 @pytest.mark.asyncio async def test_next_high_severity_ignores_past_events(httpx_mock: HTTPXMock) -> None: now = datetime(2026, 4, 27, 14, 0, tzinfo=UTC) httpx_mock.add_response( json={ "events": [ { "name": "stale", "country_code": "US", "importance": "high", "datetime_utc": (now - timedelta(days=2)).isoformat(), }, ] } ) assert ( await _client().next_high_severity_within(days=18, countries=None, now=now) is None ) @pytest.mark.asyncio async def test_next_high_severity_no_events_returns_none( httpx_mock: HTTPXMock, ) -> None: httpx_mock.add_response(json={"events": []}) out = await _client().next_high_severity_within( days=18, countries=["US"], now=datetime(2026, 4, 27, 14, 0, tzinfo=UTC) ) assert out is None @pytest.mark.asyncio async def test_get_calendar_passes_filters(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(json={"events": []}) await _client().get_calendar( days=18, country_filter=["US", "EU"], importance_min="high" ) request = httpx_mock.get_request() assert request is not None body = request.read().decode() assert '"days":18' in body assert '"country_filter":["US","EU"]' in body assert '"importance_min":"high"' in body def test_macro_client_rejects_wrong_service() -> None: bad = HttpToolClient( service="deribit", base_url="http://x:1", token="t", retry_max=1, ) with pytest.raises(ValueError, match="requires service 'macro'"): MacroClient(bad)