#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Listen-/Filter-Tests für Templates & Pläne (v0.1.0).""" import os import requests from datetime import datetime, timezone, timedelta BASE = os.getenv("BASE_URL", "http://127.0.0.1:8000").rstrip("/") def test_list_plan_templates_filters(): # Zwei Templates anlegen (unterschiedliche Sections/Goals) tpl1 = { "name": "ListTpl A", "discipline": "Karate", "age_group": "Teenager", "target_group": "Breitensport", "total_minutes": 60, "sections": [{"name": "Warmup", "target_minutes": 10, "must_keywords": ["Reaktion"], "forbid_keywords": [], "ideal_keywords": ["Koordination"], "supplement_keywords": [], "capability_targets": {}}], "goals": ["Technik"], "equipment_allowed": [], "created_by": "tester", "version": "1.0" } tpl2 = { "name": "ListTpl B", "discipline": "Karate", "age_group": "Erwachsene", "target_group": "Breitensport", "total_minutes": 60, "sections": [{"name": "Technikblock", "target_minutes": 30, "must_keywords": ["Mae-Geri"], "forbid_keywords": [], "ideal_keywords": ["Timing"], "supplement_keywords": ["Partnerarbeit"], "capability_targets": {}}], "goals": ["Kondition"], "equipment_allowed": [], "created_by": "tester", "version": "1.0" } r1 = requests.post(f"{BASE}/plan_templates", json=tpl1); assert r1.status_code == 200 r2 = requests.post(f"{BASE}/plan_templates", json=tpl2); assert r2.status_code == 200 # Filter: discipline=Karate & section=Warmup → sollte tpl1 enthalten r = requests.get(f"{BASE}/plan_templates", params={"discipline": "Karate", "section": "Warmup", "limit": 10, "offset": 0}) assert r.status_code == 200, r.text js = r.json(); assert js["count"] >= 1 assert any(tpl["name"] == "ListTpl A" for tpl in js["items"]) # Filter: keyword=Timing → sollte tpl2 treffen (ideal_keywords) r = requests.get(f"{BASE}/plan_templates", params={"keyword": "Timing"}) assert r.status_code == 200 js = r.json(); names = [t["name"] for t in js["items"]] assert "ListTpl B" in names def test_list_plans_filters_and_window(): # Plan A (Teenager), Plan B (Erwachsene) base_tpl = { "name": "ListTpl PlanBase", "discipline": "Karate", "age_group": "Teenager", "target_group": "Breitensport", "total_minutes": 45, "sections": [{"name": "Warmup", "target_minutes": 10, "must_keywords": [], "forbid_keywords": [], "capability_targets": {}}], "goals": ["Technik"], "equipment_allowed": [], "created_by": "tester", "version": "1.0" } rt = requests.post(f"{BASE}/plan_templates", json=base_tpl); assert rt.status_code == 200 tpl_id = rt.json()["id"] now = datetime.now(timezone.utc) plan_a = { "template_id": tpl_id, "title": "List Plan A", "discipline": "Karate", "age_group": "Teenager", "target_group": "Breitensport", "total_minutes": 45, "sections": [{"name": "Warmup", "minutes": 10, "items": []}], "goals": ["Technik"], "capability_summary": {}, "created_by": "tester", "created_at": now.isoformat(), "source": "test" } plan_b = { "template_id": tpl_id, "title": "List Plan B", "discipline": "Karate", "age_group": "Erwachsene", "target_group": "Breitensport", "total_minutes": 45, "sections": [{"name": "Technikblock", "minutes": 30, "items": []}], "goals": ["Kondition"], "capability_summary": {}, "created_by": "tester", "created_at": (now + timedelta(seconds=1)).isoformat(), "source": "test" } ra = requests.post(f"{BASE}/plan", json=plan_a); assert ra.status_code == 200 rb = requests.post(f"{BASE}/plan", json=plan_b); assert rb.status_code == 200 # Filter: age_group=Teenager & section=Warmup → sollte Plan A enthalten r = requests.get(f"{BASE}/plans", params={"age_group": "Teenager", "section": "Warmup"}) assert r.status_code == 200 js = r.json(); assert js["count"] >= 1 assert any(p["title"] == "List Plan A" for p in js["items"]) # Zeitfenster: created_from nach Plan A → sollte Plan B enthalten r = requests.get(f"{BASE}/plans", params={"created_from": (now + timedelta(milliseconds=500)).isoformat()}) assert r.status_code == 200 js = r.json(); titles = [p["title"] for p in js["items"]] assert "List Plan B" in titles