import json
from http.client import HTTPConnection
from http.server import ThreadingHTTPServer
from threading import Thread
from tests.conftest import app_config
from worker_watcher.api import create_handler
from worker_watcher.reports import render_json, render_markdown
from worker_watcher.watcher import Watcher
def test_api_health_and_reports(tmp_path) -> None:
watcher = Watcher(app_config(tmp_path / "api.sqlite"), tmp_path)
watcher.run_once()
assert "jobs_total" in watcher.health()
assert "failed" in render_markdown(watcher)
assert json.loads(render_json(watcher))["watcher"]
server = ThreadingHTTPServer(("127.0.0.1", 0), create_handler(watcher))
thread = Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
connection = HTTPConnection("127.0.0.1", server.server_port, timeout=3)
connection.request("GET", "/health/live")
response = connection.getresponse()
assert response.status == 200
assert json.loads(response.read())["status"] == "live"
connection.request("GET", "/")
html = connection.getresponse().read().decode()
for label in ("Letzte Aktivität", "Seit", "Betriebszustand", "Gesundheit", "Beobachtung", "Nächster Lauf / Überfällig", "Zuletzt aktualisiert", "Letzte Watcher-Prüfung", "Wird aktualisiert"):
assert label in html
for element_id in ("refresh", "refresh-spinner", "refresh-label", "last-updated", "last-watcher-cycle", "refresh-message"):
assert f'id="{element_id}"' in html
assert "aria-sort" in html
assert "data-sort-target" in html
connection.request("GET", "/api/v1/jobs/999999")
assert connection.getresponse().status == 404
agent_payload = {"agent_key": "agent.api.test", "agent_name": "API test", "agent_version": "0.1",
"environment": "local", "host": "test-host", "runtime": "python", "capabilities": ["heartbeat"]}
body = json.dumps(agent_payload).encode()
connection.request("POST", "/api/v1/agents/register", body=body, headers={"Content-Type": "application/json"})
assert connection.getresponse().status == 201
event = {"event_id": "api-event-1", "agent": agent_payload, "worker_key": "worker.api.test",
"job_key": "api.test.worker", "event_type": "heartbeat", "occurred_at": "2026-08-01T12:00:00Z",
"payload": {"display_name": "API worker", "stale_after_seconds": 60}}
body = json.dumps(event).encode()
connection.request("POST", "/api/v1/agents/events", body=body, headers={"Content-Type": "application/json"})
assert connection.getresponse().status == 200
connection.request("GET", "/api/v1/workers")
assert json.loads(connection.getresponse().read())["items"][0]["worker_key"] == "worker.api.test"
connection.request("GET", "/api/v1/collectors")
collectors = json.loads(connection.getresponse().read())
assert collectors["items"][0]["name"] == "generic_worker"
connection.request("GET", "/api/v1/collectors/runs")
runs = json.loads(connection.getresponse().read())
assert runs["items"][0]["collector_name"] == "generic-worker"
connection.request("GET", "/api/v1/collectors/generic_worker")
assert json.loads(connection.getresponse().read())["type"] == "generic_worker"
connection.request("GET", "/api/v1/alerts/summary")
summary = json.loads(connection.getresponse().read())
assert summary["overall_status"] == "healthy"
assert summary["active_alerts"] == 0
assert summary["oldest_problem"] is None
assert "generated_at" in summary
finally:
server.shutdown()
server.server_close()
watcher.close()