Files
boehmitools-training/plugins/trainingstracker/tests/test_app.py
T
2026-09-01 16:53:14 +02:00

176 lines
6.6 KiB
Python

from __future__ import annotations
import importlib.util
import json
import os
import uuid
from pathlib import Path
def load_module(module_path: Path, data_dir: Path, plans_dir: Path):
try:
import flask # noqa: F401
except ModuleNotFoundError:
import pytest
pytest.skip("Flask ist in dieser isolierten Testumgebung nicht installiert")
os.environ["TRAININGSTRACKER_DATA_DIR"] = str(data_dir)
os.environ["TRAININGSTRACKER_PLANS_DIR"] = str(plans_dir)
name = f"tracker_test_app_{uuid.uuid4().hex}"
spec = importlib.util.spec_from_file_location(name, module_path)
module = importlib.util.module_from_spec(spec)
assert spec.loader
spec.loader.exec_module(module)
return module
def sample_plan() -> dict:
return {
"name": "Testplan",
"revision": 4,
"published_revision": 4,
"config": {
"schema_version": 5,
"contract_version": 4,
"plan_id": "testplan",
"meta": {"title": "Testplan"},
"exercises": [
{
"id": "exercise-push",
"name": "Push-up-Progression",
"progressions": [
{"id": "progression-high-plank", "name": "High Plank"},
{"id": "progression-negative", "name": "Negative"},
],
"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-push"}],
},
{
"id": "day-2",
"num": 2,
"name": "Tag 2",
"warmup": {"items": []},
"cooldown": {"items": []},
"exercises": [{"id": "item-2", "exercise_id": "exercise-push"}],
}
],
},
"draft": {
"schema_version": 5,
"contract_version": 4,
"plan_id": "testplan",
"meta": {"title": "Testplan"},
"exercises": [
{
"id": "exercise-push",
"name": "Push-up-Progression",
"progressions": [
{"id": "progression-high-plank", "name": "High Plank"},
{"id": "progression-negative", "name": "Negative"},
],
"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-push"}],
},
{
"id": "day-2",
"num": 2,
"name": "Tag 2",
"warmup": {"items": []},
"cooldown": {"items": []},
"exercises": [{"id": "item-2", "exercise_id": "exercise-push"}],
}
],
},
}
def test_lists_only_training_plans_and_returns_slim_detail(tmp_path: Path):
plans = tmp_path / "data" / "trainingsplan" / "plans"
data_dir = tmp_path / "data" / "trainingstracker"
plans.mkdir(parents=True)
(plans / "training.json").write_text(json.dumps(sample_plan()), encoding="utf-8")
(plans / "food.json").write_text(json.dumps({"name": "Essen", "config": {"type": "recipe", "days": []}}), encoding="utf-8")
module = load_module(Path(__file__).parents[1] / "app.py", data_dir, plans)
client = module.app.test_client()
listed = client.get("/api/plans").get_json()
assert [item["id"] for item in listed["plans"]] == ["training.json"]
detail = client.get("/api/plans/training.json").get_json()
cfg = detail["plan"]["config"]
assert cfg["schema_version"] == 5
assert cfg["contract_version"] == 4
assert cfg["days"][0]["exercises"][0]["exercise"]["current_progression"]["name"] == "High Plank"
def test_current_progression_update_writes_config_and_draft(tmp_path: Path):
plans = tmp_path / "data" / "trainingsplan" / "plans"
data_dir = tmp_path / "data" / "trainingstracker"
plans.mkdir(parents=True)
plan_file = plans / "training.json"
plan_file.write_text(json.dumps(sample_plan()), encoding="utf-8")
module = load_module(Path(__file__).parents[1] / "app.py", data_dir, plans)
client = module.app.test_client()
response = client.patch(
"/api/plans/training.json/exercises/exercise-push/current",
json={"current_progression_id": "progression-negative"},
)
assert response.status_code == 200
payload = response.get_json()
exercise = payload["plan"]["config"]["exercises"][0]
assert exercise["current_progression_id"] == "progression-negative"
day_progressions = [
item["exercise"]["current_progression"]["id"]
for day in payload["plan"]["config"]["days"]
for item in day["exercises"]
]
assert day_progressions == ["progression-negative", "progression-negative"]
saved = json.loads(plan_file.read_text(encoding="utf-8"))
assert saved["config"]["exercises"][0]["current_progression_id"] == "progression-negative"
assert saved["draft"]["exercises"][0]["current_progression_id"] == "progression-negative"
assert saved["revision"] == 5
assert saved["published_revision"] == 5
def test_frontend_no_longer_contains_session_or_analysis_surfaces():
source = (Path(__file__).parents[1] / "static" / "index.html").read_text(encoding="utf-8")
assert "data-current-progression" in source
assert "analysis/status" not in source
assert "sessionView" not in source
assert "week" not in source.lower()
def test_frontend_embeds_plugin_mount_path(tmp_path: Path):
plans = tmp_path / "data" / "trainingsplan" / "plans"
data_dir = tmp_path / "data" / "trainingstracker"
plans.mkdir(parents=True)
(plans / "training.json").write_text(json.dumps(sample_plan()), encoding="utf-8")
module = load_module(Path(__file__).parents[1] / "app.py", data_dir, plans)
client = module.app.test_client()
html = client.get("/", environ_overrides={"SCRIPT_NAME": "/plugins/trainingstracker"}).get_data(as_text=True)
assert 'data-base="/plugins/trainingstracker"' in html