feat(v1.3.0): Step 3 — Router /db avec API CRUD collections + pages
- Nouveau router app/routers/collections.py - GET/POST/PUT/DELETE /db pour les collections - POST/GET/PUT/DELETE pour les pages dans une collection - Vue HTML basique par collection + vue par défaut auto-créée - CSRF exempté pour /db/ - 5 nouveaux tests (collections list, CRUD, pages CRUD, validation, HTML render) - 33/33 tests passent
This commit is contained in:
+128
-1
@@ -1,4 +1,5 @@
|
||||
"""FlowDeck — Comprehensive tests v1.0.0."""
|
||||
"""FlowDeck — Comprehensive tests v1.3.0."""
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import pytest
|
||||
@@ -220,3 +221,129 @@ def test_all_view_endpoints_respond(client):
|
||||
for view in views:
|
||||
resp = client.get(f"/board/test/test/view/{view}")
|
||||
assert resp.status_code in (200, 500), f"View {view} failed with {resp.status_code}"
|
||||
|
||||
|
||||
# ── v1.3.0: Database Concept ──
|
||||
|
||||
def test_collections_api_list_empty(client):
|
||||
"""List collections API — should return empty when no collections exist."""
|
||||
resp = client.get("/db/api")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "collections" in data
|
||||
assert data["collections"] == []
|
||||
|
||||
|
||||
def test_collections_api_crud(client):
|
||||
"""Full CRUD lifecycle: create → read → update → delete."""
|
||||
# Create
|
||||
resp = client.post("/db/api", json={
|
||||
"name": "Test Database",
|
||||
"description": "A test collection",
|
||||
"icon": "🗂️",
|
||||
"schema": [
|
||||
{"name": "Status", "type": "select", "options": ["Todo", "Done"]},
|
||||
],
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
created = resp.json()
|
||||
assert created["status"] == "created"
|
||||
assert "id" in created
|
||||
coll_id = created["id"]
|
||||
|
||||
# List — should now have 1 collection
|
||||
resp = client.get("/db/api")
|
||||
assert resp.status_code == 200
|
||||
assert len(resp.json()["collections"]) == 1
|
||||
|
||||
# Get single
|
||||
resp = client.get(f"/db/{coll_id}/api")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["collection"]["name"] == "Test Database"
|
||||
assert data["collection"]["icon"] == "🗂️"
|
||||
|
||||
# Update
|
||||
resp = client.put(f"/db/api/{coll_id}", json={
|
||||
"name": "Updated DB",
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["status"] == "updated"
|
||||
|
||||
# Verify update
|
||||
resp = client.get(f"/db/{coll_id}/api")
|
||||
assert resp.json()["collection"]["name"] == "Updated DB"
|
||||
|
||||
# Delete
|
||||
resp = client.delete(f"/db/api/{coll_id}")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["status"] == "deleted"
|
||||
|
||||
# Verify deletion
|
||||
resp = client.get(f"/db/{coll_id}/api")
|
||||
assert resp.status_code == 404
|
||||
|
||||
|
||||
def test_collections_pages_crud(client):
|
||||
"""CRUD for pages inside a collection."""
|
||||
# Create collection first
|
||||
resp = client.post("/db/api", json={"name": "Page Test DB"})
|
||||
coll_id = resp.json()["id"]
|
||||
|
||||
# Create page
|
||||
resp = client.post(f"/db/{coll_id}/pages/api", json={
|
||||
"title": "My First Page",
|
||||
"properties": {"Status": "Todo", "Priority": "P1"},
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
page_data = resp.json()
|
||||
assert page_data["status"] == "created"
|
||||
page_id = page_data["id"]
|
||||
|
||||
# Get page
|
||||
resp = client.get(f"/db/pages/{page_id}/api")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["title"] == "My First Page"
|
||||
|
||||
# Update page
|
||||
resp = client.put(f"/db/pages/{page_id}/api", json={
|
||||
"title": "Updated Page",
|
||||
"properties": {"Status": "Done"},
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
|
||||
# Verify update
|
||||
resp = client.get(f"/db/pages/{page_id}/api")
|
||||
data = resp.json()
|
||||
assert data["title"] == "Updated Page"
|
||||
props = json.loads(data["property_values_json"])
|
||||
assert props["Status"] == "Done"
|
||||
|
||||
# Delete page
|
||||
resp = client.delete(f"/db/pages/{page_id}/api")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["status"] == "deleted"
|
||||
|
||||
# Cleanup: delete collection
|
||||
client.delete(f"/db/api/{coll_id}")
|
||||
|
||||
|
||||
def test_collections_api_validation(client):
|
||||
"""Validation: missing name should return 400."""
|
||||
resp = client.post("/db/api", json={})
|
||||
assert resp.status_code == 400
|
||||
assert "name" in resp.json()["detail"].lower()
|
||||
|
||||
|
||||
def test_collections_db_page_renders(client):
|
||||
"""GET /db/{id} should render an HTML page."""
|
||||
# Create collection first
|
||||
resp = client.post("/db/api", json={"name": "Render Test"})
|
||||
coll_id = resp.json()["id"]
|
||||
|
||||
resp = client.get(f"/db/{coll_id}")
|
||||
assert resp.status_code == 200
|
||||
assert "Render Test" in resp.text
|
||||
|
||||
# Cleanup
|
||||
client.delete(f"/db/api/{coll_id}")
|
||||
|
||||
Reference in New Issue
Block a user