From 123df8a48a15b81db435eecc616d562946f74b50 Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 13 Aug 2025 07:07:29 +0200 Subject: [PATCH] =?UTF-8?q?tests/test=5Fplan=5Flists=5Fwp15.py=20hinzugef?= =?UTF-8?q?=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_plan_lists_wp15.py | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/test_plan_lists_wp15.py diff --git a/tests/test_plan_lists_wp15.py b/tests/test_plan_lists_wp15.py new file mode 100644 index 0000000..dda30d7 --- /dev/null +++ b/tests/test_plan_lists_wp15.py @@ -0,0 +1,73 @@ +#!/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 \ No newline at end of file