- Add quick capture input to topbar (desktop: inline 250px, mobile: full-width with submit button) that POSTs to /capture/add with redirect back to current page - Fix mobile bottom bar: 5 items (Dashboard, Focus, Tasks, Capture, More), nowrap/overflow:hidden to prevent multi-line wrapping - Rebuild mobile More panel as 3-column grid overlay (z-index 998/999/1000 stack) with backdrop dismiss, 8 items: Calendar, Notes, Meetings, Decisions, Contacts, Processes, Weblinks, Admin - Add file seed fixture and registry mapping to eliminate 4 test skips - Add time_budgets form factory patterns to fix 2 test failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
"""
|
|
Route registry - imports app, runs introspection once, exposes route data.
|
|
Disposes the async engine after introspection to avoid event loop conflicts.
|
|
"""
|
|
import os
|
|
import asyncio
|
|
|
|
# Point the app at the test database BEFORE importing
|
|
os.environ["DATABASE_URL"] = "postgresql+asyncpg://postgres:UCTOQDZiUhN8U@lifeos-db:5432/lifeos_test"
|
|
|
|
from main import app
|
|
from tests.introspect import introspect_app
|
|
|
|
# Build route registry from live app
|
|
ROUTE_REGISTRY = introspect_app(app)
|
|
ALL_ROUTES = ROUTE_REGISTRY # Alias used by test_crud_dynamic.py
|
|
|
|
# Classify routes into buckets for parametrized tests
|
|
GET_NO_PARAMS = [r for r in ROUTE_REGISTRY if "GET" in r.methods and not r.path_params]
|
|
GET_WITH_PARAMS = [r for r in ROUTE_REGISTRY if "GET" in r.methods and r.path_params]
|
|
POST_CREATE = [r for r in ROUTE_REGISTRY if "POST" in r.methods and r.kind == "create"]
|
|
POST_EDIT = [r for r in ROUTE_REGISTRY if "POST" in r.methods and r.kind == "edit"]
|
|
POST_DELETE = [r for r in ROUTE_REGISTRY if "POST" in r.methods and r.kind == "delete"]
|
|
POST_ACTION = [r for r in ROUTE_REGISTRY if "POST" in r.methods and r.kind in ("action", "toggle")]
|
|
|
|
# Map route prefixes to seed fixture keys
|
|
PREFIX_TO_SEED = {
|
|
"/domains": "domain",
|
|
"/areas": "area",
|
|
"/projects": "project",
|
|
"/tasks": "task",
|
|
"/notes": "note",
|
|
"/links": "link",
|
|
"/contacts": "contact",
|
|
"/lists": "list",
|
|
"/meetings": "meeting",
|
|
"/decisions": "decision",
|
|
"/weblinks": "weblink",
|
|
"/weblinks/folders": "weblink_folder",
|
|
"/appointments": "appointment",
|
|
"/focus": "focus",
|
|
"/capture": "capture",
|
|
"/time": "task",
|
|
"/processes": "process",
|
|
"/processes/runs": "process_run",
|
|
"/time-budgets": "time_budget",
|
|
"/files": "file",
|
|
"/admin/trash": None,
|
|
}
|
|
|
|
def resolve_path(path_template, seeds):
|
|
"""Replace {id} placeholders with real seed UUIDs."""
|
|
import re
|
|
result = path_template
|
|
for param in re.findall(r"\{(\w+)\}", path_template):
|
|
# Find prefix for this route
|
|
for prefix, seed_key in sorted(PREFIX_TO_SEED.items(), key=lambda x: -len(x[0])):
|
|
if path_template.startswith(prefix) and seed_key and seed_key in seeds:
|
|
result = result.replace(f"{{{param}}}", str(seeds[seed_key]))
|
|
break
|
|
return result
|
|
|
|
# Note: Engine disposal is handled by the _reinit_engine fixture in conftest.py.
|
|
# It runs within the test event loop, ensuring the pool is recreated correctly.
|