diff --git a/tests/test_plan_sessions_wp15.py b/tests/test_plan_sessions_wp15.py new file mode 100644 index 0000000..72d3fab --- /dev/null +++ b/tests/test_plan_sessions_wp15.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Integration/E2E-Tests für plan_sessions (v0.1.0).""" +import os +import requests +from datetime import datetime, timezone + +BASE = os.getenv("BASE_URL", "http://127.0.0.1:8000").rstrip("/") + + +def test_plan_session_create_read(): + # 1) Template minimal + tpl = { + "name": "Std 60 for sessions", + "discipline": "Karate", + "age_group": "Erwachsene", + "target_group": "Breitensport", + "total_minutes": 60, + "sections": [ + {"name": "Warmup", "target_minutes": 10, "must_keywords": [], "forbid_keywords": [], "capability_targets": {}} + ], + "goals": [], + "equipment_allowed": [], + "created_by": "tester", + "version": "1.0" + } + r1 = requests.post(f"{BASE}/plan_templates", json=tpl) + assert r1.status_code == 200, r1.text + + # 2) Plan minimal + plan = { + "template_id": r1.json()["id"], + "title": "Session‑Plan", + "discipline": "Karate", + "age_group": "Erwachsene", + "target_group": "Breitensport", + "total_minutes": 60, + "sections": [ + {"name": "Warmup", "minutes": 10, "items": []} + ], + "goals": [], + "capability_summary": {}, + "created_by": "tester", + "created_at": datetime.now(timezone.utc).isoformat(), + "source": "test" + } + r2 = requests.post(f"{BASE}/plan", json=plan) + assert r2.status_code == 200, r2.text + plan_id = r2.json()["id"] + + # 3) Session anlegen + session = { + "plan_id": plan_id, + "executed_at": datetime.now(timezone.utc).isoformat(), + "location": "Dojo A", + "coach": "Sensei K.", + "group_label": "Montag 18:00", + "feedback": {"rating": 4, "notes": "Gute Energie, Warmup etwas zu kurz."}, + "used_equipment": [" Pratzen ", "Bälle", "pratzen"] + } + r3 = requests.post(f"{BASE}/plan_sessions", json=session) + assert r3.status_code == 200, r3.text + sess_id = r3.json()["id"] + + # 4) Session lesen & Normalisierung prüfen + r4 = requests.get(f"{BASE}/plan_sessions/{sess_id}") + assert r4.status_code == 200 + js = r4.json() + # used_equipment dedupliziert/trimmed/casefolded → len == 2 + assert len(js["used_equipment"]) == 2 + assert "Pratzen" in js["used_equipment"] or "pratzen" in [x.lower() for x in js["used_equipment"]] + + +def test_plan_session_invalid_rating(): + # Minimaler Plan für Referenz + tpl = { + "name": "Std 45 for sessions", + "discipline": "Karate", + "age_group": "Erwachsene", + "target_group": "Breitensport", + "total_minutes": 45, + "sections": [ + {"name": "Warmup", "target_minutes": 10, "must_keywords": [], "forbid_keywords": [], "capability_targets": {}} + ], + "goals": [], + "equipment_allowed": [], + "created_by": "tester", + "version": "1.0" + } + r1 = requests.post(f"{BASE}/plan_templates", json=tpl) + assert r1.status_code == 200 + plan = { + "template_id": r1.json()["id"], + "title": "Fehlerfall", + "discipline": "Karate", + "age_group": "Erwachsene", + "target_group": "Breitensport", + "total_minutes": 45, + "sections": [ + {"name": "Warmup", "minutes": 10, "items": []} + ], + "goals": [], + "capability_summary": {}, + "created_by": "tester", + "created_at": datetime.now(timezone.utc).isoformat(), + "source": "test" + } + r2 = requests.post(f"{BASE}/plan", json=plan) + assert r2.status_code == 200 + + bad_session = { + "plan_id": r2.json()["id"], + "executed_at": datetime.now(timezone.utc).isoformat(), + "location": "Dojo B", + "coach": "Assist.", + "group_label": "Dienstag 19:00", + "feedback": {"rating": 7, "notes": "invalid"}, # ungültig (1..5) + "used_equipment": [] + } + r_bad = requests.post(f"{BASE}/plan_sessions", json=bad_session) + assert r_bad.status_code == 422 \ No newline at end of file