#!/usr/bin/env python3 """S2 test: Agents frontend pages — /agents and /agent/ routes.""" import json, sys, subprocess BASE = "http://127.0.0.1:5001" passed = 0 failed = 0 def curl(path, method="GET", data=None): cmd = ["curl", "-s", "-w", "\n%{http_code}", f"{BASE}{path}"] if method == "POST" and data: cmd = ["curl", "-s", "-w", "\n%{http_code}", "-X", "POST", f"{BASE}{path}", "-H", "Content-Type: application/json", "-d", json.dumps(data)] r = subprocess.run(cmd, capture_output=True, text=True, timeout=15) parts = r.stdout.rsplit("\n", 1) body = parts[0] if len(parts) > 1 else r.stdout code = int(parts[1]) if len(parts) > 1 else 0 return code, body # TC1: GET /agents returns 200 + HTML contains "Agents" title + profile table code, html = curl("/agents") if code == 200 and "Agents" in html and "profile" in html.lower(): passed += 1 print(f" PASS GET /agents: HTTP {code}, has title + profile refs") else: failed += 1 print(f" FAIL GET /agents: HTTP {code}, title={('Agents' in html)}, profile={('profile' in html.lower())}") # TC2: /agents HTML has create button + delete confirm + chat modal code, html = curl("/agents") has_create = "create" in html.lower() or "新建" in html or "创建" in html has_confirm = "confirm" in html.lower() has_chat = "chat" in html.lower() or "消息" in html or "发消息" in html if has_create and has_confirm and has_chat: passed += 1 print(f" PASS /agents HTML: create={has_create} confirm={has_confirm} chat={has_chat}") else: failed += 1 print(f" FAIL /agents HTML: create={has_create} confirm={has_confirm} chat={has_chat}") # TC3: /agents HTML has no Jinja2 escaped quotes or backslash bugs code, html = curl("/agents") ok = True msgs = [] if 'style=\\' in html: ok = False; msgs.append("STYLE BACKSLASH BUG") if 'data-action=\\"' in html: ok = False; msgs.append("JINJA2 ESCAPED QUOTES") if ok: passed += 1 print(f" PASS /agents HTML: no escape bugs") else: failed += 1 print(f" FAIL /agents HTML: {'; '.join(msgs)}") # TC4: /agents HTML has default profile marker (◆ or similar) code, html = curl("/agents") if "default" in html: passed += 1 print(f" PASS /agents HTML: contains 'default' profile ref") else: failed += 1 print(f" FAIL /agents HTML: no 'default' profile ref found") # TC5: GET /agent/default returns 200 + SOUL.md content + skills list code, html = curl("/agent/default") if code == 200 and ("skill" in html.lower() or "SOUL" in html or "soul" in html.lower()): passed += 1 print(f" PASS GET /agent/default: HTTP {code}, has skill/soul refs") else: failed += 1 print(f" FAIL GET /agent/default: HTTP {code}, soul={('soul' in html.lower())}, skill={('skill' in html.lower())}") # TC6: /agent/default HTML has no escape bugs code, html = curl("/agent/default") ok = True msgs = [] if 'style=\\' in html: ok = False; msgs.append("STYLE BACKSLASH BUG") if 'data-action=\\"' in html: ok = False; msgs.append("JINJA2 ESCAPED QUOTES") if ok: passed += 1 print(f" PASS /agent/default HTML: no escape bugs") else: failed += 1 print(f" FAIL /agent/default HTML: {'; '.join(msgs)}") print(f"\n{passed}/{passed+failed} 通过") sys.exit(0 if failed == 0 else 1)