"""Phase 2: SSE-Plumbing für den Compliance-Check. Deckt emit (Queue-Push), _format_sse (SSE-Zeilenformat) und den event_generator (hello → Events → stream_close bei 'complete') ab. """ from __future__ import annotations import asyncio from compliance.api.agent_check import _sse def test_emit_pushes_and_format(): cid = "sse-test-1" _sse.new_queue(cid) _sse.emit(cid, {"type": "topic", "topic": "impressum", "output": {"x": 1}}) q = _sse._check_queues[cid] assert q.qsize() == 1 ev = q.get_nowait() assert ev["type"] == "topic" and ev["topic"] == "impressum" line = _sse._format_sse(ev) assert line.startswith("data: ") and line.endswith("\n\n") assert '"impressum"' in line def test_emit_is_noop_without_queue(): # Kein new_queue → emit darf nicht crashen (best-effort). _sse.emit("does-not-exist-xyz", {"type": "topic"}) def test_event_generator_streams_topic_then_closes_on_complete(): cid = "sse-test-gen" _sse.new_queue(cid) _sse.emit(cid, {"type": "topic", "topic": "impressum", "output": {}}) _sse.emit(cid, {"type": "complete", "status": "completed"}) async def collect(): out = [] async for line in _sse.event_generator(cid): out.append(line) if len(out) > 12: # safety break return out blob = "".join(asyncio.run(collect())) assert '"type": "hello"' in blob assert '"topic": "impressum"' in blob assert '"type": "complete"' in blob assert '"type": "stream_close"' in blob