- source_meta.py kennt jetzt den echten Bestand: Kategorien telegram (107 Quellen) und x (40), Typen x_account und pdf_document. Die 10 nie belegten Lagen-Kategorien und der ungenutzte Typ excluded sind raus. - Pydantic-Pattern source_type um x_account ergaenzt, excluded raus. Behebt 422 beim Speichern von 40 X-Account-Quellen. - Modal-Selects (Typ, Kategorie, PDF-Kategorie) werden aus /api/sources/meta befuellt statt hartkodiert. Submit sendet category/source_type nur noch, wenn nicht leer. Behebt stilles Loeschen der Kategorie bei Telegram-Quellen. - source_suggester: Import auf shared.agents.claude_client angepasst (war im Portal seit jeher kaputt, Konvention wie source_classifier). - Toter Code raus: POST /health/run-stream (147 Z. SSE-Duplikat), runHealthCheck() im Frontend, excluded_counts-CTE + Sperren-Spalte (immer 0), Trend-Delta (braucht 2 Runs, es gibt 1), Alignment-Chips (source_alignments ist leer), doppeltes formatDateTime, redundanter setupHealthTab-Listener, toter healthContent-Zugriff. - Tests: Kategorien-/Typen-Sets neu gepinnt, Smoke-Karteileichen entfernt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
74 Zeilen
2.5 KiB
Python
74 Zeilen
2.5 KiB
Python
"""Integration-Tests fuer DB-freie Endpoints mit Mock-Auth.
|
|
|
|
GET /api/sources/meta liefert die Single-Source-of-Truth Kategorien/Typen
|
|
und braucht keine DB. Mit override des get_current_admin Dependency
|
|
testen wir den Endpoint richtig durch (echtes JSON, echtes Schema).
|
|
"""
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
@pytest.fixture
|
|
def authed_client():
|
|
from main import app
|
|
from auth import get_current_admin
|
|
|
|
def fake_admin():
|
|
return {"id": 1, "email": "test@aegis-sight.de", "username": "test"}
|
|
|
|
app.dependency_overrides[get_current_admin] = fake_admin
|
|
yield TestClient(app)
|
|
app.dependency_overrides = {}
|
|
|
|
|
|
def test_meta_returns_schema(authed_client):
|
|
r = authed_client.get("/api/sources/meta")
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
assert "categories" in data
|
|
assert "types" in data
|
|
assert isinstance(data["categories"], list)
|
|
assert isinstance(data["types"], list)
|
|
|
|
|
|
def test_meta_categories_have_required_fields(authed_client):
|
|
r = authed_client.get("/api/sources/meta")
|
|
data = r.json()
|
|
for cat in data["categories"]:
|
|
assert "key" in cat
|
|
assert "label" in cat
|
|
assert isinstance(cat["key"], str) and cat["key"]
|
|
assert isinstance(cat["label"], str) and cat["label"]
|
|
|
|
|
|
def test_meta_types_have_required_fields(authed_client):
|
|
r = authed_client.get("/api/sources/meta")
|
|
data = r.json()
|
|
for t in data["types"]:
|
|
assert "key" in t
|
|
assert "label" in t
|
|
|
|
|
|
def test_meta_categories_exact_set(authed_client):
|
|
"""Bereinigte Kategorienliste - exakt gepinnt gegen stilles Driften.
|
|
|
|
telegram und x muessen drin sein (147 Quellen im Bestand), die frueher
|
|
definierten, aber nie belegten Lagen-Kategorien sind bewusst entfernt.
|
|
"""
|
|
r = authed_client.get("/api/sources/meta")
|
|
keys = {c["key"] for c in r.json()["categories"]}
|
|
assert keys == {
|
|
"nachrichtenagentur", "oeffentlich-rechtlich", "qualitaetszeitung",
|
|
"behoerde", "fachmedien", "think-tank", "international", "regional",
|
|
"boulevard", "telegram", "x", "sonstige",
|
|
}
|
|
assert "cybercrime" not in keys
|
|
assert "stimmungsbild" not in keys
|
|
|
|
|
|
def test_meta_includes_all_source_types(authed_client):
|
|
"""Alle 6 Source-Types muessen rauskommen (excluded ist bewusst entfernt)."""
|
|
r = authed_client.get("/api/sources/meta")
|
|
keys = {t["key"] for t in r.json()["types"]}
|
|
assert keys == {"rss_feed", "web_source", "telegram_channel", "podcast_feed", "x_account", "pdf_document"}
|