from __future__ import annotations from fastapi.testclient import TestClient from app.main import create_app from app.market.fake import FakeMarketData from app.runtime import Runtime def test_health_and_strategies(runtime: Runtime) -> None: app = create_app(runtime.settings, runtime) with TestClient(app) as client: assert client.get("/api/health").json() == {"status": "ok"} keys = {s["key"] for s in client.get("/api/strategies").json()} assert {"sma_cross", "rsi_reversion"} <= keys def test_start_status_stop_flow(runtime: Runtime) -> None: app = create_app(runtime.settings, runtime) with TestClient(app) as client: status = client.get("/api/status").json() assert status["running"] is False started = client.post( "/api/bot/start", json={"strategy_key": "sma_cross", "params": {"fast": 2, "slow": 4}}, ) assert started.status_code == 200 assert started.json()["running"] is True assert client.get("/api/positions").status_code == 200 assert client.get("/api/orders").status_code == 200 assert client.get("/api/events").status_code == 200 stopped = client.post("/api/bot/stop").json() assert stopped["running"] is False def test_unknown_strategy_returns_404(runtime: Runtime) -> None: app = create_app(runtime.settings, runtime) with TestClient(app) as client: response = client.post("/api/bot/start", json={"strategy_key": "does_not_exist"}) assert response.status_code == 404 def test_backtest_endpoint(runtime: Runtime, market: FakeMarketData) -> None: market.candles = FakeMarketData.sine_wave(200).candles app = create_app(runtime.settings, runtime) with TestClient(app) as client: response = client.post( "/api/backtest", json={"strategy_key": "sma_cross", "params": {"fast": 5, "slow": 20}, "limit": 200}, ) assert response.status_code == 200 data = response.json() assert data["strategy_key"] == "sma_cross" assert data["error"] is None assert len(data["equity_curve"]) == 200 assert "total_return_pct" in data["metrics"] assert data["metrics"]["num_trades"] >= 1 def test_backtest_unknown_strategy_404(runtime: Runtime) -> None: app = create_app(runtime.settings, runtime) with TestClient(app) as client: response = client.post("/api/backtest", json={"strategy_key": "nope"}) assert response.status_code == 404 def test_backtest_limit_validation(runtime: Runtime) -> None: app = create_app(runtime.settings, runtime) with TestClient(app) as client: assert ( client.post("/api/backtest", json={"strategy_key": "sma_cross", "limit": 5}).status_code == 422 ) def test_websocket_sends_initial_status(runtime: Runtime) -> None: app = create_app(runtime.settings, runtime) with TestClient(app) as client, client.websocket_connect("/api/ws") as websocket: message = websocket.receive_json() assert message["type"] == "status" assert message["data"]["running"] is False