""" FlowDeck — Audit fonctionnel de bout-en-bout. Base SQLite isolée (init schéma) + TestClient FastAPI réel. Vérifie status code + payload de chaque processus métier. """ import os, tempfile, json, sys from pathlib import Path _tmp = tempfile.mkdtemp(prefix="fd_audit_") os.environ["DATABASE_URL"] = f"sqlite:///{_tmp}/audit.db" os.environ["APP_SECRET_KEY"] = "audit-secret-0000" os.environ["RATE_LIMIT_ENABLED"] = "false" os.environ["BACKUP_ENABLED"] = "false" os.environ["FLOWDECK_DATA_DIR"] = _tmp os.environ["PROJECT_SYNC_ENABLED"] = "false" os.environ["PROJECT_SYNC"] = "false" sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from fastapi.testclient import TestClient from app.main import app from app.db import init_db init_db() client = TestClient(app) results = [] def csrf(): return client.get("/api/csrf-token").json().get("token", "") def h(c): return {"X-CSRF-Token": c, "Content-Type": "application/json"} def register_login(email="audit@flowdeck.local", pwd="secret123"): c = csrf() client.post("/auth/register", json={"name": "Audit", "email": email, "password": pwd}, headers=h(c)) c2 = csrf() r = client.post("/auth/local-login", json={"email": email, "password": pwd}, headers=h(c2)) return c2 def rec(name, ok, detail=""): results.append((name, ok, detail)) print(f"{'PASS' if ok else 'FAIL'} {name}" + (f" — {detail}" if detail else "")) print("="*72) print("FLOWDECK — AUDIT FONCTIONNEL (base isolée)") print("="*72) try: # ── 1. AUTH & WORKSPACE ─────────────────────────────── c = register_login() me = client.get("/api/users/me").json() rec("register + login user local", me.get("login") == "audit@flowdeck.local" or me.get("email") == "audit@flowdeck.local", f"login={me.get('login')} admin={me.get('is_admin')}") r = client.post("/api/workspaces", json={"name": "Audit WS"}, headers=h(c)) rec("POST /api/workspaces", r.status_code in (200, 201, 302), f"HTTP {r.status_code} {str(r.text)[:70]}") # ── 2. CRÉATION NOTE ────────────────────────────────── r = client.post("/api/pages", json={"workspace": "Audit WS", "title": "Note de test", "content": "## MD init", "content_format": "markdown"}, headers=h(c)) pid = r.json().get("id") if r.status_code in (200, 201) else None rec("POST /api/pages (création note)", pid is not None, f"HTTP {r.status_code} body={str(r.text)[:60]}") # ── 3. CRÉATION BASE DE DONNÉES (collection) ────────── r = client.post("/db/api", json={"name": "Tâches", "schema": [{"name":"Statut","prop_type":"select","options":["À faire","En cours","Fait"]}]}, headers=h(c)) coll = r.json() cid = coll.get("id") rec("POST /db/api (création DB)", cid is not None, f"HTTP {r.status_code} id={cid}") # ── 4. TÂCHES (rows) ────────────────────────────────── if cid: r = client.post(f"/db/{cid}/pages/api", json={"title": "Terminer audit", "property_values_json": json.dumps({"Statut":"En cours"})}, headers=h(c)) rec("POST /{cid}/pages (création row)", r.status_code in (200, 201, 200), f"HTTP {r.status_code} {str(r.text)[:70]}") # ── 5. (Kanban board-config testé via instance Gitea réelle — cf. audit live) ── # ── 6. SHARE / PUBLISH ──────────────────────────────── if pid: r = client.post(f"/api/pages/{pid}/share", json={"email":"other@x.com","permission":"edit"}, headers=h(c)) rec("POST /pages/{id}/share", r.status_code in (200, 201), f"HTTP {r.status_code} {str(r.text)[:70]}") r = client.post(f"/api/pages/{pid}/publish", json={}, headers=h(c)) rec("POST /pages/{id}/publish", r.status_code in (200, 201), f"HTTP {r.status_code} {str(r.text)[:70]}") # ── 7. EXPORT ───────────────────────────────────────── if pid: r = client.get(f"/api/export/markdown/{pid}") rec("GET /api/export/markdown", r.status_code == 200, f"HTTP {r.status_code} len={len(r.content)}") # ── 8. RECHERCHE ────────────────────────────────────── r = client.get("/api/search", params={"q": "audit"}) rec("GET /api/search?q=", r.status_code == 200, f"HTTP {r.status_code}") # ── 9. AGENTS ───────────────────────────────────────── r = client.get("/api/agent") rec("GET /api/agent (agents)", r.status_code == 200, f"HTTP {r.status_code}") except Exception as e: import traceback traceback.print_exc() rec("EXÉCUTION SCRIPT", False, str(e)[:100]) print("="*72) ok = sum(1 for _, o, _ in results if o) print(f"RÉSULTAT: {ok}/{len(results)} processus OK")