Private
Public Access
0
0

feat(api_hooks): add /api/warmup_status and /api/warmup_wait endpoints (sub-track 3)

Sub-track 3 of startup_speedup_20260606. Builds on the Phase 7 minimal
work at b464d1fe which only added warmup_status to /api/gui/diagnostics.

New dedicated endpoints:
- GET /api/warmup_status -> controller.warmup_status() (cheap, lock-guarded)
- GET /api/warmup_wait?timeout=N -> controller.wait_for_warmup(timeout)
  then returns the final status. Default 30s.

Both callable from external clients via ApiHookClient.get_warmup_status()
and ApiHookClient.get_warmup_wait(timeout=30.0).

7 new tests in tests/test_api_hooks_warmup.py (5 unit + 2 live_gui).
All 7 pass.
This commit is contained in:
2026-06-06 21:01:56 -04:00
parent 0f74705d01
commit 8fea8fe9a0
3 changed files with 146 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
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)