Adds complete super_admin panel with 9 pages and account owner categories page. Backend includes 5 new DB tables, ~25 API endpoints, settings manager with in-memory cache, and 29 integration tests. Frontend includes reusable admin components (DataTable, Pagination, ActionMenu, etc.) with code-split lazy loading. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
77 lines
2.6 KiB
Python
77 lines
2.6 KiB
Python
"""Integration tests for admin audit log endpoints."""
|
|
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
|
|
class TestAdminAuditLogs:
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_audit_logs(
|
|
self, client: AsyncClient, admin_auth_headers: dict, test_user: dict
|
|
):
|
|
"""List audit logs with pagination."""
|
|
# Generate some audit activity first (e.g., admin listing users creates no audit,
|
|
# but we can create a tree to generate audit data)
|
|
response = await client.get(
|
|
"/api/v1/admin/audit-logs", headers=admin_auth_headers
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "items" in data
|
|
assert "total" in data
|
|
assert "page" in data
|
|
assert "per_page" in data
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_filter_audit_logs_by_action(
|
|
self, client: AsyncClient, admin_auth_headers: dict
|
|
):
|
|
"""Filter audit logs by action."""
|
|
response = await client.get(
|
|
"/api/v1/admin/audit-logs?action=tree.create",
|
|
headers=admin_auth_headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_filter_audit_logs_by_resource_type(
|
|
self, client: AsyncClient, admin_auth_headers: dict
|
|
):
|
|
"""Filter audit logs by resource_type."""
|
|
response = await client.get(
|
|
"/api/v1/admin/audit-logs?resource_type=tree",
|
|
headers=admin_auth_headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_filter_audit_logs_by_date_range(
|
|
self, client: AsyncClient, admin_auth_headers: dict
|
|
):
|
|
"""Filter audit logs by date range."""
|
|
response = await client.get(
|
|
"/api/v1/admin/audit-logs?date_from=2020-01-01T00:00:00Z&date_to=2030-12-31T23:59:59Z",
|
|
headers=admin_auth_headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_export_audit_logs_csv(
|
|
self, client: AsyncClient, admin_auth_headers: dict
|
|
):
|
|
"""Export audit logs as CSV."""
|
|
response = await client.get(
|
|
"/api/v1/admin/audit-logs/export", headers=admin_auth_headers
|
|
)
|
|
assert response.status_code == 200
|
|
assert "text/csv" in response.headers.get("content-type", "")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_non_admin_cannot_access(
|
|
self, client: AsyncClient, auth_headers: dict
|
|
):
|
|
"""Non-admin gets 403."""
|
|
response = await client.get("/api/v1/admin/audit-logs", headers=auth_headers)
|
|
assert response.status_code == 403
|