108 lines
4.1 KiB
Python
108 lines
4.1 KiB
Python
|
|
"""Test for API Audit (Task 5.1) — verifies audit document exists and key endpoints are reachable."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import os
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from httpx import AsyncClient
|
||
|
|
|
||
|
|
from tests.conftest import ORIGIN_HEADER, login_client, seed_tenant_and_users
|
||
|
|
|
||
|
|
|
||
|
|
AUDIT_FILE = Path(__file__).parent.parent / "docs" / "api-audit.md"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_document_exists():
|
||
|
|
"""Audit document docs/api-audit.md exists and has content."""
|
||
|
|
assert AUDIT_FILE.exists(), f"API audit document not found at {AUDIT_FILE}"
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
assert len(content) > 1000, "API audit document is too short"
|
||
|
|
assert "# API Audit" in content, "Missing title"
|
||
|
|
assert "Summary" in content, "Missing summary section"
|
||
|
|
assert "Missing Endpoints" in content, "Missing missing endpoints section"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_covers_all_categories():
|
||
|
|
"""Audit document covers all major UI categories."""
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
required_categories = [
|
||
|
|
"Contacts",
|
||
|
|
"Calendar",
|
||
|
|
"DMS",
|
||
|
|
"Mail",
|
||
|
|
"Notifications",
|
||
|
|
"Workflows",
|
||
|
|
"Automation",
|
||
|
|
"AI Assistant",
|
||
|
|
"AI Proactive",
|
||
|
|
"Communication",
|
||
|
|
"Unified Search",
|
||
|
|
"Plugins",
|
||
|
|
"Settings",
|
||
|
|
"UI State",
|
||
|
|
]
|
||
|
|
for category in required_categories:
|
||
|
|
assert category in content, f"Missing category '{category}' in audit document"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_covers_user_preferences():
|
||
|
|
"""Audit document covers the user preferences API (Task 5.2)."""
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
assert "user/preferences" in content, "Missing user preferences endpoint in audit"
|
||
|
|
assert "sidebar" in content.lower(), "Missing sidebar state in audit"
|
||
|
|
assert "theme" in content.lower(), "Missing theme in audit"
|
||
|
|
assert "active_tab" in content or "active tab" in content.lower(), "Missing active tab in audit"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_covers_workflows():
|
||
|
|
"""Audit document covers the workflow API (Task 5.3)."""
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
assert "/api/v1/workflows" in content, "Missing workflow endpoint in audit"
|
||
|
|
assert "instances" in content, "Missing workflow instances in audit"
|
||
|
|
assert "advance" in content, "Missing workflow advance in audit"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_no_missing_endpoints():
|
||
|
|
"""Audit document reports zero missing endpoints."""
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
# Check that the summary shows 0 missing
|
||
|
|
assert "| 0 |" in content or "Missing Endpoints — None" in content, \
|
||
|
|
"Audit should report no missing endpoints"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_covers_rbac():
|
||
|
|
"""Audit document covers RBAC enforcement."""
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
assert "RBAC" in content, "Missing RBAC section in audit"
|
||
|
|
assert "require_permission" in content, "Missing require_permission mention in audit"
|
||
|
|
|
||
|
|
|
||
|
|
def test_api_audit_covers_frontend_modules():
|
||
|
|
"""Audit document maps frontend API modules to backend routes."""
|
||
|
|
content = AUDIT_FILE.read_text()
|
||
|
|
assert "Frontend API Module Coverage" in content, "Missing frontend module coverage section"
|
||
|
|
assert "api/workflows.ts" in content, "Missing workflows.ts in frontend coverage"
|
||
|
|
assert "api/userPreferences.ts" in content, "Missing userPreferences.ts in frontend coverage"
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_user_preferences_endpoint_reachable(client: AsyncClient, db_session):
|
||
|
|
"""Verify the user preferences API endpoint (from Task 5.2) is reachable — covers sidebar/tab/filter state."""
|
||
|
|
await seed_tenant_and_users(db_session)
|
||
|
|
await login_client(client, "admin@tenanta.com")
|
||
|
|
resp = await client.get("/api/v1/user/preferences", headers=ORIGIN_HEADER)
|
||
|
|
assert resp.status_code == 200
|
||
|
|
assert "preferences" in resp.json()
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_workflow_endpoints_reachable(client: AsyncClient, db_session):
|
||
|
|
"""Verify the workflow API endpoints (from Task 5.3) are reachable."""
|
||
|
|
await seed_tenant_and_users(db_session)
|
||
|
|
await login_client(client, "admin@tenanta.com")
|
||
|
|
resp = await client.get("/api/v1/workflows", headers=ORIGIN_HEADER)
|
||
|
|
assert resp.status_code == 200
|
||
|
|
assert "items" in resp.json()
|