Files
weircon-front/tests/erindringer_smoke.py
T
root 3dee428a37
CD / deploy (push) Successful in 17s
CI / check (push) Successful in 23s
feat(erindringer): samtalestyring med forberedte spørgsmål, talt udgave med lydtags, spørgsmålets lyd gemmes med svaret
Intervieweren når de forberedte spørgsmål, følger op højst N gange pr. spørgsmål
(indstilles pr. emne), trækker tilbage til emnet og afrunder. 'Spring over' i UI.
Spørgsmålet oplæses med ElevenLabs-tags ([warmly], [chuckles] …) som ikke vises
i teksten; oplæsningen gemmes som <id>-sp.mp3 ved siden af svaret og følger med i
zip-eksporten, så spørgsmål + svar kan klippes ind i en podcast.

Claude-Session: https://claude.ai/code/session_01JmhJG6JnhXfzNiKv8f2vHu
2026-10-06 22:15:46 +02:00

63 lines
5.0 KiB
Python

# Røgtest af erindringer-modulet med FastAPI TestClient, uden OIDC: sessionen sættes direkte.
# Kør i CT151: PORTAL_DATA=/tmp/ef-test/data + env fra /etc/portal.env. Rører ikke prod-data.
import io, json, os, sys
from fastapi.testclient import TestClient
import main, erindringer
c = TestClient(main.app, base_url="https://weircon.dk")
adm = {"username": "agw", "name": "Asger", "groups": [main.config.ADMIN_GROUP, "Familie"]}
def login(client, user):
# Starlette-session: skriv via en lille rute er omstændeligt; monkeypatch current_user i stedet.
main.current_user = lambda request: user
login(c, adm)
r = c.get("/admin/erindringer"); assert r.status_code == 200 and "Erindringer" in r.text, r.status_code
r = c.post("/admin/erindringer/projekt", data={"slug": "test-ep", "titel": "Testemne", "beskrivelse": "b", "kontekst": "Personen er Asger. Vi ved at han bor i Sønderlund.", "start": "Hvad husker du fra Rørbæk?\nHvem var din morfar?"}, follow_redirects=False)
assert r.status_code == 303, r.text
assert erindringer.projekt("test-ep")["start"][0].startswith("Hvad husker")
r = c.post("/admin/erindringer/gaest", data={"navn": "Tina Test", "projekter": ["test-ep"]}, follow_redirects=False)
assert r.status_code == 303
pid = [p for p in erindringer.alle_personer() if p["navn"] == "Tina Test"][0]["pid"]; noegle = erindringer.person(pid)["noegle"]
print("gæst", pid)
# API som gæst (uden session)
login(c, None)
r = c.post("/erindringer/api/naeste", json={"projekt": "test-ep", "samtale": None, "noegle": noegle}); assert r.status_code == 200, r.text
q1 = r.json(); print("Q1", q1["spoergsmaal"], "| lyd:", bool(q1["lyd_url"]))
if q1["lyd_url"]:
assert c.get(q1["lyd_url"]).status_code == 200
r = c.post("/erindringer/api/svar", data={"projekt": "test-ep", "samtale": q1["samtale"], "spoergsmaal": q1["spoergsmaal"], "noegle": noegle, "tekst": "Jeg husker min morfar Gustav i Villa Monika i Hannerup. Han havde en stor have og en motorcykel, som han aldrig kørte på."})
assert r.status_code == 200, r.text; s1 = r.json(); print("svar1", s1["id"])
r = c.post("/erindringer/api/naeste", json={"projekt": "test-ep", "samtale": q1["samtale"], "noegle": noegle}); assert r.status_code == 200, r.text
q2 = r.json(); print("Q2 (Claude)", q2["spoergsmaal"], "| talt:", q2["talt"], "| kilde:", q2["kilde"], "| afslut:", q2["afslut"])
assert "[" not in q2["spoergsmaal"] and q2["lyd_sha"]
# spring over: det sprungne må ikke komme igen
r = c.post("/erindringer/api/naeste", json={"projekt": "test-ep", "samtale": q1["samtale"], "noegle": noegle, "sprunget": [q2["spoergsmaal"]]}); assert r.status_code == 200
assert r.json()["spoergsmaal"] != q2["spoergsmaal"]; print("Q3 efter spring", r.json()["spoergsmaal"], "| kilde:", r.json()["kilde"])
# lydsvar: 2 s tone som mp3 lavet med ffmpeg
os.system("ffmpeg -y -v error -f lavfi -i 'sine=frequency=440:duration=2' -c:a libmp3lame /tmp/ef-test/tone.mp3")
r = c.post("/erindringer/api/svar", data={"projekt": "test-ep", "samtale": q1["samtale"], "spoergsmaal": q2["spoergsmaal"], "spoergsmaal_talt": q2["talt"], "lyd_sha": q2["lyd_sha"], "kilde": q2["kilde"], "noegle": noegle}, files={"lyd": ("svar.mp3", open("/tmp/ef-test/tone.mp3", "rb"), "audio/mpeg")})
assert r.status_code == 200, r.text; s2 = r.json(); print("svar2 lyd", s2["id"], "varighed", s2["varighed"], "tekst:", repr(s2["tekst"])[:60])
r = c.get(f"/erindringer/g/{noegle}/klip/{s2['id']}.mp3"); assert r.status_code == 200 and r.headers["content-type"].startswith("audio")
r = c.get(f"/erindringer/g/{noegle}/klip/{s2['id']}-sp.mp3"); assert r.status_code == 200, "spørgsmålets lyd mangler"
k2 = erindringer.klip(pid, s2["id"]); assert k2["spoergsmaal_lyd"] and k2["kilde"] == q2["kilde"] and k2["spoergsmaal_talt"] == q2["talt"]
r = c.post("/erindringer/api/ret", json={"id": s1["id"], "tekst": "Rettet tekst.", "noegle": noegle}); assert r.status_code == 200
assert erindringer.klip(pid, s1["id"])["tekst"] == "Rettet tekst."
# forkert nøgle -> 404
r = c.post("/erindringer/api/naeste", json={"projekt": "test-ep", "samtale": None, "noegle": "x" * 40}); assert r.status_code == 404
# indlogget familie: dagbog findes, admin-person-side, eksport
login(c, adm)
r = c.post("/erindringer/api/naeste", json={"projekt": "dagbog", "samtale": None, "noegle": ""}); assert r.status_code == 200, r.text
print("dagbog Q", r.json()["spoergsmaal"])
r = c.get(f"/admin/erindringer/p/{pid}"); assert r.status_code == 200 and "Rettet tekst." in r.text
r = c.get(f"/admin/erindringer/p/{pid}/eksport.zip"); assert r.status_code == 200 and r.headers["content-type"] == "application/zip" and len(r.content) > 1000
r = c.post(f"/admin/erindringer/p/{pid}/klip/{s1['id']}", data={"handling": "favorit", "favorit": "1"}, follow_redirects=False); assert r.status_code == 303
assert erindringer.klip(pid, s1["id"])["favorit"] is True
r = c.post(f"/admin/erindringer/person/{pid}", data={"handling": "luk"}, follow_redirects=False); assert r.status_code == 303
login(c, None)
r = c.post("/erindringer/api/naeste", json={"projekt": "test-ep", "samtale": None, "noegle": noegle}); assert r.status_code == 404
print("ALT OK")