Files
ObsiGate/tests/test_excalidraw.py
T
bruno 1b5319fde1
CI / lint (push) Failing after 9s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 13s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled
feat(excalidraw): support complet des fichiers .excalidraw (#78)
- Backend: ajout .excalidraw dans SUPPORTED_EXTENSIONS + squelette JSON creation
- Backend: détection is_excalidraw dans api_file() + FileContentResponse
- Frontend: icône pen-tool dans EXT_ICONS
- Frontend: ajout dans la modale de création (ui.js)
- Frontend: excalidraw-editor.html (iframe autonome, React+Excalidraw via esm.sh)
- Frontend: excalidraw-viewer.js (postMessage, auto-save 2s, thème)
- Frontend: dispatch dans viewer.js (renderFile)
- Tests: 6 tests (détection, création squelette, fallback, tree, roundtrip)
- 359/359 tests passent
2026-07-29 10:55:00 -04:00

167 lines
6.3 KiB
Python

"""Tests for Excalidraw file support in ObsiGate."""
import json
EXCALIDRAW_SKELETON = {
"type": "excalidraw",
"version": 2,
"elements": [],
"appState": {"viewBackgroundColor": "#ffffff"},
"files": {},
}
EXCALIDRAW_WITH_CONTENT = {
"type": "excalidraw",
"version": 2,
"elements": [
{
"id": "rect-1",
"type": "rectangle",
"x": 100, "y": 200, "width": 300, "height": 150,
"angle": 0, "strokeColor": "#1e1e1e",
"backgroundColor": "#ffec99", "fillStyle": "solid",
"strokeWidth": 2, "strokeStyle": "solid",
"roughness": 1, "opacity": 100, "groupIds": [],
"roundness": {"type": 3},
"boundElements": None, "updated": 1,
"link": None, "locked": False,
},
{
"id": "text-1", "type": "text",
"x": 150, "y": 260, "width": 200, "height": 30,
"angle": 0, "strokeColor": "#1e1e1e",
"backgroundColor": "transparent", "fillStyle": "solid",
"strokeWidth": 2, "strokeStyle": "solid",
"roughness": 1, "opacity": 100, "groupIds": [],
"roundness": None, "boundElements": None,
"updated": 1, "link": None, "locked": False,
"text": "Hello Excalidraw", "fontSize": 20,
"fontFamily": 1, "textAlign": "center",
"verticalAlign": "middle", "containerId": "rect-1",
"originalText": "Hello Excalidraw",
"autoResize": True, "lineHeight": 1.25,
},
],
"appState": {"viewBackgroundColor": "#ffffff", "name": "My Diagram"},
"files": {},
}
class TestExcalidrawDetection:
"""Test that the /api/file endpoint correctly detects .excalidraw files."""
VAULT = "TestVault"
def test_valid_excalidraw_file(self, client):
"""A valid .excalidraw file should return is_excalidraw: true."""
path = "diagram.excalidraw"
resp = client.post(
f"/api/file/{self.VAULT}",
json={"path": path, "content": json.dumps(EXCALIDRAW_WITH_CONTENT)},
)
assert resp.status_code == 200, resp.text
resp = client.get(f"/api/file/{self.VAULT}", params={"path": path})
assert resp.status_code == 200, resp.text
data = resp.json()
assert data["is_excalidraw"] is True
assert "excalidraw_data" in data
assert len(data["excalidraw_data"]["elements"]) == 2
assert data["excalidraw_data"]["elements"][0]["type"] == "rectangle"
assert data["title"] == "My Diagram"
def test_empty_excalidraw_creation(self, client):
"""Creating a .excalidraw with empty content injects skeleton JSON."""
path = "empty.excalidraw"
resp = client.post(
f"/api/file/{self.VAULT}",
json={"path": path, "content": ""},
)
assert resp.status_code == 200, resp.text
resp = client.get(f"/api/file/{self.VAULT}", params={"path": path})
assert resp.status_code == 200, resp.text
data = resp.json()
assert data["is_excalidraw"] is True
assert data["excalidraw_data"]["elements"] == []
assert data["excalidraw_data"]["appState"]["viewBackgroundColor"] == "#ffffff"
def test_invalid_json_excalidraw_fallback(self, client):
"""A .excalidraw with invalid JSON should show as text, not Excalidraw."""
path = "corrupt.excalidraw"
resp = client.post(
f"/api/file/{self.VAULT}",
json={"path": path, "content": "this is not valid json!!!"},
)
assert resp.status_code == 200, resp.text
resp = client.get(f"/api/file/{self.VAULT}", params={"path": path})
assert resp.status_code == 200, resp.text
data = resp.json()
assert not data.get("is_excalidraw")
def test_json_without_excalidraw_type(self, client):
"""A .excalidraw with valid JSON but wrong type falls through."""
path = "not-excalidraw.excalidraw"
resp = client.post(
f"/api/file/{self.VAULT}",
json={"path": path, "content": '{"type":"something-else","data":[1,2,3]}'},
)
assert resp.status_code == 200, resp.text
resp = client.get(f"/api/file/{self.VAULT}", params={"path": path})
assert resp.status_code == 200, resp.text
data = resp.json()
assert not data.get("is_excalidraw")
def test_excalidraw_in_tree(self, client):
"""A .excalidraw file appears in the file tree."""
path = "tree-diagram.excalidraw"
resp = client.post(
f"/api/file/{self.VAULT}",
json={"path": path, "content": json.dumps(EXCALIDRAW_SKELETON)},
)
assert resp.status_code == 200, resp.text
resp = client.get(f"/api/browse/{self.VAULT}", params={"path": ""})
assert resp.status_code == 200, resp.text
items = resp.json()["items"]
names = [i["name"] for i in items]
assert "tree-diagram.excalidraw" in names, f"Not found in: {names}"
def test_excalidraw_save_roundtrip(self, client):
"""Create, edit (PUT), and re-read an .excalidraw file."""
path = "roundtrip.excalidraw"
client.post(
f"/api/file/{self.VAULT}",
json={"path": path, "content": ""},
)
modified = dict(EXCALIDRAW_SKELETON)
modified["elements"] = [{
"id": "ellipse-1", "type": "ellipse",
"x": 50, "y": 50, "width": 100, "height": 80,
"angle": 0, "strokeColor": "#1e1e1e",
"backgroundColor": "#a5d8ff", "fillStyle": "solid",
"strokeWidth": 2, "strokeStyle": "solid",
"roughness": 1, "opacity": 100, "groupIds": [],
"roundness": {"type": 2},
"boundElements": None, "updated": 1,
"link": None, "locked": False,
}]
resp = client.put(
f"/api/file/{self.VAULT}/save",
params={"path": path, "backup": "false"},
json={"content": json.dumps(modified)},
)
assert resp.status_code == 200, resp.text
resp = client.get(f"/api/file/{self.VAULT}", params={"path": path})
assert resp.status_code == 200, resp.text
data = resp.json()
assert data["is_excalidraw"] is True
assert len(data["excalidraw_data"]["elements"]) == 1
assert data["excalidraw_data"]["elements"][0]["type"] == "ellipse"