init
This commit is contained in:
87
backend/tests/test_routes.py
Normal file
87
backend/tests/test_routes.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""API-Routen: Lesen + Scan-Start über httpx/ASGITransport (gleicher Event-Loop wie
|
||||
create_task und der DB-Write-Lock — fastapi.TestClient wäre die Loop-Falle)."""
|
||||
import asyncio
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
import config
|
||||
import scan_dienst
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def client(gescanntes_repo, monkeypatch, tmp_path):
|
||||
wurzel, git = gescanntes_repo
|
||||
datei = tmp_path / "projekte.txt"
|
||||
datei.write_text(f"{wurzel}\n{tmp_path}/tot\n")
|
||||
monkeypatch.setattr(config, "PROJEKTE_DATEI", datei)
|
||||
scan_dienst._laeufe.clear()
|
||||
from server import app
|
||||
transport = httpx.ASGITransport(app=app)
|
||||
async with httpx.AsyncClient(transport=transport, base_url="http://test") as c:
|
||||
yield c, wurzel, git
|
||||
|
||||
|
||||
async def test_projektliste(client):
|
||||
c, wurzel, _ = client
|
||||
r = await c.get("/api/projekte")
|
||||
assert r.status_code == 200
|
||||
eintraege = {p["name"]: p for p in r.json()}
|
||||
assert eintraege["mini"]["hat_planer"] is True
|
||||
assert eintraege["mini"]["drift"] == []
|
||||
assert eintraege["mini"]["scan_laeuft"] is False
|
||||
assert "fehler" in eintraege["tot"]
|
||||
|
||||
|
||||
async def test_projekt_detail(client):
|
||||
c, _, _ = client
|
||||
r = await c.get("/api/projekte/mini")
|
||||
daten = r.json()
|
||||
assert daten["kern"]["titel"] == "mini"
|
||||
assert daten["bereiche"] and daten["bereiche"][0]["features"]
|
||||
assert "rechner.py::addiere" in daten["einheiten"]
|
||||
assert daten["doku_ordnung"]
|
||||
assert (await c.get("/api/projekte/gibtsnicht")).status_code == 404
|
||||
|
||||
|
||||
async def test_einheit_mit_code(client):
|
||||
c, _, _ = client
|
||||
r = await c.get("/api/projekte/mini/einheit", params={"id": "rechner.py::addiere"})
|
||||
e = r.json()
|
||||
assert "return a + b" in e["code"]
|
||||
assert e["veraltet"] is False
|
||||
assert (await c.get("/api/projekte/mini/einheit", params={"id": "x.py::y"})).status_code == 404
|
||||
|
||||
|
||||
async def test_drift_nach_commit(client):
|
||||
c, wurzel, git = client
|
||||
(wurzel / "rechner.py").write_text((wurzel / "rechner.py").read_text() + "\nX9 = 9\n")
|
||||
git("add", "-A")
|
||||
git("commit", "-m", "drift")
|
||||
r = await c.get("/api/projekte")
|
||||
mini = next(p for p in r.json() if p["name"] == "mini")
|
||||
assert mini["drift"] == ["rechner.py"]
|
||||
e = (await c.get("/api/projekte/mini/einheit", params={"id": "rechner.py::addiere"})).json()
|
||||
assert e["veraltet"] is True
|
||||
|
||||
|
||||
async def test_scan_starten_und_pollen(client):
|
||||
c, _, _ = client
|
||||
r = await c.post("/api/projekte/mini/scan", json={"art": "rescan"})
|
||||
assert r.json()["status"] == "gestartet"
|
||||
doppel = await c.post("/api/projekte/mini/scan", json={"art": "rescan"})
|
||||
assert doppel.json()["status"] in ("laeuft", "gestartet") # idempotent, nie Doppellauf
|
||||
for _ in range(100):
|
||||
s = (await c.get("/api/projekte/mini/scan-status")).json()
|
||||
if not s["laeuft"]:
|
||||
break
|
||||
await asyncio.sleep(0.1)
|
||||
assert s["ergebnis"]["status"] in ("ok", "unveraendert")
|
||||
|
||||
|
||||
async def test_scan_409_bei_dirty_tree(client):
|
||||
c, wurzel, _ = client
|
||||
(wurzel / "schmutz.py").write_text("X = 1\n")
|
||||
r = await c.post("/api/projekte/mini/scan", json={"art": "scan"})
|
||||
assert r.status_code == 409
|
||||
assert "uncommittete" in r.json()["detail"]
|
||||
Reference in New Issue
Block a user