Tests: pytest-Suite für Konten, Haushalt, Kanban, Reisen und Migrationen

- backend/tests: jede Test-Funktion bekommt eine frische Datenbank;
  test_migrationen.py baut ältere Datenbank-Stände nach und prüft die
  verlustfreie Umstellung (auch zweiter Start ohne Änderung)
- requirements-dev.txt mit pytest
- Fix (von den Tests gefunden): Eine neue, leere Datenbank bekam keine
  erste Liste "Zuhause"; jetzt einmalig beim ersten Start

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-15 18:07:54 +02:00
1 parent dc4ce18593
commit 79cbaab092
10 files changed
+478

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
from datetime import datetime, timedelta, timezone
def ago(days):
return (datetime.now(timezone.utc) - timedelta(days=days)).isoformat(timespec="milliseconds").replace("+00:00", "Z")
def board(client, project_id):
return client.get(f"/api/kanban/projekte/{project_id}").json()
def make_board(client):
return client.post("/api/kanban/projekte", json={"name": "Test"}).json()["id"]
def task(client, project_id, title, status="offen"):
data = client.post(f"/api/kanban/projekte/{project_id}/aufgaben", json={"title": title, "status": status}).json()
return next(t for t in data["tasks"] if t["title"] == title)
def test_erledigt_setzt_und_loescht_zeitpunkt(login):
anna = login("anna")
pid = make_board(anna)
t = task(anna, pid, "A")
assert t["doneAt"] is None
data = anna.patch(f"/api/kanban/aufgaben/{t['id']}", json={"status": "erledigt"}).json()
assert next(x for x in data["tasks"] if x["id"] == t["id"])["doneAt"]
data = anna.patch(f"/api/kanban/aufgaben/{t['id']}", json={"status": "arbeit"}).json()
assert next(x for x in data["tasks"] if x["id"] == t["id"])["doneAt"] is None
assert task(anna, pid, "Gleich erledigt", status="erledigt")["doneAt"]
def test_archiv_nach_2_tagen_loeschen_nach_14(login, conn):
anna = login("anna")
pid = make_board(anna)
for title in ("frisch", "alt", "uralt"):
task(anna, pid, title, status="erledigt")
with conn:
conn.execute("UPDATE kanban_tasks SET done_at = ? WHERE title = 'alt'", (ago(3),))
conn.execute("UPDATE kanban_tasks SET done_at = ? WHERE title = 'uralt'", (ago(15),))
data = board(anna, pid)
assert [t["title"] for t in data["tasks"]] == ["frisch"]
assert [t["title"] for t in data["archived"]] == ["alt"]
assert data["archived"][0]["deleteAt"] > ago(-10)
assert conn.execute("SELECT COUNT(*) FROM kanban_tasks WHERE title = 'uralt'").fetchone()[0] == 0
def test_zurueckholen_startet_fristen_neu(login, conn):
anna = login("anna")
pid = make_board(anna)
t = task(anna, pid, "alt", status="erledigt")
with conn:
conn.execute("UPDATE kanban_tasks SET done_at = ? WHERE id = ?", (ago(5), t["id"]))
data = anna.post(f"/api/kanban/aufgaben/{t['id']}/zurueckholen").json()
assert data["archived"] == []
assert [x["title"] for x in data["tasks"]] == ["alt"]
def test_loeschen_nur_ersteller_oder_admin(login):
anna, ben, chef = login("anna"), login("ben"), login("chef", admin=True)
pid = make_board(anna)
t1, t2 = task(anna, pid, "eins"), task(anna, pid, "zwei")
assert ben.delete(f"/api/kanban/aufgaben/{t1['id']}").status_code == 403
assert anna.delete(f"/api/kanban/aufgaben/{t1['id']}").status_code == 200
assert chef.delete(f"/api/kanban/aufgaben/{t2['id']}").status_code == 200