feat(icon): Notion-style icon picker + custom workspace emojis; fix side peek file content & ctx menu overflow
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Failing after 3h6m55s
FlowDeck CI / docker (push) Skipped

This commit is contained in:
2026-09-12 20:05:53 -04:00
parent 19e8ba0e4a
commit da3e09c215
16 changed files with 766 additions and 53 deletions
+72 -1
View File
@@ -484,12 +484,27 @@ class TestCoverIcon:
page = _page(client, cookie, csrf, "Icon long")
r = client.post(
f"/board/api/pages/{page}/icon",
json={"icon": "x" * 32},
json={"icon": "x" * 600},
headers={"Content-Type": "application/json", **_cookie_headers(cookie, csrf)},
cookies={"flowdeck_session": cookie},
)
assert r.status_code == 400
def test_custom_emoji_url_accepted_as_icon(self, client):
cookie, csrf = _login(client)
_workspace(client, cookie)
page = _page(client, cookie, csrf, "Custom icon")
url = "/api/files/1/emoji_123_cat.png"
r = client.post(
f"/board/api/pages/{page}/icon",
json={"icon": url},
headers={"Content-Type": "application/json", **_cookie_headers(cookie, csrf)},
cookies={"flowdeck_session": cookie},
)
assert r.status_code == 200
r2 = client.get(f"/board/api/pages/{page}", cookies={"flowdeck_session": cookie})
assert r2.json()["page_icon"] == url
def test_public_page_renders_cover_and_icon(self, client):
cookie, csrf = _login(client)
_workspace(client, cookie)
@@ -543,3 +558,59 @@ class TestEditorEndpointPaths:
assert "fetch('/api/pages/'+this.pid+'/versions" not in tpl
assert "fetch('/api/pages/'+this.pid+'/backlinks" not in tpl
assert "fetch('/api/og/metadata" not in tpl
# ══════════════════════════════════════════════════════════════════════════
# v5.6.0: custom workspace emojis
# ══════════════════════════════════════════════════════════════════════════
class TestCustomEmojis:
def test_list_empty(self, client):
cookie, _ = _login(client)
_workspace(client, cookie)
r = client.get("/api/custom-emojis", cookies={"flowdeck_session": cookie})
assert r.status_code == 200
assert r.json()["emojis"] == []
def test_upload_and_delete(self, client):
cookie, csrf = _login(client)
_workspace(client, cookie)
png = b"\x89PNG\r\n\x1a\n" + b"0" * 16
r = client.post(
"/api/custom-emojis",
data={"name": "pushup"},
files={"file": ("pushup.png", png, "image/png")},
headers=_cookie_headers(cookie, csrf),
cookies={"flowdeck_session": cookie},
)
assert r.status_code == 200
emoji = r.json()["emoji"]
assert emoji["name"] == "pushup"
assert emoji["url"].startswith("/api/files/")
listed = client.get("/api/custom-emojis", cookies={"flowdeck_session": cookie}).json()["emojis"]
assert any(e["id"] == emoji["id"] for e in listed)
d = client.request(
"DELETE",
f"/api/custom-emojis/{emoji['id']}",
headers=_cookie_headers(cookie, csrf),
cookies={"flowdeck_session": cookie},
)
assert d.status_code == 200
after = client.get("/api/custom-emojis", cookies={"flowdeck_session": cookie}).json()["emojis"]
assert all(e["id"] != emoji["id"] for e in after)
def test_reject_non_image(self, client):
cookie, csrf = _login(client)
_workspace(client, cookie)
r = client.post(
"/api/custom-emojis",
data={"name": "bad"},
files={"file": ("evil.sh", b"#!/bin/sh", "text/plain")},
headers=_cookie_headers(cookie, csrf),
cookies={"flowdeck_session": cookie},
)
assert r.status_code == 400