"""End-to-end test for ``cerbero-bite ping``. The CLI uses the production code paths, so we set up an HTTP mock that matches every URL Bite is going to hit and assert the rendered output contains the expected statuses. """ from __future__ import annotations from pathlib import Path from click.testing import CliRunner from pytest_httpx import HTTPXMock from cerbero_bite.cli import main as cli_main def _seed_token(tmp_path: Path) -> Path: target = tmp_path / "core_token" target.write_text("super-secret\n", encoding="utf-8") return target def test_ping_reports_each_service( tmp_path: Path, httpx_mock: HTTPXMock ) -> None: token_file = _seed_token(tmp_path) httpx_mock.add_response( url="http://mcp-deribit:9011/tools/environment_info", json={ "exchange": "deribit", "environment": "testnet", "source": "env", "env_value": "true", "base_url": "https://test.deribit.com/api/v2", "max_leverage": 3, }, ) httpx_mock.add_response( url="http://mcp-hyperliquid:9012/tools/get_funding_rate", json={"asset": "ETH", "current_funding_rate": 0.0001}, ) httpx_mock.add_response( url="http://mcp-macro:9013/tools/get_macro_calendar", json={"events": []}, ) httpx_mock.add_response( url="http://mcp-sentiment:9014/tools/get_cross_exchange_funding", json={"snapshot": {"ETH": {"binance": 0.0001}}}, ) httpx_mock.add_response( url="http://mcp-portfolio:9018/tools/get_total_portfolio_value", json={"total_value_eur": 5000.0}, ) result = CliRunner().invoke( cli_main, ["ping", "--token-file", str(token_file), "--timeout", "1.0"] ) assert result.exit_code == 0, result.output assert "deribit" in result.output assert "hyperliquid" in result.output assert "macro" in result.output assert "sentiment" in result.output assert "portfolio" in result.output assert "telegram" in result.output # listed even if skipped # at least 5 OK statuses assert result.output.count("OK") >= 5 def test_ping_reports_failure_when_service_unreachable( tmp_path: Path, httpx_mock: HTTPXMock ) -> None: token_file = _seed_token(tmp_path) httpx_mock.add_response( url="http://mcp-deribit:9011/tools/environment_info", status_code=500, text="boom", ) # Provide successful stubs for the others to keep the call small. httpx_mock.add_response( url="http://mcp-hyperliquid:9012/tools/get_funding_rate", json={"asset": "ETH", "current_funding_rate": 0.0001}, ) httpx_mock.add_response( url="http://mcp-macro:9013/tools/get_macro_calendar", json={"events": []}, ) httpx_mock.add_response( url="http://mcp-sentiment:9014/tools/get_cross_exchange_funding", json={"snapshot": {"ETH": {"binance": 0.0001}}}, ) httpx_mock.add_response( url="http://mcp-portfolio:9018/tools/get_total_portfolio_value", json={"total_value_eur": 0.0}, ) result = CliRunner().invoke( cli_main, ["ping", "--token-file", str(token_file), "--timeout", "1.0"] ) assert result.exit_code == 0 assert "FAIL" in result.output def test_ping_token_missing_exits_nonzero(tmp_path: Path) -> None: result = CliRunner().invoke( cli_main, ["ping", "--token-file", str(tmp_path / "nope")] ) assert result.exit_code == 1 assert "token error" in result.output