Files
2026-09-01 15:48:43 +02:00

171 lines
5.8 KiB
Python

from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parents[1]))
from schema_contract import migrate_training_config, validate_training_config
def legacy_config():
return {
"meta": {
"title": "Alter Plan",
"subtitle": "wird reduziert",
"output_name": "plan.pdf",
},
"colors": {"ACCENT": "#ff00ff"},
"training_format": {"mode": "tabata", "rounds": 8},
"phases": {"items": [{"name": "Phase 1"}]},
"stages": {"squat": {"name": "Squat", "steps": ["leicht", "schwer"]}},
"prepost": {
"1": {
"warmup": "Handgelenke · Kniebeugen",
"cooldown": "Atmen<br/>Locker gehen",
"stretch": "alte Dehnung",
}
},
"days": [
{
"num": 1,
"focus": "Beine",
"color": "#123456",
"rotations": [
{
"label": "Block A",
"exercises": [
{
"id": "old-placement",
"exercise_id": "exercise-squat",
"name": "Squat",
"key": "squat",
"cue": "tief",
"equipment": "Körpergewicht",
"description": "alter Beschreibungstext",
"sets": 3,
"reps": "8-12",
"duration_seconds": 30,
"result_schema": {"mode": "reps"},
}
],
}
],
}
],
}
def test_migration_flattens_legacy_plan_to_days_and_exercises():
migrated = migrate_training_config(legacy_config(), plan_id="test")
assert migrated["schema_version"] == 5
assert migrated["contract_version"] == 4
assert migrated["plan_id"] == "test"
assert "colors" not in migrated
assert "training_format" not in migrated
assert "phases" not in migrated
assert "stages" not in migrated
assert "exercise_catalog" not in migrated
assert migrated["meta"] == {"title": "Alter Plan", "subtitle": "wird reduziert"}
assert migrated["exercises"][0]["id"] == "exercise-squat"
assert migrated["exercises"][0]["name"] == "Squat"
assert [item["name"] for item in migrated["exercises"][0]["progressions"]] == ["leicht", "schwer"]
assert migrated["exercises"][0]["current_progression_id"] == migrated["exercises"][0]["progressions"][0]["id"]
day = migrated["days"][0]
assert day["name"] == "Beine"
assert day["warmup"]["items"] == ["Handgelenke", "Kniebeugen"]
assert day["cooldown"]["items"] == ["Atmen", "Locker gehen"]
assert "stretch" not in day
assert "rotations" not in day
assert "focus" not in day
assert "notes" not in day
item = day["exercises"][0]
assert item == {
"id": "old-placement",
"exercise_id": "exercise-squat",
}
def test_migration_is_stable_across_repeated_runs():
first = migrate_training_config(legacy_config(), plan_id="test")
second = migrate_training_config(first, plan_id="test")
assert first == second
def test_root_json_style_keys_create_one_exercise_with_stage_progressions():
cfg = {
"meta": {"title": "Root Import"},
"stages": {
"ls": {
"name": "Push-up-Progression",
"steps": [
{"name": "High Plank"},
{"name": "Negative"},
{"name": "Negative"},
{"name": "voll"},
],
}
},
"days": [
{
"num": 1,
"focus": "A",
"rotations": [{"exercises": [{"key": "ls", "name": "Push-up-Progression"}]}],
},
{
"num": 2,
"focus": "B",
"rotations": [{"exercises": [{"key": "ls", "name": "Push-up-Progression"}]}],
},
],
}
migrated = migrate_training_config(cfg, plan_id="root")
assert len(migrated["exercises"]) == 1
exercise = migrated["exercises"][0]
assert [item["name"] for item in exercise["progressions"]] == ["High Plank", "Negative", "voll"]
assert len(migrated["days"][0]["exercises"]) == 1
assert migrated["days"][0]["exercises"][0]["exercise_id"] == exercise["id"]
assert migrated["days"][1]["exercises"][0]["exercise_id"] == exercise["id"]
def test_validation_accepts_complete_minimal_plan():
cfg = {
"meta": {"title": "Minimal"},
"exercises": [{"id": "exercise-pushup", "name": "Push-up", "progressions": [{"id": "progression-high-plank", "name": "High Plank"}], "current_progression_id": "progression-high-plank"}],
"days": [
{
"id": "day-1",
"num": 1,
"name": "Tag 1",
"warmup": {"items": ["Mobilisieren"]},
"cooldown": {"items": ["Atmen"]},
"exercises": [{"id": "item-1", "exercise_id": "exercise-pushup"}],
}
],
}
assert validate_training_config(cfg)["errors"] == []
def test_validation_rejects_unknown_day_exercise_reference():
cfg = {
"meta": {"title": "Kaputt"},
"exercises": [{"id": "exercise-pushup", "name": "Push-up"}],
"days": [
{
"id": "day-1",
"num": 1,
"name": "Tag 1",
"exercises": [{"id": "item-1", "exercise_id": "missing"}],
}
],
}
errors = validate_training_config(cfg)["errors"]
assert [error["code"] for error in errors] == ["unknown_exercise"]