Files
sapl/docs/scripts/smoke_test_pert.py
T

81 lines
3.2 KiB
Python

"""Smoke test — PERT chart endpoint and data quality."""
import sys, requests, urllib.parse
sys.stdout.reconfigure(encoding='utf-8')
BASE = "http://localhost:8000/api/tna"
checks = []
def check(label, ok, detail=""):
checks.append((label, ok, detail))
print(f" [{'PASS' if ok else 'FAIL'}] {label}" + (f" — {detail}" if detail else ""))
# Get orders first
r = requests.get(f"{BASE}/orders")
orders = r.json().get("orders", [])
check("Orders available", len(orders) > 0, f"{len(orders)} orders")
for order in orders:
style = order["style_number"]
encoded = urllib.parse.quote(style, safe='')
r = requests.get(f"{BASE}/orders/{encoded}/pert")
check(f"PERT endpoint 200 for {style[:20]}", r.status_code == 200, str(r.status_code))
if r.status_code != 200:
continue
data = r.json()
# Structure checks
check("PERT has nodes array", isinstance(data.get("nodes"), list), f"{len(data.get('nodes',[]))} nodes")
check("PERT has edges array", isinstance(data.get("edges"), list), f"{len(data.get('edges',[]))} edges")
check("PERT has critical_path_ids", isinstance(data.get("critical_path_ids"), list))
check("PERT has days_to_pcd", "days_to_pcd" in data, str(data.get("days_to_pcd")))
check("PERT has track_y_positions", isinstance(data.get("track_y_positions"), dict))
nodes = data.get("nodes", [])
check("At least 5 nodes", len(nodes) >= 5, f"{len(nodes)}")
if nodes:
n = nodes[0]
required_fields = ["id", "task_name", "sop_code", "track", "status",
"end_date", "delay_days", "float_days", "is_critical", "x", "y"]
check("Node has all required fields", all(f in n for f in required_fields),
str([f for f in required_fields if f not in n]))
check("Node x > 0", n["x"] > 0, f"x={n['x']}")
check("Node y > 0", n["y"] > 0, f"y={n['y']}")
check("Node status is valid", n["status"] in ("RED","AMBER","GREEN","DONE","PENDING"),
n["status"])
edges = data.get("edges", [])
if edges:
e = edges[0]
check("Edge has id, source, target", all(f in e for f in ["id","source","target"]))
node_ids = {n["id"] for n in nodes}
orphan = [e for e in edges if e["source"] not in node_ids or e["target"] not in node_ids]
check("No orphan edges (source/target in nodes)", len(orphan) == 0,
f"{len(orphan)} orphans: {orphan[:2]}")
cp = data.get("critical_path_ids", [])
check("Critical path has nodes", len(cp) > 0, f"path={cp}")
check("Critical path nodes are in node list", all(n in {n['id'] for n in nodes} for n in cp),
f"path={cp}")
# Check critical nodes are marked
crit_nodes = [n for n in nodes if n["is_critical"]]
check("At least 1 critical node", len(crit_nodes) > 0, f"{len(crit_nodes)} critical")
# Frontend
r = requests.get("http://localhost:5173/tna")
check("Frontend /tna still loads", r.status_code == 200)
passed = sum(1 for _, ok, _ in checks if ok)
failed = sum(1 for _, ok, _ in checks if not ok)
print(f"\n{passed} PASS / {failed} FAIL")
if failed == 0:
print("\nPERT Chart: PASS")
sys.exit(0)
else:
print("\nPERT Chart: FAIL")
sys.exit(1)