Files
AdrianoDev 9da2e12473
ci / ruff lint (push) Successful in 15s
ci / validate compose + Caddyfile (push) Successful in 2m6s
ci / mypy mcp_common (push) Successful in 30s
ci / pytest (push) Successful in 34s
ci / build & push to registry (push) Failing after 47s
lint: ruff clean services/ (autofix + manual + ignore E741)
- 24 autofix safe (SIM105 contextlib.suppress, F401 unused imports,
  I001 import order, B007 unused loop var, F811 redef, F841 unused).
- 15 unsafe-fix (UP038 X|Y in isinstance, SIM108 ternary, ecc.).
- Manual fix: SIM102 nested if in deribit term_structure, E402 imports
  in test_cot.py + sentiment server.py.
- Ignore E741 (variabili 'l' in list comprehensions deribit/client.py
  — stilistico, non bug).

Tests: 478/478 verdi.
2026-04-29 08:44:12 +02:00

203 lines
5.4 KiB
Python

from __future__ import annotations
from unittest.mock import AsyncMock, patch
import pytest
from fastapi.testclient import TestClient
from mcp_common.auth import Principal, TokenStore
from mcp_macro.server import create_app
@pytest.fixture
def http():
store = TokenStore(
tokens={
"ct": Principal("core", {"core"}),
"ot": Principal("observer", {"observer"}),
}
)
app = create_app(fred_api_key="testfred", finnhub_api_key="testfinn", token_store=store)
return TestClient(app)
# --- Health ---
def test_health(http):
assert http.get("/health").status_code == 200
# --- get_economic_indicators ---
def test_get_economic_indicators_core_ok(http):
with patch(
"mcp_macro.server.fetch_economic_indicators",
new=AsyncMock(return_value={"fed_rate": 5.25, "updated_at": "2024-01-01T00:00:00+00:00"}),
):
r = http.post(
"/tools/get_economic_indicators",
headers={"Authorization": "Bearer ct"},
json={},
)
assert r.status_code == 200
assert r.json()["fed_rate"] == 5.25
def test_get_economic_indicators_observer_ok(http):
with patch(
"mcp_macro.server.fetch_economic_indicators",
new=AsyncMock(return_value={"fed_rate": 5.25}),
):
r = http.post(
"/tools/get_economic_indicators",
headers={"Authorization": "Bearer ot"},
json={},
)
assert r.status_code == 200
def test_get_economic_indicators_no_auth_401(http):
r = http.post("/tools/get_economic_indicators", json={})
assert r.status_code == 401
# --- get_macro_calendar ---
def test_get_macro_calendar_core_ok(http):
with patch(
"mcp_macro.server.fetch_macro_calendar",
new=AsyncMock(return_value={"events": []}),
):
r = http.post(
"/tools/get_macro_calendar",
headers={"Authorization": "Bearer ct"},
json={"days": 7},
)
assert r.status_code == 200
def test_get_macro_calendar_observer_ok(http):
with patch(
"mcp_macro.server.fetch_macro_calendar",
new=AsyncMock(return_value={"events": []}),
):
r = http.post(
"/tools/get_macro_calendar",
headers={"Authorization": "Bearer ot"},
json={},
)
assert r.status_code == 200
def test_get_macro_calendar_no_auth_401(http):
r = http.post("/tools/get_macro_calendar", json={})
assert r.status_code == 401
# --- get_market_overview ---
def test_get_market_overview_core_ok(http):
with patch(
"mcp_macro.server.fetch_market_overview",
new=AsyncMock(return_value={"btc_dominance": 52.0, "btc_price": 65000}),
):
r = http.post(
"/tools/get_market_overview",
headers={"Authorization": "Bearer ct"},
json={},
)
assert r.status_code == 200
assert r.json()["btc_price"] == 65000
def test_get_market_overview_observer_ok(http):
with patch(
"mcp_macro.server.fetch_market_overview",
new=AsyncMock(return_value={"btc_dominance": 52.0}),
):
r = http.post(
"/tools/get_market_overview",
headers={"Authorization": "Bearer ot"},
json={},
)
assert r.status_code == 200
def test_get_market_overview_no_auth_401(http):
r = http.post("/tools/get_market_overview", json={})
assert r.status_code == 401
def test_get_cot_tff_core_ok(http):
with patch(
"mcp_macro.server.fetch_cot_tff",
new=AsyncMock(return_value={"symbol": "ES", "rows": []}),
):
r = http.post(
"/tools/get_cot_tff",
headers={"Authorization": "Bearer ct"},
json={"symbol": "ES"},
)
assert r.status_code == 200
assert r.json()["symbol"] == "ES"
def test_get_cot_tff_observer_ok(http):
with patch(
"mcp_macro.server.fetch_cot_tff",
new=AsyncMock(return_value={"symbol": "ES", "rows": []}),
):
r = http.post(
"/tools/get_cot_tff",
headers={"Authorization": "Bearer ot"},
json={"symbol": "ES"},
)
assert r.status_code == 200
def test_get_cot_tff_no_auth_401(http):
r = http.post("/tools/get_cot_tff", json={"symbol": "ES"})
assert r.status_code == 401
def test_get_cot_disagg_observer_ok(http):
with patch(
"mcp_macro.server.fetch_cot_disaggregated",
new=AsyncMock(return_value={"symbol": "CL", "rows": []}),
):
r = http.post(
"/tools/get_cot_disaggregated",
headers={"Authorization": "Bearer ot"},
json={"symbol": "CL"},
)
assert r.status_code == 200
def test_get_cot_disagg_no_auth_401(http):
r = http.post("/tools/get_cot_disaggregated", json={"symbol": "CL"})
assert r.status_code == 401
def test_get_cot_extreme_positioning_ok(http):
with patch(
"mcp_macro.server.fetch_cot_extreme_positioning",
new=AsyncMock(return_value={"extremes": []}),
):
r = http.post(
"/tools/get_cot_extreme_positioning",
headers={"Authorization": "Bearer ot"},
json={},
)
assert r.status_code == 200
def test_get_cot_extreme_positioning_lookback_too_short(http):
"""Pydantic validation: lookback_weeks < 4 → 422."""
r = http.post(
"/tools/get_cot_extreme_positioning",
headers={"Authorization": "Bearer ct"},
json={"lookback_weeks": 2},
)
assert r.status_code == 422