Files
flowdeck/tests/test_v7700_gitea_project_mirror.py
T
bruno fc8548194a
FlowDeck CI / lint (push) Failing after 1m32s
FlowDeck CI / test (push) Failing after 27m50s
FlowDeck CI / docker (push) Skipped
feat(templates): refonte complète des templates façon Notion + vues/agents-skills
Templates (v7.71.x) :

- registre unifié \	emplates\ (migrations 48-49) + TemplateService.instantiate unique (UI, API v2, agent, scheduler)

- sélecteur (pilule page vide, menu •••, commande /template), gestionnaire /templates, menu New ▾, From template, base inline dans un document

- 141 presets système (59 pages, 42 bases, 15 blocs, 25 lignes), titre auto depuis le template, variables title réservée

- récurrences RRULE + scheduler dédupliqué, agent apply_template/list_templates, API /api/templates + /api/v2/fd-templates

- correctifs : bouton Templates, centrage fenêtre, filtres CSP, flux de création, variable title

- tests : tests/test_fd_templates.py (19) et e2e/templates_picker.spec.js (8)

Inclut le travail déjà présent dans le working tree (vues Notion : view_query/view_aggregate/form_projection/geocoding, property_types, database_table, docs agents-skills) et ignore .playwright-mcp/.
2026-10-10 18:52:19 -04:00

104 lines
4.2 KiB
Python

"""FlowDeck v7.70.0 — Ouverture d'un projet Gitea : présentation + miroir local.
Régression couverte :
- ``GET /gitea-workspace?owner=&repo=`` crée le **workspace miroir local**
AVANT de calculer la sidebar : le premier affichage du projet ne montre plus
« No workspace open » (ou un ``localWsId: 0``) — équivalent local ouvert en
parallèle du dépôt distant ;
- le contexte projet est porté par l'URL : la sidebar résout le miroir même
sans cookie ``flowdeck_workspace`` (navigation directe / favori) ;
- ``GET /api/sidebar/workspace-tree`` rend l'arbre du **miroir** (et non plus le
placeholder « Remote workspace ») quand le cookie est ``gitea:owner:repo`` ;
- ``loadGiteaTree`` (base.html) cible ``#sidebar-gitea-items`` et n'écrase plus
l'arbre du workspace local de ``#sidebar-workspace-items``.
"""
from __future__ import annotations
import re
from app.db import get_conn
def _mirror_id(ws_key: str) -> int | None:
with get_conn() as conn:
row = conn.execute(
"SELECT id FROM workspaces WHERE name=? AND settings_json LIKE ?",
(ws_key, "%gitea_repo%"),
).fetchone()
return row["id"] if row else None
def _mk_mirror_page(ws_id: int, title: str) -> int:
with get_conn() as conn:
cur = conn.execute(
"INSERT INTO pages (workspace, workspace_id, title, content, content_format, parent_section) "
"VALUES ('', ?, ?, '', 'blocks', 'Private')",
(ws_id, title),
)
conn.commit()
return cur.lastrowid
def test_gitea_workspace_creates_and_shows_local_mirror(client):
"""Le premier GET crée le miroir et le sidebar pointe dessus (localWsId>0)."""
assert _mirror_id("acme/widget") is None
r = client.get("/gitea-workspace?owner=acme&repo=widget")
assert r.status_code == 200, r.text
ws_id = _mirror_id("acme/widget")
assert ws_id is not None, "le workspace miroir doit être créé"
# La sidebar expose l'ID du miroir (et non 0) dès le premier rendu.
m = re.search(r"localWsId:\s*(\d+)", r.text)
assert m, "localWsId introuvable dans la page"
assert int(m.group(1)) == ws_id, "la sidebar doit ouvrir l'équivalent local en parallèle"
assert "Open a workspace to see your files" not in r.text
assert "acme/widget" in r.text
def test_gitea_workspace_context_from_url_without_cookie(client):
"""Navigation directe (sans cookie) : le projet reste identifié par l'URL."""
r = client.get("/gitea-workspace?owner=acme&repo=gadget")
assert r.status_code == 200, r.text
ws_id = _mirror_id("acme/gadget")
assert ws_id is not None
m = re.search(r"localWsId:\s*(\d+)", r.text)
assert m and int(m.group(1)) == ws_id
# Pas de bandeau « aucune workspace ouverte » alors que le miroir existe.
assert "Open a workspace to see your files" not in r.text
def test_sidebar_workspace_tree_renders_gitea_mirror(client):
"""Le refresh sidebar ne remplace plus le miroir par « Remote workspace »."""
client.get("/gitea-workspace?owner=acme&repo=repo1")
ws_id = _mirror_id("acme/repo1")
assert ws_id is not None
_mk_mirror_page(ws_id, "Note miroir")
r = client.get(
"/api/sidebar/workspace-tree",
cookies={"flowdeck_workspace": "gitea:acme:repo1"},
)
assert r.status_code == 200, r.text
assert "Note miroir" in r.text
assert "Remote workspace" not in r.text
def test_sidebar_workspace_tree_gitea_without_mirror_is_empty_not_error(client):
r = client.get(
"/api/sidebar/workspace-tree",
cookies={"flowdeck_workspace": "gitea:ghost/none"},
)
assert r.status_code == 200
assert "Remote workspace" not in r.text
assert "No pages yet" in r.text
def test_loadgitea_tree_targets_repository_section():
"""Scan statique : loadGiteaTree ne doit pas cibler #sidebar-workspace-items."""
from pathlib import Path
html = (Path(__file__).resolve().parent.parent / "app" / "templates" / "base.html").read_text(
encoding="utf-8"
)
fn = html.split("loadGiteaTree() {", 1)[1].split("newPageInWorkspace()", 1)[0]
assert "getElementById('sidebar-gitea-items')" in fn
assert "getElementById('sidebar-workspace-items')" not in fn