test(e2e): SSE initial-ping + heartbeat + log-frames regression guards (4 new)
This commit is contained in:
@@ -199,6 +199,56 @@ def test_sse_logs_streams_not_unsupported():
|
|||||||
assert "text/event-stream" in body.lower(), f"no SSE content-type: {body[:300]!r}"
|
assert "text/event-stream" in body.lower(), f"no SSE content-type: {body[:300]!r}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_sse_status_emits_initial_ping_within_1s():
|
||||||
|
"""Backend MUST emit ":ping" immediately after headers (regression guard).
|
||||||
|
|
||||||
|
Without this, agents_dashboard sat on "connecting" indefinitely because
|
||||||
|
fgets() blocked waiting for the first body byte.
|
||||||
|
"""
|
||||||
|
apikey = _apikey()
|
||||||
|
r = _curl([
|
||||||
|
"-sN", "-m", "2",
|
||||||
|
"-H", f"Authorization: Bearer {apikey}",
|
||||||
|
f"{_url()}/sse/status",
|
||||||
|
], timeout=5)
|
||||||
|
# Body should contain at minimum the ping comment within 2s window
|
||||||
|
assert ": ping" in r.stdout, f"no initial ping in 2s: {r.stdout[:300]!r}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_sse_logs_emits_initial_ping_within_1s():
|
||||||
|
apikey = _apikey()
|
||||||
|
r = _curl([
|
||||||
|
"-sN", "-m", "2",
|
||||||
|
"-H", f"Authorization: Bearer {apikey}",
|
||||||
|
f"{_url()}/sse/agents/assistant-bot/logs",
|
||||||
|
], timeout=5)
|
||||||
|
assert ": ping" in r.stdout, f"no initial ping in 2s: {r.stdout[:300]!r}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_sse_logs_actually_streams_log_lines():
|
||||||
|
"""Beyond the ping, the log SSE must emit `event: log` frames with data.
|
||||||
|
|
||||||
|
assistant-bot is a long-running agent that emits log lines frequently,
|
||||||
|
so we collect a 2s window and expect at least one log event.
|
||||||
|
"""
|
||||||
|
apikey = _apikey()
|
||||||
|
r = _curl([
|
||||||
|
"-sN", "-m", "2",
|
||||||
|
"-H", f"Authorization: Bearer {apikey}",
|
||||||
|
f"{_url()}/sse/agents/assistant-bot/logs",
|
||||||
|
], timeout=5)
|
||||||
|
assert "event: log" in r.stdout, f"no log events in 2s window: {r.stdout[:500]!r}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_sse_unauthorized_without_bearer():
|
||||||
|
"""SSE endpoints respect the same auth middleware as REST endpoints."""
|
||||||
|
r = _curl([
|
||||||
|
"-s", "-o", "/dev/null", "-w", "%{http_code}",
|
||||||
|
f"{_url()}/sse/status",
|
||||||
|
])
|
||||||
|
assert r.stdout == "401", f"expected 401 got {r.stdout!r}"
|
||||||
|
|
||||||
|
|
||||||
def test_health_no_auth_required():
|
def test_health_no_auth_required():
|
||||||
"""/health must respond 200 without any Authorization header."""
|
"""/health must respond 200 without any Authorization header."""
|
||||||
r = _curl(["-fsS", f"{_url()}/health"])
|
r = _curl(["-fsS", f"{_url()}/health"])
|
||||||
|
|||||||
Reference in New Issue
Block a user