Files
the-other-dude/backend/tests/unit/test_audit_service.py
Jason Staack 06a41ca9bf fix(lint): resolve all ruff lint errors
Add ruff config to exclude alembic E402, SQLAlchemy F821, and pre-existing
E501 line-length issues. Auto-fix 69 unused imports and 2 f-strings without
placeholders. Manually fix 8 unused variables. Apply ruff format to 127 files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 22:17:50 -05:00

89 lines
2.4 KiB
Python

"""Unit tests for the audit service and model.
Tests cover:
- AuditLog model can be imported
- log_action function signature is correct
- Audit logs router is importable with expected endpoints
- CSV export endpoint exists
"""
import uuid
from unittest.mock import AsyncMock
import pytest
class TestAuditLogModel:
"""Tests for the AuditLog ORM model."""
def test_model_importable(self):
from app.models.audit_log import AuditLog
assert AuditLog.__tablename__ == "audit_logs"
def test_model_has_required_columns(self):
from app.models.audit_log import AuditLog
mapper = AuditLog.__table__.columns
expected_columns = {
"id",
"tenant_id",
"user_id",
"action",
"resource_type",
"resource_id",
"device_id",
"details",
"ip_address",
"created_at",
}
actual_columns = {c.name for c in mapper}
assert expected_columns.issubset(actual_columns), (
f"Missing columns: {expected_columns - actual_columns}"
)
def test_model_exported_from_init(self):
from app.models import AuditLog
assert AuditLog.__tablename__ == "audit_logs"
class TestAuditService:
"""Tests for the audit service log_action function."""
def test_log_action_importable(self):
from app.services.audit_service import log_action
assert callable(log_action)
@pytest.mark.asyncio
async def test_log_action_does_not_raise_on_db_error(self):
"""log_action must swallow exceptions so it never breaks the caller."""
from app.services.audit_service import log_action
mock_db = AsyncMock()
mock_db.execute = AsyncMock(side_effect=Exception("DB down"))
# Should NOT raise even though the DB call fails
await log_action(
db=mock_db,
tenant_id=uuid.uuid4(),
user_id=uuid.uuid4(),
action="test_action",
)
class TestAuditRouter:
"""Tests for the audit logs router."""
def test_router_importable(self):
from app.routers.audit_logs import router
assert router is not None
def test_router_has_audit_logs_endpoint(self):
from app.routers.audit_logs import router
paths = [route.path for route in router.routes]
assert "/audit-logs" in paths or any("/audit-logs" in p for p in paths)