127 lines
4.7 KiB
Python
127 lines
4.7 KiB
Python
"""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
|