Files
kleiderboerse/tests/test_entwuerfe.py
T
StefanandClaude Opus 5 3d7b7c706a Phase 1: Datenmodell, CRUD-API und Stammdaten
FastAPI mit SQLAlchemy und SQLite, Migrationen über Alembic. Die
Endpunkte aus projekt.md für items, categories und sizes stehen samt
Reservierung; Bilder und Anmeldung folgen in Phase 2 und 3.

Umgesetzt wie in Plan.md festgelegt:

- Feste Wertelisten als Enum UND als CHECK in der Datenbank. Die
  CHECK-Bedingung ist der eigentliche Schutz: an SQLAlchemy vorbei (Import,
  sqlite3 von Hand) käme sonst "Gril" durch, und die Filter griffen still
  nicht mehr.
- Status "draft" für den Stapel-Import. Entwürfe erscheinen weder in der
  Galerie noch in GET /items, solange nicht ausdrücklich status=draft
  angefragt wird, und lassen sich nicht reservieren.
- Titel ist freiwillig und wird sonst beim ANZEIGEN aus Kategorie und
  Grösse gebildet ("Jacken 98/104") - nicht beim Speichern, damit er einer
  späteren Korrektur der Grösse folgt.
- reservation_token: nur wer es hat, kann die eigene Reservierung aufheben.
  Verglichen mit compare_digest, gelöscht beim Freigeben und beim
  Erledigen, damit ein alter Link nicht später eine fremde Reservierung
  aufhebt.
- Eigene sizes-Tabelle mit sort_order statt SELECT DISTINCT: sonst stünde
  "104" vor "56" und jeder Tippfehler würde zur Filteroption.
- Pagination auf GET /items, in projekt.md nicht vorgesehen.

Zwei SQLite-Eigenheiten, die leicht untergehen: foreign_keys ist
standardmässig AUS (ohne PRAGMA greift ON DELETE CASCADE nicht), und
check_same_thread muss für FastAPI abgeschaltet werden. Beides in
database.py, dazu WAL fürs gleichzeitige Lesen.

24 Tests, alle grün. Zusätzlich von Hand geprüft: Migration anwenden,
Eintrag anlegen, reservieren, ohne Token freigeben (403), mit Token
freigeben (200), Swagger UI erreichbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GR4bNaj9GtRu57J4Niii8o
2026-08-29 22:00:58 +02:00

54 lines
1.8 KiB
Python

"""Tests zum Stapel-Import.
Entwürfe entstehen beim Hochladen vieler Fotos auf einmal und haben noch
keine Angaben. Entscheidend ist, dass sie nicht in der Galerie auftauchen.
"""
from app import crud
def test_entwuerfe_erscheinen_nicht_in_der_galerie(client, db_sitzung, kategorie_id):
crud.entwuerfe_anlegen(db_sitzung, 3)
client.post("/api/v1/items", json={"size": "80", "category_id": kategorie_id})
galerie = client.get("/api/v1/items").json()
assert galerie["total"] == 1
entwuerfe = client.get("/api/v1/items?status=draft").json()
assert entwuerfe["total"] == 3
def test_entwurf_darf_unvollstaendig_sein(client, db_sitzung):
entwurf = crud.entwuerfe_anlegen(db_sitzung, 1)[0]
assert entwurf.size is None
assert entwurf.category_id is None
assert entwurf.anzeige_titel == "Kleidungsstück"
def test_entwurf_wird_durch_nachtragen_sichtbar(client, db_sitzung, kategorie_id):
entwurf = crud.entwuerfe_anlegen(db_sitzung, 1)[0]
antwort = client.patch(
f"/api/v1/items/{entwurf.id}",
json={"size": "92", "category_id": kategorie_id, "status": "available"},
)
assert antwort.status_code == 200
assert client.get("/api/v1/items").json()["total"] == 1
def test_unvollstaendiger_eintrag_kann_nicht_veroeffentlicht_werden(
client, db_sitzung
):
"""Die CHECK-Bedingung greift auch dann, wenn die Route es zuliesse."""
entwurf = crud.entwuerfe_anlegen(db_sitzung, 1)[0]
antwort = client.patch(f"/api/v1/items/{entwurf.id}", json={"status": "available"})
assert antwort.status_code == 422
def test_entwurf_kann_nicht_reserviert_werden(client, db_sitzung):
entwurf = crud.entwuerfe_anlegen(db_sitzung, 1)[0]
antwort = client.post(
f"/api/v1/items/{entwurf.id}/reserve", json={"reserved_by": "Wer auch immer"}
)
assert antwort.status_code == 404