feat: Fusion bloc 1 — barre d'apps commune (ACC-1.1, #17) et références croisées external_ref (ACC-1.3, #18)
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
"""Références croisées ``external_ref`` — Fusion ACC-1.3 (Flowdeck).
|
||||
|
||||
Vérifie le parseur d'URL profondes (contrat figé dracodev-commons), le
|
||||
cycle API sur une page et sur un projet (collection), les refus
|
||||
(422/404/401) et la route profonde ``/collections/{id}`` du contrat
|
||||
ACC-0.1 (redirection vers la vue native ``/db/{id}``).
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from app.db import get_conn
|
||||
from app.services.external_refs import parse_deep_link
|
||||
|
||||
# ── Parseur d'URL profondes ─────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.parametrize("url,attendu", [
|
||||
("https://tiktak.dracodev.net/?task=42", ("tiktak", "task", "42")),
|
||||
("https://tiktak.dracodev.net/?list=3", ("tiktak", "list", "3")),
|
||||
("https://og.dracodev.net/#file=Perso:Notes/Idée.md",
|
||||
("obsigate", "note", "Perso:Notes/Idée.md")),
|
||||
("https://flowdeck.dracodev.net/pages/7", ("flowdeck", "page", "7")),
|
||||
("https://flowdeck.dracodev.net/collections/9", ("flowdeck", "project", "9")),
|
||||
("https://git.dracodev.net/Projets/ticktick-clone/issues/213",
|
||||
("kanbante", "card", "Projets/ticktick-clone#213")),
|
||||
])
|
||||
def test_parse_formes_reconnues(url, attendu):
|
||||
parsed = parse_deep_link(url)
|
||||
assert parsed is not None
|
||||
assert parsed[:3] == attendu
|
||||
|
||||
|
||||
@pytest.mark.parametrize("url", [
|
||||
"https://tiktak.dracodev.net/autre?x=1",
|
||||
"https://og.dracodev.net/#recherche",
|
||||
"https://flowdeck.dracodev.net/tableau",
|
||||
"https://example.com/pages/1",
|
||||
"pas une url",
|
||||
"",
|
||||
])
|
||||
def test_parse_formes_refusees(url):
|
||||
assert parse_deep_link(url) is None
|
||||
|
||||
|
||||
# ── Fixtures d'objets ───────────────────────────────────────────────────
|
||||
|
||||
def _creer_page() -> int:
|
||||
with get_conn() as conn:
|
||||
cur = conn.execute(
|
||||
"INSERT INTO pages (workspace, title) VALUES ('bruno/flowdeck', 'Page Fusion')"
|
||||
)
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
|
||||
|
||||
def _creer_collection() -> int:
|
||||
with get_conn() as conn:
|
||||
cur = conn.execute("INSERT INTO collections (name) VALUES ('Projet Fusion')")
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
|
||||
|
||||
# ── API sur une page ────────────────────────────────────────────────────
|
||||
|
||||
def test_cycle_refs_page(client):
|
||||
pid = _creer_page()
|
||||
r = client.post(f"/api/pages/{pid}/refs",
|
||||
json={"url": "https://tiktak.dracodev.net/?task=42"})
|
||||
assert r.status_code == 201, r.text
|
||||
ref = r.json()
|
||||
assert ref["target_app"] == "tiktak" and ref["target_id"] == "42"
|
||||
assert ref["label"] == "TikTak · tâche 42"
|
||||
assert ref["app_color"] == "#e8762c"
|
||||
|
||||
r = client.post(f"/api/pages/{pid}/refs",
|
||||
json={"url": "https://og.dracodev.net/#file=Perso:A.md",
|
||||
"label": "Note liée"})
|
||||
assert r.status_code == 201, r.text
|
||||
|
||||
r = client.get(f"/api/pages/{pid}/refs")
|
||||
assert r.status_code == 200
|
||||
assert [x["target_app"] for x in r.json()["refs"]] == ["tiktak", "obsigate"]
|
||||
assert r.json()["refs"][1]["label"] == "Note liée"
|
||||
|
||||
r = client.delete(f"/api/refs/{ref['id']}")
|
||||
assert r.status_code == 200
|
||||
r = client.get(f"/api/pages/{pid}/refs")
|
||||
assert [x["target_app"] for x in r.json()["refs"]] == ["obsigate"]
|
||||
|
||||
|
||||
def test_ref_url_inconnue_422(client):
|
||||
pid = _creer_page()
|
||||
r = client.post(f"/api/pages/{pid}/refs", json={"url": "https://example.com/x"})
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
def test_delete_ref_inconnue_404(client):
|
||||
r = client.delete("/api/refs/999999")
|
||||
assert r.status_code == 404
|
||||
|
||||
|
||||
def test_refs_anonyme_401(client):
|
||||
from tests.conftest import anon
|
||||
pid = _creer_page()
|
||||
r = anon(client).get(f"/api/pages/{pid}/refs")
|
||||
assert r.status_code == 401
|
||||
|
||||
|
||||
# ── API sur un projet (collection) + route profonde ─────────────────────
|
||||
|
||||
def test_cycle_refs_collection(client):
|
||||
cid = _creer_collection()
|
||||
r = client.post(f"/api/collections/{cid}/refs",
|
||||
json={"url": "https://git.dracodev.net/Projets/fusion/issues/5"})
|
||||
assert r.status_code == 201, r.text
|
||||
assert r.json()["target_app"] == "kanbante"
|
||||
r = client.get(f"/api/collections/{cid}/refs")
|
||||
assert len(r.json()["refs"]) == 1
|
||||
|
||||
|
||||
def test_route_profonde_collection(client):
|
||||
cid = _creer_collection()
|
||||
r = client.get(f"/collections/{cid}", follow_redirects=False)
|
||||
assert r.status_code == 303
|
||||
assert r.headers["location"] == f"/db/{cid}"
|
||||
r = client.get("/collections/999999", follow_redirects=False)
|
||||
assert r.status_code == 404
|
||||
Reference in New Issue
Block a user