Files
nico d56be7b2c0 Wichtel-Werkstatt: Secret-Santa-App mit Räumen, Ausschlüssen und Recovery-Links
- FastAPI + SQLite, serverseitig gerenderte Templates, mobil-zuerst
- Admin-Passwort, einseitige Ausschlüsse, eingefrorene Auslosung
- Teilnehmer sehen Ergebnis per Cookie; Einmal-Recovery-Links bei Verlust
- Docker/podman-tauglich (Entrypoint mit Privilegien-Drop, SELinux-:z)
- Unit-Tests für Auslosung, E2E-Testskript (30 Checks)
2026-08-05 16:07:21 +02:00

145 lines
6.7 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# End-to-End-Test gegen eine laufende Instanz.
# Aufruf: BASE=http://localhost:8080 bash tests/e2e.sh
set -euo pipefail
BASE="${BASE:-http://localhost:8080}"
JAR_DIR="$(mktemp -d)"
trap 'rm -rf "$JAR_DIR"' EXIT
PASS=0
FAIL=0
ok() { PASS=$((PASS+1)); echo " ✓ $1"; }
fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
check() { # check <beschreibung> <bedingung-wahr?>
if [ "${2:-0}" = "1" ]; then ok "$1"; else fail "$1"; fi
}
redirect_of() { # POST mit Formulardaten, liefert Location-Header
curl -s -o /dev/null -w '%{redirect_url}' "${@}"
}
echo "== Raum erstellen =="
LOC=$(curl -s -c "$JAR_DIR/admin" -o /dev/null -w '%{redirect_url}' \
--data-urlencode "room_name=E2E Raum" \
--data-urlencode "password=strenggeheim" \
"$BASE/rooms")
CODE=$(printf '%s' "$LOC" | sed -E 's|.*/r/([A-Z2-9]{6})/admin|\1|')
check "Raum angelegt, Code=$CODE" "$([ ${#CODE} -eq 6 ] && echo 1 || echo 0)"
PANEL=$(curl -s -b "$JAR_DIR/admin" "$BASE/r/$CODE/admin")
echo "$PANEL" | grep -q "Einladung teilen" && ok "Admin-Panel erreichbar" || fail "Admin-Panel erreichbar"
echo "== Falsches Admin-Passwort =="
curl -s -c "$JAR_DIR/fake" -o /dev/null --data-urlencode "password=falsch" "$BASE/r/$CODE/admin/login"
FAKE=$(curl -s -b "$JAR_DIR/fake" "$BASE/r/$CODE/admin")
echo "$FAKE" | grep -q "Admin-Bereich" && ok "Falsches Passwort bleibt im Login" || fail "Falsches Passwort bleibt im Login"
echo "== Teilnehmer registrieren =="
NAMES=(Anna Ben Clara David)
for n in "${NAMES[@]}"; do
LOC=$(curl -s -c "$JAR_DIR/$n" -o /dev/null -w '%{redirect_url}' \
--data-urlencode "name=$n" "$BASE/r/$CODE/register")
case "$LOC" in
*/r/"$CODE") ok "Registrierung $n" ;;
*) fail "Registrierung $n (Redirect: $LOC)" ;;
esac
done
LOC=$(curl -s -c "$JAR_DIR/dup" -o /dev/null -w '%{redirect_url}' \
--data-urlencode "name=anna" "$BASE/r/$CODE/register")
echo "$LOC" | grep -q "error=duplicate" && ok "Doppelter Name wird abgelehnt" || fail "Doppelter Name wird abgelehnt"
echo "== Admin nimmt selbst teil =="
SELF=$(curl -s -b "$JAR_DIR/admin" -c "$JAR_DIR/admin" --data-urlencode "name=Nico" "$BASE/r/$CODE/admin/self-register")
echo "$SELF" | grep -q "wichtelst als »Nico«" && ok "Admin als Teilnehmer angemeldet" || fail "Admin als Teilnehmer angemeldet"
WAIT=$(curl -s -b "$JAR_DIR/admin" "$BASE/r/$CODE")
echo "$WAIT" | grep -q "Hi Nico" && ok "Admin sieht eigene Teilnehmeransicht" || fail "Admin sieht eigene Teilnehmeransicht"
SELF2=$(curl -s -b "$JAR_DIR/admin" --data-urlencode "name=Nico" "$BASE/r/$CODE/admin/self-register")
echo "$SELF2" | grep -q "bereits vergeben" && ok "Admin-Doppelname wird abgelehnt" || fail "Admin-Doppelname wird abgelehnt"
NAMES=(Anna Ben Clara David Nico)
# Nicos Teilnehmer-Cookie lebt im Admin-Jar für die Ergebnis-Prüfung kopieren
cp "$JAR_DIR/admin" "$JAR_DIR/Nico"
echo "== Ausschlüsse (Anna darf Ben nicht ziehen, Ben darf Anna nicht ziehen) =="
PANEL=$(curl -s -b "$JAR_DIR/admin" "$BASE/r/$CODE/admin")
id_of() { printf '%s' "$PANEL" | grep -oE "value=\"[^\"]+\">$1<" | head -1 | sed -E 's/value="([^"]+)".*/\1/'; }
ANNA_ID=$(id_of Anna); BEN_ID=$(id_of Ben)
check "Teilnehmer-IDs gefunden" "$([ -n "$ANNA_ID" ] && [ -n "$BEN_ID" ] && echo 1 || echo 0)"
curl -s -b "$JAR_DIR/admin" -o /dev/null \
--data-urlencode "from_id=$ANNA_ID" --data-urlencode "to_id=$BEN_ID" "$BASE/r/$CODE/exclusions/add"
curl -s -b "$JAR_DIR/admin" -o /dev/null \
--data-urlencode "from_id=$BEN_ID" --data-urlencode "to_id=$ANNA_ID" "$BASE/r/$CODE/exclusions/add"
PANEL=$(curl -s -b "$JAR_DIR/admin" "$BASE/r/$CODE/admin")
echo "$PANEL" | grep -q "Anna ➜ darf nicht ➜ Ben" && ok "Ausschluss sichtbar" || fail "Ausschluss sichtbar"
echo "== Auslosen =="
DRAW=$(curl -s -b "$JAR_DIR/admin" -X POST "$BASE/r/$CODE/draw")
echo "$DRAW" | grep -q "Auslosung ist abgeschlossen" && ok "Auslosung erfolgreich" || fail "Auslosung erfolgreich"
echo "== Ergebnisse der Teilnehmer =="
declare -A RECEIVER
for n in "${NAMES[@]}"; do
PAGE=$(curl -s -b "$JAR_DIR/$n" "$BASE/r/$CODE")
R=$(printf '%s' "$PAGE" | grep -oE 'result-name">🎁 [^<]+' | sed 's/result-name">🎁 //')
RECEIVER[$n]="$R"
if [ -n "$R" ] && [ "$R" != "$n" ]; then
ok "$n beschenkt $R"
else
fail "Ergebnis für $n (Wert: '$R')"
fi
done
SORTED=$(printf '%s\n' "${RECEIVER[@]}" | sort)
UNIQUE=$(printf '%s\n' "${RECEIVER[@]}" | sort -u)
check "Jede Person wird genau einmal beschenkt" "$([ "$SORTED" = "$UNIQUE" ] && echo 1 || echo 0)"
check "Ausschluss eingehalten: Anna ≠> Ben" "$([ "${RECEIVER[Anna]}" != "Ben" ] && echo 1 || echo 0)"
check "Ausschluss eingehalten: Ben ≠> Anna" "$([ "${RECEIVER[Ben]}" != "Anna" ] && echo 1 || echo 0)"
echo "== Admin sieht keine Zuweisungen =="
PANEL=$(curl -s -b "$JAR_DIR/admin" "$BASE/r/$CODE/admin")
echo "$PANEL" | grep -q "Ausgelost" && ok "Admin sieht Auslosungs-Status" || fail "Admin sieht Auslosungs-Status"
LEAK=1
echo "$PANEL" | grep -q "Du beschenkst" && LEAK=0
for n in "${NAMES[@]}"; do
echo "$PANEL" | grep -qE "$n (beschenkt|zieht)" && LEAK=0
done
check "Keine Ergebnis-Details im Admin-Panel" "$LEAK"
echo "== Raum ist eingefroren =="
DEL=$(curl -s -b "$JAR_DIR/admin" -X POST "$BASE/r/$CODE/participants/$ANNA_ID/delete")
echo "$DEL" | grep -q "eingefroren\|können keine" && ok "Teilnehmer löschen nach Auslosung blockiert" || fail "Teilnehmer löschen nach Auslosung blockiert"
DRAW2=$(curl -s -b "$JAR_DIR/admin" -X POST "$BASE/r/$CODE/draw")
echo "$DRAW2" | grep -q "bereits ausgelost" && ok "Zweite Auslosung blockiert" || fail "Zweite Auslosung blockiert"
LATE=$(curl -s -o /dev/null -w '%{redirect_url}' -c "$JAR_DIR/late" --data-urlencode "name=Zuspät" "$BASE/r/$CODE/register")
PAGE=$(curl -s -b "$JAR_DIR/late" "$BASE/r/$CODE")
echo "$PAGE" | grep -q "nicht mehr möglich" && ok "Keine Registrierung nach Auslosung" || fail "Keine Registrierung nach Auslosung"
echo "== Recovery-Link (Cookie verloren) =="
RECOV=$(curl -s -b "$JAR_DIR/admin" -X POST "$BASE/r/$CODE/recovery/$ANNA_ID")
LINK=$(printf '%s' "$RECOV" | grep -oE 'value="[^"]+/recover/[^"]+"' | sed -E 's/^value="//; s/"$//')
check "Recovery-Link erzeugt" "$([ -n "$LINK" ] && echo 1 || echo 0)"
LOC=$(curl -s -c "$JAR_DIR/anna_neu" -o /dev/null -w '%{redirect_url}' "$LINK")
case "$LOC" in
http://*|https://*) TARGET="$LOC" ;;
*) TARGET="$BASE$LOC" ;;
esac
PAGE=$(curl -s -b "$JAR_DIR/anna_neu" "$TARGET")
if echo "$PAGE" | grep -q "Ho ho ho, Anna" && echo "$PAGE" | grep -q "🎁 ${RECEIVER[Anna]}"; then
ok "Anna sieht mit neuem Cookie wieder ihr Ergebnis (${RECEIVER[Anna]})"
else
fail "Anna sieht mit neuem Cookie wieder ihr Ergebnis"
fi
PAGE=$(curl -s -L "$LINK")
echo "$PAGE" | grep -q "bereits verwendet" && ok "Recovery-Link ist Einmal-Link" || fail "Recovery-Link ist Einmal-Link"
echo
echo "ERGEBNIS: $PASS ok, $FAIL fehlgeschlagen"
[ "$FAIL" -eq 0 ]