- app/services/plugins.py + migration 35 : table plugins (slug, name,
description, enabled) pré-remplie avec 3 modules câblés — web-tools,
web-clipper, automations ; ligne absente = activé (défaut sûr)
- automations OFF → dépendance FastAPI posée à l'include_router dans main.py
(aucun router touché) → toutes les routes /workspace/automations* refusées +
garde de tick du scheduler en arrière-plan
- web-clipper OFF → GET /extensions et tout /api/v2/web-clipper/* refusés
- web-tools OFF → web_search et fetch_url retirés du schéma ET de execute()
via ToolRegistry._all() : le LLM ne les voit plus
- UI rendue côté serveur : global Jinja plugin_enabled(slug) — nav
« Extensions » / « Automations » en {% if %} (absentes du DOM), sections
conditionnées en x-show dans settings.html
- menu + : l'entrée « Add plugins » devient vivante (fini disabled:true) —
liste des 3 plugins avec bascule, GET/PATCH /api/agent/plugins[/slug]
(slug inconnu → 404, 401 sans session)
- tests : tests/test_v758_plugins.py (10 tests) — routes refusées (302 hors
/api, 404 JSON pour /api*), outils retirés, nav disparue, persistance,
câblage ; assertions disabled:true == 0 dans les tests des phases 1/3/4/5/7
- livraison : VERSION + app/main = 7.58.0, OpenAPI 525 chemins, CHANGELOG,
ROADMAP phase 8 cochée (menu + complet), avenant phase 8 (docs)
73 lines
3.0 KiB
Python
73 lines
3.0 KiB
Python
"""v7.53.0 — Menu + : Design System – Canevas (créer / insérer / enregistrer)."""
|
||
|
||
import json
|
||
from pathlib import Path
|
||
|
||
from app.db import get_conn
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
JS_PATH = ROOT / "static" / "js" / "agent_panel_2.js"
|
||
|
||
|
||
def test_canvases_list_includes_design_system(client):
|
||
tpl = {t["key"]: t for t in client.get("/board/api/page-templates").json()["templates"] if t.get("builtin")}
|
||
assert "design_system" in tpl
|
||
assert tpl["design_system"]["name"] == "Design System"
|
||
assert tpl["design_system"]["icon"] == "🎨"
|
||
|
||
|
||
def test_blocks_route_builtin(client):
|
||
r = client.get("/board/api/page-templates/0/blocks", params={"key": "design_system"})
|
||
assert r.status_code == 200, r.text
|
||
blocks = r.json()["blocks"]
|
||
assert isinstance(blocks, list) and blocks
|
||
assert blocks[0]["type"] == "heading_1" and blocks[0]["content"] == "Design System"
|
||
# les builtins sont livrés sans id : le front appelle ensureBlockIds()
|
||
assert "id" not in blocks[0]
|
||
|
||
assert client.get("/board/api/page-templates/0/blocks", params={"key": "nope"}).status_code == 404
|
||
empty = client.get("/board/api/page-templates/0/blocks", params={"key": "empty"})
|
||
assert empty.status_code == 200 and empty.json()["blocks"]
|
||
|
||
|
||
def test_blocks_route_user_template(client):
|
||
blocks = [{"type": "heading_1", "content": "Mon canevas"},
|
||
{"type": "paragraph", "content": "Contenu."}]
|
||
created = client.post("/board/api/page-templates", json={"name": "Mon canevas", "blocks": blocks})
|
||
assert created.status_code == 200, created.text
|
||
tid = created.json()["id"]
|
||
|
||
got = client.get(f"/board/api/page-templates/{tid}/blocks")
|
||
assert got.status_code == 200
|
||
assert [b["content"] for b in got.json()["blocks"]] == ["Mon canevas", "Contenu."]
|
||
|
||
assert client.get("/board/api/page-templates/999999/blocks").status_code == 404
|
||
|
||
|
||
def test_use_design_system_creates_page(client):
|
||
r = client.post("/board/api/page-templates/0/use", json={"key": "design_system"})
|
||
assert r.status_code == 200, r.text
|
||
page_id = r.json()["id"]
|
||
with get_conn() as conn:
|
||
row = conn.execute(
|
||
"SELECT content, content_format FROM pages WHERE id=?", (page_id,)
|
||
).fetchone()
|
||
assert row["content_format"] == "blocks"
|
||
blocks = json.loads(row["content"])
|
||
texts = [b.get("content", "") for b in blocks]
|
||
assert "Design System" in texts
|
||
# les ids sont assignés côté serveur (_ensure_block_ids)
|
||
assert all(b.get("id") for b in blocks)
|
||
|
||
|
||
def test_canvases_menu_wired(client):
|
||
src = JS_PATH.read_text(encoding="utf-8")
|
||
root = src.split("var FD_PLUS_MENU = [", 1)[1].split("];", 1)[0]
|
||
assert "action:'canvases'" in root
|
||
assert root.count("disabled:true") == 0 # v7.58.0 : menu complet
|
||
for action in ("'canvas'", "'canvas-create'", "'canvas-insert'", "'canvas-save'"):
|
||
assert action in src, action
|
||
# piège /use : la clé builtin part DANS LE BODY, pas en query string
|
||
assert "body: JSON.stringify(c.builtin ? {key: c.key} : {})" in src
|
||
assert "ensureBlockIds" in src
|