"""Smoke-Tests für die neuen API-Endpoints. Diese Tests prüfen nur ob die Endpoints antworten und das richtige Format zurückgeben — keine echten LLM-Calls oder DB-Writes. """ import pytest # Skip wenn die App nicht importierbar ist (missing dependencies lokal) try: from fastapi.testclient import TestClient from app.main import app client = TestClient(app) _HAS_APP = True except ImportError: _HAS_APP = False client = None pytestmark = pytest.mark.skipif(not _HAS_APP, reason="app.main not importable") class TestQueueStatus: def test_returns_json(self): resp = client.get("/api/queue/status") assert resp.status_code == 200 data = resp.json() assert "pending" in data assert "worker_running" in data def test_pending_starts_at_zero(self): data = client.get("/api/queue/status").json() assert data["pending"] == 0 class TestAuthMe: def test_unauthenticated_returns_false(self): resp = client.get("/api/auth/me") assert resp.status_code == 200 data = resp.json() assert data["authenticated"] is False class TestAuthLoginUrl: def test_returns_enabled_flag(self): resp = client.get("/api/auth/login-url") assert resp.status_code == 200 data = resp.json() assert "enabled" in data class TestBundeslaender: def test_returns_list(self): resp = client.get("/api/bundeslaender") assert resp.status_code == 200 data = resp.json() assert isinstance(data, list) assert len(data) > 10 # mindestens 10 BLs class TestProgramme: def test_returns_list(self): resp = client.get("/api/programme") assert resp.status_code == 200 data = resp.json() assert isinstance(data, list) assert len(data) > 50 # mindestens 50 Programme def test_status_returns_indexed_count(self): resp = client.get("/api/programme/status") assert resp.status_code == 200 data = resp.json() assert "indexed" in data assert "total" in data class TestHealth: def test_health(self): resp = client.get("/health") assert resp.status_code == 200 class TestVoteOrphansEndpoint: """GET /api/auswertungen/vote-orphans (öffentlich).""" def test_returns_json_structure(self): resp = client.get("/api/auswertungen/vote-orphans?limit=5") assert resp.status_code == 200 data = resp.json() assert "count" in data assert "items" in data assert "by_bundesland" in data assert isinstance(data["items"], list) def test_filter_bundesland_param(self): resp = client.get("/api/auswertungen/vote-orphans?bundesland=NRW&limit=3") assert resp.status_code == 200 data = resp.json() # Wenn items vorhanden, alle aus NRW for it in data["items"]: assert it["bundesland"] == "NRW" class TestVoteOrphansAutoRateAuth: """POST /api/auswertungen/vote-orphans/auto-rate erfordert Admin.""" def test_unauthenticated_rejected(self): resp = client.post( "/api/auswertungen/vote-orphans/auto-rate", data={"limit": 5}, ) # Auth-Wall greift entweder direkt 401, 403 oder Redirect (307/302) assert resp.status_code in (401, 403, 307, 302) class TestBatchAnalyzeAuth: """POST /api/batch-analyze erfordert Admin.""" def test_unauthenticated_rejected(self): resp = client.post( "/api/batch-analyze", data={"bundesland": "NRW", "limit": 5}, ) assert resp.status_code in (401, 403, 307, 302) def test_all_bl_unauthenticated_also_rejected(self): resp = client.post( "/api/batch-analyze", data={"bundesland": "ALL", "limit": 10}, ) assert resp.status_code in (401, 403, 307, 302) class TestAktuelleThemenEndpoints: """GET /api/aktuelle-themen/* sind oeffentlich.""" def test_top_returns_buckets(self): resp = client.get("/api/aktuelle-themen/top?days=7&top_k=3") assert resp.status_code == 200 data = resp.json() assert "buckets" in data assert "n_total_news" in data assert "filter" in data def test_top_with_single_date(self): resp = client.get("/api/aktuelle-themen/top?date=2026-05-01") assert resp.status_code == 200 data = resp.json() assert data["filter"]["single_date"] == "2026-05-01" def test_top_with_only_relevant(self): resp = client.get("/api/aktuelle-themen/top?only_relevant=true&top_k=5") assert resp.status_code == 200 data = resp.json() assert data["filter"]["only_relevant"] is True def test_zeitreihe(self): resp = client.get("/api/aktuelle-themen/zeitreihe?days=14") assert resp.status_code == 200 data = resp.json() assert "buckets" in data assert "sources" in data assert "series" in data def test_top_antraege(self): resp = client.get("/api/aktuelle-themen/top-antraege?min_gwoe_score=8.0") assert resp.status_code == 200 data = resp.json() assert "antraege" in data def test_cluster(self): resp = client.get("/api/aktuelle-themen/cluster?days=7") assert resp.status_code == 200 data = resp.json() assert "clusters" in data def test_drafts_list(self): resp = client.get("/api/aktuelle-themen/drafts?limit=5") assert resp.status_code == 200 data = resp.json() assert "drafts" in data def test_drafts_versions(self): resp = client.get( "/api/aktuelle-themen/drafts-versions" "?drucksache=missing&news_url=https://example.com/x" ) assert resp.status_code == 200 data = resp.json() assert "versions" in data assert isinstance(data["versions"], list)