157 lines
6.0 KiB
Python
157 lines
6.0 KiB
Python
"""Das Buch der Abende: Wertungen als Momentaufnahme, Kommentare als
|
|
Diskussion — verschachtelt, so tief man will."""
|
|
|
|
|
|
def abend(client, film, movie_id=1):
|
|
"""Host trägt einen Film ein, gibt die watched_id zurück."""
|
|
return client.post("/api/watched", json={"movie_id": film(movie_id)}).json()["id"]
|
|
|
|
|
|
def wertung(client, watched_id, stars=4):
|
|
client.post(f"/api/watched/{watched_id}/rating", json={"stars": stars})
|
|
return next(f for f in client.get("/api/watched").json() if f["id"] == watched_id)
|
|
|
|
|
|
def film_von(client, watched_id):
|
|
return next(f for f in client.get("/api/watched").json() if f["id"] == watched_id)
|
|
|
|
|
|
def kommentar(client, watched_id, text, parent_id=None):
|
|
antwort = client.post(
|
|
f"/api/watched/{watched_id}/notes", json={"text": text, "parent_id": parent_id}
|
|
)
|
|
assert antwort.status_code == 200, antwort.text
|
|
return antwort.json()["id"]
|
|
|
|
|
|
def test_laufende_nummer_zaehlt_vom_ersten_abend(client, film):
|
|
erster = abend(client, film, 1)
|
|
client.patch(f"/api/watched/{erster}", json={"watched_at": "2026-01-01"})
|
|
zweiter = abend(client, film, 2)
|
|
client.patch(f"/api/watched/{zweiter}", json={"watched_at": "2026-01-08"})
|
|
|
|
liste = client.get("/api/watched").json()
|
|
# Jüngster zuerst, trägt aber die höchste Nummer
|
|
assert [(f["id"], f["nummer"]) for f in liste] == [(zweiter, 2), (erster, 1)]
|
|
|
|
|
|
def test_katalogdaten_haengen_am_abend(client):
|
|
from app import db
|
|
|
|
with db.connect() as conn:
|
|
db.upsert(conn, {"id": 5, "title": "Alien", "backdrop_path": "/b.jpg",
|
|
"images": ["/s1.jpg"], "runtime": 117, "genres": ["Horror"]})
|
|
watched_id = client.post("/api/watched", json={"movie_id": 5}).json()["id"]
|
|
f = film_von(client, watched_id)
|
|
assert f["backdrop_path"] == "/b.jpg"
|
|
assert f["images"] == ["/s1.jpg"]
|
|
assert f["runtime"] == 117
|
|
assert f["genres"] == ["Horror"]
|
|
|
|
|
|
def test_kommentare_bilden_einen_baum(client, client2, film):
|
|
watched_id = abend(client, film)
|
|
oben = kommentar(client, watched_id, "War super.")
|
|
antwort = kommentar(client2, watched_id, "Fand ich nicht.", oben)
|
|
tiefer = kommentar(client, watched_id, "Doch!", antwort)
|
|
noch_einer = kommentar(client2, watched_id, "Anderes Thema.")
|
|
|
|
notes = film_von(client, watched_id)["notes"]
|
|
assert [n["text"] for n in notes] == ["War super.", "Anderes Thema."]
|
|
assert notes[0]["replies"][0]["text"] == "Fand ich nicht."
|
|
assert notes[0]["replies"][0]["name"] == "Ben"
|
|
assert notes[0]["replies"][0]["mine"] is False
|
|
assert notes[0]["replies"][0]["replies"][0]["text"] == "Doch!"
|
|
assert notes[0]["replies"][0]["replies"][0]["mine"] is True
|
|
assert notes[1]["replies"] == []
|
|
assert (oben, antwort, tiefer, noch_einer) == tuple(sorted((oben, antwort, tiefer, noch_einer)))
|
|
|
|
|
|
def test_zehn_ebenen_tief(client, film):
|
|
watched_id = abend(client, film)
|
|
vater = None
|
|
for stufe in range(10):
|
|
vater = kommentar(client, watched_id, f"Stufe {stufe}", vater)
|
|
|
|
knoten = film_von(client, watched_id)["notes"][0]
|
|
tiefe = 0
|
|
while knoten["replies"]:
|
|
knoten = knoten["replies"][0]
|
|
tiefe += 1
|
|
assert tiefe == 9
|
|
assert knoten["text"] == "Stufe 9"
|
|
|
|
|
|
def test_leerer_text_oder_fremder_vater_werden_abgelehnt(client, film):
|
|
watched_id = abend(client, film, 1)
|
|
anderer = abend(client, film, 2)
|
|
dort = kommentar(client, anderer, "woanders")
|
|
|
|
assert client.post(f"/api/watched/{watched_id}/notes", json={"text": " "}).status_code == 400
|
|
# Der Vater gehört zu einem anderen Abend
|
|
assert client.post(
|
|
f"/api/watched/{watched_id}/notes", json={"text": "x", "parent_id": dort}
|
|
).status_code == 400
|
|
assert client.post(
|
|
f"/api/watched/{watched_id}/notes", json={"text": "x", "parent_id": 9999}
|
|
).status_code == 400
|
|
|
|
|
|
def test_wertungen_und_kommentare_sind_unabhaengig(client, film):
|
|
watched_id = abend(client, film)
|
|
wertung(client, watched_id, 5)
|
|
kommentar(client, watched_id, "Diskussion.")
|
|
f = film_von(client, watched_id)
|
|
assert f["average"] == 5.0 and f["mine"] == 5
|
|
# Die Namen an den Wertungen sieht nur der Host
|
|
assert f["ratings"] == []
|
|
assert [n["text"] for n in f["notes"]] == ["Diskussion."]
|
|
|
|
|
|
def test_eigenen_kommentar_loeschen_fremden_nicht(client, client2, film):
|
|
watched_id = abend(client, film)
|
|
meiner = kommentar(client, watched_id, "meiner")
|
|
|
|
assert client2.delete(f"/api/watched-notes/{meiner}").status_code == 404
|
|
assert client.delete(f"/api/watched-notes/{meiner}").json()["removed"] == 1
|
|
assert film_von(client, watched_id)["notes"] == []
|
|
|
|
|
|
def test_loeschen_nimmt_den_ganzen_ast_mit(client, client2, film):
|
|
"""Eine Antwort ohne ihren Anlass ergäbe keinen Sinn."""
|
|
watched_id = abend(client, film)
|
|
oben = kommentar(client, watched_id, "a")
|
|
mitte = kommentar(client2, watched_id, "b", oben)
|
|
unten = kommentar(client, watched_id, "c", mitte)
|
|
daneben = kommentar(client2, watched_id, "d")
|
|
|
|
assert client.delete(f"/api/watched-notes/{oben}").json()["removed"] == 3
|
|
notes = film_von(client, watched_id)["notes"]
|
|
assert [n["id"] for n in notes] == [daneben]
|
|
|
|
|
|
def test_host_loescht_jeden_kommentar(client, zuschauer, hostmodus, film):
|
|
watched_id = abend(client, film)
|
|
note_id = kommentar(client, watched_id, "x")
|
|
hostmodus(zuschauer)
|
|
assert zuschauer.delete(f"/api/watched-notes/{note_id}").json()["removed"] == 1
|
|
|
|
|
|
def test_film_loeschen_raeumt_alles(client, client2, film):
|
|
from app import db
|
|
|
|
watched_id = abend(client, film)
|
|
wertung(client, watched_id, 5)
|
|
oben = kommentar(client2, watched_id, "frei")
|
|
kommentar(client, watched_id, "antwort", oben)
|
|
|
|
client.delete(f"/api/watched/{watched_id}")
|
|
with db.connect() as conn:
|
|
for tabelle in ("ratings", "watched_notes"):
|
|
assert conn.execute(f"SELECT COUNT(*) FROM {tabelle}").fetchone()[0] == 0, tabelle
|
|
|
|
|
|
def test_zuschauer_darf_nicht_schreiben(zuschauer, client, film):
|
|
watched_id = abend(client, film)
|
|
assert zuschauer.post(f"/api/watched/{watched_id}/notes", json={"text": "x"}).status_code == 403
|