import pytest import sys import os from unittest.mock import patch sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) from src.api_hook_client import ApiHookClient def test_get_warmup_status_calls_correct_endpoint() -> None: """get_warmup_status() hits GET /api/warmup_status.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = {"pending": [], "completed": ["a", "b"], "failed": []} result = client.get_warmup_status() assert "pending" in result assert "completed" in result assert "failed" in result mock_make.assert_called_once_with("GET", "/api/warmup_status") def test_get_warmup_status_handles_empty_response() -> None: """get_warmup_status() returns empty dict when server returns None/empty.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = None result = client.get_warmup_status() assert result == {} def test_get_warmup_wait_passes_timeout_as_query_string() -> None: """get_warmup_wait(timeout=N) hits GET /api/warmup_wait?timeout=N.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = {"pending": [], "completed": ["x"], "failed": []} result = client.get_warmup_wait(timeout=12.5) assert "completed" in result mock_make.assert_called_once_with("GET", "/api/warmup_wait?timeout=12.5") def test_get_warmup_wait_uses_default_timeout_when_unspecified() -> None: """get_warmup_wait() with no args uses the default timeout=30.0.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = {"pending": [], "completed": [], "failed": []} client.get_warmup_wait() args, _ = mock_make.call_args assert args[0] == "GET" assert args[1].startswith("/api/warmup_wait?timeout=") assert "30" in args[1] def test_get_warmup_wait_handles_empty_response() -> None: """get_warmup_wait() returns empty dict when server returns None.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = None result = client.get_warmup_wait(timeout=5.0) assert result == {} def test_live_warmup_status_endpoint(live_gui) -> None: """Live: GET /api/warmup_status returns 200 + warmup dict (sub-track 3).""" client = ApiHookClient() assert client.wait_for_server(timeout=10) status = client.get_warmup_status() assert "pending" in status assert "completed" in status assert "failed" in status assert isinstance(status["pending"], list) assert isinstance(status["completed"], list) assert isinstance(status["failed"], list) def test_live_warmup_wait_endpoint_completes(live_gui) -> None: """Live: GET /api/warmup_wait?timeout=2.0 returns the (likely-completed) status.""" client = ApiHookClient() assert client.wait_for_server(timeout=10) result = client.get_warmup_wait(timeout=2.0) assert "pending" in result assert "completed" in result assert "failed" in result # In a live session the warmup either already finished (no pending) or # completed within the 2s window. Either way the response is well-formed. assert isinstance(result["pending"], list) def test_get_warmup_canaries_calls_correct_endpoint() -> None: """get_warmup_canaries() hits GET /api/warmup_canaries and unwraps the list.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = {"canaries": [{"canary_id": 1, "module": "os", "thread_name": "controller-io-0", "thread_id": 12345, "status": "completed"}]} result = client.get_warmup_canaries() assert isinstance(result, list) assert len(result) == 1 assert result[0]["module"] == "os" assert result[0]["status"] == "completed" mock_make.assert_called_once_with("GET", "/api/warmup_canaries") def test_get_warmup_canaries_handles_empty_response() -> None: """get_warmup_canaries() returns [] when server returns None or empty payload.""" client = ApiHookClient() with patch.object(client, "_make_request") as mock_make: mock_make.return_value = None result = client.get_warmup_canaries() assert result == [] def test_live_warmup_canaries_endpoint(live_gui) -> None: """Live: GET /api/warmup_canaries returns canary records with thread + status info.""" client = ApiHookClient() assert client.wait_for_server(timeout=10) canaries = client.get_warmup_canaries() assert isinstance(canaries, list) assert len(canaries) >= 1, "expected at least one canary record from live warmup" for c in canaries: assert "canary_id" in c assert "module" in c assert "thread_name" in c assert "thread_id" in c assert "status" in c assert c["status"] in ("running", "completed", "failed", "cancelled") completed = [c for c in canaries if c["status"] == "completed"] assert len(completed) >= 1, "at least one canary should be completed"