193 lines
7.8 KiB
Python
193 lines
7.8 KiB
Python
#!/usr/bin/env python3
|
|
"""API-Test fuer Einstellungen + Auto-Reset (offener Modus).
|
|
|
|
Lauf: python3 tests/test_api_settings.py
|
|
"""
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import urllib.request
|
|
import urllib.error
|
|
|
|
BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
STATE = "/tmp/tp_state2"
|
|
PORT = 8255
|
|
BASE_URL = f"http://127.0.0.1:{PORT}"
|
|
|
|
PASS = 0
|
|
FAIL = 0
|
|
|
|
|
|
def check(name, cond, detail=""):
|
|
global PASS, FAIL
|
|
if cond:
|
|
PASS += 1
|
|
print(f" ok {name}")
|
|
else:
|
|
FAIL += 1
|
|
print(f"FAIL {name} {detail}")
|
|
|
|
|
|
def req(method, path, body=None):
|
|
url = BASE_URL + path
|
|
data = None
|
|
headers = {}
|
|
if body is not None:
|
|
data = json.dumps(body).encode("utf-8")
|
|
headers["Content-Type"] = "application/json"
|
|
r = urllib.request.Request(url, data=data, headers=headers, method=method)
|
|
try:
|
|
with urllib.request.urlopen(r, timeout=5) as resp:
|
|
return resp.status, json.loads(resp.read().decode("utf-8"))
|
|
except urllib.error.HTTPError as e:
|
|
try:
|
|
return e.code, json.loads(e.read().decode("utf-8"))
|
|
except Exception:
|
|
return e.code, {}
|
|
|
|
|
|
def main():
|
|
if os.path.exists(STATE):
|
|
shutil.rmtree(STATE)
|
|
os.makedirs(STATE, exist_ok=True)
|
|
env = dict(os.environ, TRAINING_STATE_DIR=STATE, PORT=str(PORT))
|
|
proc = subprocess.Popen(
|
|
[sys.executable, os.path.join(BASE, "server.py")],
|
|
env=env, cwd=BASE,
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
try:
|
|
for _ in range(40):
|
|
time.sleep(0.25)
|
|
try:
|
|
urllib.request.urlopen(BASE_URL + "/api/meta", timeout=1)
|
|
break
|
|
except Exception:
|
|
pass
|
|
else:
|
|
print("Server nicht erreichbar")
|
|
sys.exit(1)
|
|
|
|
st, s = req("GET", "/api/settings")
|
|
check("Settings Defaults", st == 200
|
|
and s["theme"] == "dark" and s["accent"] == "white"
|
|
and s["autoReset"] is False and s["showTips"] is True, s)
|
|
|
|
st, s = req("PUT", "/api/settings",
|
|
{"theme": "light", "accent": "green",
|
|
"autoReset": True, "showTips": False})
|
|
check("Settings speichern", st == 200 and s["theme"] == "light"
|
|
and s["accent"] == "green" and s["autoReset"] is True
|
|
and s["showTips"] is False, s)
|
|
st, s = req("GET", "/api/settings")
|
|
check("Settings persistiert", s["theme"] == "light"
|
|
and s["autoReset"] is True and s["showTips"] is False, s)
|
|
|
|
st, s = req("PUT", "/api/settings", {"autoReset": False})
|
|
check("Teil-Update", s["autoReset"] is False
|
|
and s["theme"] == "light", s)
|
|
req("PUT", "/api/settings", {"autoReset": True, "showTips": True})
|
|
|
|
ex = "Push/Bankdrücken KH (je Hand)"
|
|
st, done = req("POST", "/api/sessions",
|
|
{"activity": "gym", "day": "Push"})
|
|
did = done["id"]
|
|
sets = []
|
|
for i, w in enumerate(["18", "18,5", "20", ""]):
|
|
sets.append({"exercise": ex, "sort": i, "weight": w,
|
|
"reps": "10", "done": 1 if i < 3 else 0})
|
|
req("PATCH", f"/api/sessions/{did}", {"sets": sets})
|
|
req("PATCH", f"/api/sessions/{did}", {"meta": {"status": "done"}})
|
|
|
|
req("PUT", "/api/settings", {"autoReset": False})
|
|
st, s1 = req("POST", "/api/sessions", {"activity": "gym", "day": "Push"})
|
|
check("AutoReset OFF: keine vorbefuellten Sets",
|
|
len(s1["entries"]) == 0, s1["entries"])
|
|
req("DELETE", f"/api/sessions/{s1['id']}")
|
|
|
|
req("PUT", "/api/settings", {"autoReset": True})
|
|
st, s2 = req("POST", "/api/sessions", {"activity": "gym", "day": "Push"})
|
|
entries = s2["entries"]
|
|
check("AutoReset ON: nur 3 gefuellte Sets geladen",
|
|
len(entries) == 3, entries)
|
|
check("AutoReset ON: Gewichte uebernommen",
|
|
[e["weight"] for e in entries] == ["18", "18,5", "20"],
|
|
[e["weight"] for e in entries])
|
|
check("AutoReset ON: Abhak-Status zurueckgesetzt",
|
|
all(e["done"] == 0 for e in entries), entries)
|
|
check("AutoReset ON: Reps uebernommen",
|
|
all(e["reps"] == "10" for e in entries), entries)
|
|
|
|
new_sets = [{"exercise": ex, "sort": 0, "weight": "999", "reps": "1",
|
|
"done": 0}]
|
|
req("PATCH", f"/api/sessions/{s2['id']}", {"sets": new_sets})
|
|
st, filled = req("POST", f"/api/sessions/{s2['id']}/autofill")
|
|
check("Autofill: Saetze ersetzt", st == 200
|
|
and len(filled["entries"]) == 3
|
|
and filled["entries"][0]["weight"] == "18", filled["entries"])
|
|
|
|
exB = "Push/Schrägbank KH (je Hand)"
|
|
req("PATCH", f"/api/sessions/{s2['id']}",
|
|
{"sets": [{"exercise": exB, "sort": 0, "weight": "14", "reps": "12",
|
|
"done": 0}]})
|
|
st, filled = req("POST", f"/api/sessions/{s2['id']}/autofill")
|
|
b = [e for e in filled["entries"] if e["exercise"] == exB]
|
|
check("Autofill: Uebung ohne Verlauf unberuehrt",
|
|
b and b[0]["weight"] == "14", filled["entries"])
|
|
|
|
req("PUT", "/api/settings",
|
|
{"autoReset": "ja", "showTips": 1, "bogus": 42, "theme": "oled"})
|
|
st, s = req("GET", "/api/settings")
|
|
check("Typen + unbekannte Keys", s["autoReset"] is True
|
|
and s["showTips"] is True and "bogus" not in s
|
|
and s["theme"] == "oled", s)
|
|
|
|
# --- Plan-Gewichte vorbefuellen ------------------------------------
|
|
req("PUT", "/api/settings", {"autoReset": False, "planPrefill": True})
|
|
st, s3 = req("POST", "/api/sessions", {"activity": "gym", "day": "Push"})
|
|
bd = [e for e in s3["entries"] if e["exercise"] == "Push/Bankdrücken KH (je Hand)"]
|
|
check("PlanPrefill: alle Plan-Saetze mit startKg",
|
|
len(bd) == 4 and all(e["weight"] == "18" for e in bd), bd)
|
|
check("PlanPrefill: alle Uebungen des Tags befuellt",
|
|
len({e["exercise"] for e in s3["entries"]}) == 8,
|
|
len(s3["entries"]))
|
|
check("PlanPrefill: Reps leer, done=0",
|
|
all(e["reps"] == "" and e["done"] == 0 for e in s3["entries"]),
|
|
s3["entries"])
|
|
req("DELETE", f"/api/sessions/{s3['id']}")
|
|
# Auto-Reset hat Vorrang vor Plan-Gewichten (je Uebung)
|
|
req("PUT", "/api/settings", {"autoReset": True, "planPrefill": True})
|
|
st, s4 = req("POST", "/api/sessions", {"activity": "gym", "day": "Push"})
|
|
bd4 = [e for e in s4["entries"] if e["exercise"] == "Push/Bankdrücken KH (je Hand)"]
|
|
sb4 = [e for e in s4["entries"] if e["exercise"] == "Push/Schrägbank KH (je Hand)"]
|
|
check("PlanPrefill+AutoReset: letztes Workout gewinnt",
|
|
len(bd4) == 3
|
|
and [e["weight"] for e in bd4] == ["18", "18,5", "20"], bd4)
|
|
check("PlanPrefill+AutoReset: ohne Verlauf Plan-Gewicht",
|
|
len(sb4) == 3 and all(e["weight"] == "14" for e in sb4), sb4)
|
|
req("DELETE", f"/api/sessions/{s4['id']}")
|
|
|
|
req("PUT", "/api/settings",
|
|
{"theme": "dark", "oled": False, "accent": "white",
|
|
"autoReset": False, "planPrefill": False, "showTips": True,
|
|
"language": "de", "setupDone": False, "onboarded": False,
|
|
"weightUnit": "kg", "startTab": "today"})
|
|
st, s = req("GET", "/api/settings")
|
|
check("Zurueck auf Standard", s == {
|
|
"theme": "dark", "oled": False, "accent": "white",
|
|
"autoReset": False, "planPrefill": False, "showTips": True,
|
|
"language": "de", "setupDone": False, "onboarded": False,
|
|
"weightUnit": "kg", "startTab": "today"}, s)
|
|
|
|
finally:
|
|
proc.terminate()
|
|
proc.wait(timeout=5)
|
|
|
|
print(f"\n{PASS} ok, {FAIL} fail")
|
|
sys.exit(1 if FAIL else 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |