from pathlib import Path ROOT = Path(__file__).resolve().parents[1] def read(path: str) -> str: return (ROOT / path).read_text(encoding="utf-8") def test_v472_page_modules_exist(): for module in [ "dashboard", "operations", "opportunities", "tasks", "customers", "products", "orders", "finance", "integrations", "communications", "outbox", "events", "runs", "queues", "conversations", "system", ]: path = ROOT / "app" / "admin_ui" / "pages" / f"{module}.py" assert path.exists(), f"missing {path}" content = path.read_text(encoding="utf-8") assert "router = APIRouter()" in content def test_v472_router_aggregates_domain_modules(): router = read("app/admin_ui/router.py") assert "route registration is split by domain" in router.lower() for module in [ "dashboard", "operations", "opportunities", "tasks", "customers", "products", "orders", "finance", "integrations", "communications", "outbox", "events", "runs", "queues", "system", ]: assert f"from app.admin_ui.pages import {module}" in router assert f"router.include_router({module}.router)" in router def test_v472_routes_are_no_longer_registered_in_admin_dashboard(): dashboard = read("app/admin_dashboard.py") assert "Route handlers moved to app.admin_ui.pages.* in v4.7.2" in dashboard assert dashboard.count("@router.get(") <= 1 # /ui.css compatibility endpoint only assert "@router.get(\"/operations\"" not in dashboard assert "@router.get(\"/tasks\"" not in dashboard assert "@router.get(\"/opportunities\"" not in dashboard admin_lines = dashboard.count("\n") + 1 # Architectural guard: route handlers must remain outside this compatibility # module. The small allowance covers physical-status safety and UI helpers. assert admin_lines < 1850 def test_v472_domain_modules_own_expected_routes(): assert "@router.get(\"/operations\"" in read("app/admin_ui/pages/operations.py") assert "@router.get(\"/operacoes\"" in read("app/admin_ui/pages/operations.py") assert "@router.get(\"/opportunities\"" in read("app/admin_ui/pages/opportunities.py") assert "@router.post(\"/opportunities/{opportunity_id}/stage\"" in read("app/admin_ui/pages/opportunities.py") assert "@router.get(\"/tasks\"" in read("app/admin_ui/pages/tasks.py") assert "@router.post(\"/tasks/{task_id}/complete\"" in read("app/admin_ui/pages/tasks.py") assert "@router.get(\"/outbox\"" in read("app/admin_ui/pages/outbox.py") assert "@router.get(\"/system/health\"" in read("app/admin_ui/pages/system.py") def test_v472_documentation_exists_and_states_no_db_migration(): doc = read("docs/CLIENTFLOW_V472_DOMAIN_ROUTES.md") assert "Rotas por domínio" in doc assert "Não requer migração de base de dados" in doc