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>
This commit is contained in:
@@ -8,7 +8,7 @@ Tests cover:
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -18,15 +18,24 @@ class TestAuditLogModel:
|
||||
|
||||
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",
|
||||
"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), (
|
||||
@@ -35,6 +44,7 @@ class TestAuditLogModel:
|
||||
|
||||
def test_model_exported_from_init(self):
|
||||
from app.models import AuditLog
|
||||
|
||||
assert AuditLog.__tablename__ == "audit_logs"
|
||||
|
||||
|
||||
@@ -43,6 +53,7 @@ class TestAuditService:
|
||||
|
||||
def test_log_action_importable(self):
|
||||
from app.services.audit_service import log_action
|
||||
|
||||
assert callable(log_action)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -67,9 +78,11 @@ class TestAuditRouter:
|
||||
|
||||
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)
|
||||
|
||||
@@ -11,7 +11,6 @@ These are pure function tests -- no database or async required.
|
||||
|
||||
import uuid
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
@@ -83,9 +82,7 @@ class TestAccessToken:
|
||||
assert payload["role"] == "super_admin"
|
||||
|
||||
def test_contains_expiry(self):
|
||||
token = create_access_token(
|
||||
user_id=uuid.uuid4(), tenant_id=uuid.uuid4(), role="viewer"
|
||||
)
|
||||
token = create_access_token(user_id=uuid.uuid4(), tenant_id=uuid.uuid4(), role="viewer")
|
||||
payload = verify_token(token, expected_type="access")
|
||||
assert "exp" in payload
|
||||
assert "iat" in payload
|
||||
|
||||
@@ -3,53 +3,65 @@
|
||||
Verifies STOR-01 (table/column structure) and STOR-05 (config_text stores ciphertext).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
|
||||
|
||||
def test_router_config_snapshot_importable():
|
||||
"""RouterConfigSnapshot can be imported from app.models."""
|
||||
from app.models import RouterConfigSnapshot
|
||||
|
||||
assert RouterConfigSnapshot is not None
|
||||
|
||||
|
||||
def test_router_config_diff_importable():
|
||||
"""RouterConfigDiff can be imported from app.models."""
|
||||
from app.models import RouterConfigDiff
|
||||
|
||||
assert RouterConfigDiff is not None
|
||||
|
||||
|
||||
def test_router_config_change_importable():
|
||||
"""RouterConfigChange can be imported from app.models."""
|
||||
from app.models import RouterConfigChange
|
||||
|
||||
assert RouterConfigChange is not None
|
||||
|
||||
|
||||
def test_snapshot_tablename():
|
||||
"""RouterConfigSnapshot.__tablename__ is correct."""
|
||||
from app.models import RouterConfigSnapshot
|
||||
|
||||
assert RouterConfigSnapshot.__tablename__ == "router_config_snapshots"
|
||||
|
||||
|
||||
def test_diff_tablename():
|
||||
"""RouterConfigDiff.__tablename__ is correct."""
|
||||
from app.models import RouterConfigDiff
|
||||
|
||||
assert RouterConfigDiff.__tablename__ == "router_config_diffs"
|
||||
|
||||
|
||||
def test_change_tablename():
|
||||
"""RouterConfigChange.__tablename__ is correct."""
|
||||
from app.models import RouterConfigChange
|
||||
|
||||
assert RouterConfigChange.__tablename__ == "router_config_changes"
|
||||
|
||||
|
||||
def test_snapshot_columns():
|
||||
"""RouterConfigSnapshot has all required columns."""
|
||||
from app.models import RouterConfigSnapshot
|
||||
|
||||
table = RouterConfigSnapshot.__table__
|
||||
expected = {"id", "device_id", "tenant_id", "config_text", "sha256_hash", "collected_at", "created_at"}
|
||||
expected = {
|
||||
"id",
|
||||
"device_id",
|
||||
"tenant_id",
|
||||
"config_text",
|
||||
"sha256_hash",
|
||||
"collected_at",
|
||||
"created_at",
|
||||
}
|
||||
actual = {c.name for c in table.columns}
|
||||
assert expected.issubset(actual), f"Missing columns: {expected - actual}"
|
||||
|
||||
@@ -57,10 +69,18 @@ def test_snapshot_columns():
|
||||
def test_diff_columns():
|
||||
"""RouterConfigDiff has all required columns."""
|
||||
from app.models import RouterConfigDiff
|
||||
|
||||
table = RouterConfigDiff.__table__
|
||||
expected = {
|
||||
"id", "device_id", "tenant_id", "old_snapshot_id", "new_snapshot_id",
|
||||
"diff_text", "lines_added", "lines_removed", "created_at",
|
||||
"id",
|
||||
"device_id",
|
||||
"tenant_id",
|
||||
"old_snapshot_id",
|
||||
"new_snapshot_id",
|
||||
"diff_text",
|
||||
"lines_added",
|
||||
"lines_removed",
|
||||
"created_at",
|
||||
}
|
||||
actual = {c.name for c in table.columns}
|
||||
assert expected.issubset(actual), f"Missing columns: {expected - actual}"
|
||||
@@ -69,10 +89,17 @@ def test_diff_columns():
|
||||
def test_change_columns():
|
||||
"""RouterConfigChange has all required columns."""
|
||||
from app.models import RouterConfigChange
|
||||
|
||||
table = RouterConfigChange.__table__
|
||||
expected = {
|
||||
"id", "diff_id", "device_id", "tenant_id",
|
||||
"component", "summary", "raw_line", "created_at",
|
||||
"id",
|
||||
"diff_id",
|
||||
"device_id",
|
||||
"tenant_id",
|
||||
"component",
|
||||
"summary",
|
||||
"raw_line",
|
||||
"created_at",
|
||||
}
|
||||
actual = {c.name for c in table.columns}
|
||||
assert expected.issubset(actual), f"Missing columns: {expected - actual}"
|
||||
@@ -81,6 +108,7 @@ def test_change_columns():
|
||||
def test_snapshot_config_text_is_text_type():
|
||||
"""config_text column type is Text (documents Transit ciphertext contract)."""
|
||||
from app.models import RouterConfigSnapshot
|
||||
|
||||
col = RouterConfigSnapshot.__table__.c.config_text
|
||||
assert isinstance(col.type, Text), f"Expected Text, got {type(col.type)}"
|
||||
|
||||
@@ -88,6 +116,7 @@ def test_snapshot_config_text_is_text_type():
|
||||
def test_snapshot_sha256_hash_is_string_64():
|
||||
"""sha256_hash column type is String(64) for plaintext hash deduplication."""
|
||||
from app.models import RouterConfigSnapshot
|
||||
|
||||
col = RouterConfigSnapshot.__table__.c.sha256_hash
|
||||
assert isinstance(col.type, String), f"Expected String, got {type(col.type)}"
|
||||
assert col.type.length == 64, f"Expected length 64, got {col.type.length}"
|
||||
|
||||
@@ -7,11 +7,9 @@ Tests cover:
|
||||
- Router registration in main app
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime, timezone, timedelta
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
|
||||
class TestMaintenanceWindowModel:
|
||||
@@ -19,20 +17,31 @@ class TestMaintenanceWindowModel:
|
||||
|
||||
def test_model_importable(self):
|
||||
from app.models.maintenance_window import MaintenanceWindow
|
||||
|
||||
assert MaintenanceWindow.__tablename__ == "maintenance_windows"
|
||||
|
||||
def test_model_exported_from_init(self):
|
||||
from app.models import MaintenanceWindow
|
||||
|
||||
assert MaintenanceWindow.__tablename__ == "maintenance_windows"
|
||||
|
||||
def test_model_has_required_columns(self):
|
||||
from app.models.maintenance_window import MaintenanceWindow
|
||||
|
||||
mapper = MaintenanceWindow.__mapper__
|
||||
column_names = {c.key for c in mapper.columns}
|
||||
expected = {
|
||||
"id", "tenant_id", "name", "device_ids",
|
||||
"start_at", "end_at", "suppress_alerts",
|
||||
"notes", "created_by", "created_at", "updated_at",
|
||||
"id",
|
||||
"tenant_id",
|
||||
"name",
|
||||
"device_ids",
|
||||
"start_at",
|
||||
"end_at",
|
||||
"suppress_alerts",
|
||||
"notes",
|
||||
"created_by",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
}
|
||||
assert expected.issubset(column_names), f"Missing columns: {expected - column_names}"
|
||||
|
||||
@@ -42,6 +51,7 @@ class TestMaintenanceWindowSchemas:
|
||||
|
||||
def test_create_schema_valid(self):
|
||||
from app.routers.maintenance_windows import MaintenanceWindowCreate
|
||||
|
||||
data = MaintenanceWindowCreate(
|
||||
name="Nightly update",
|
||||
device_ids=["abc-123"],
|
||||
@@ -55,6 +65,7 @@ class TestMaintenanceWindowSchemas:
|
||||
|
||||
def test_create_schema_defaults(self):
|
||||
from app.routers.maintenance_windows import MaintenanceWindowCreate
|
||||
|
||||
data = MaintenanceWindowCreate(
|
||||
name="Quick reboot",
|
||||
device_ids=[],
|
||||
@@ -66,12 +77,14 @@ class TestMaintenanceWindowSchemas:
|
||||
|
||||
def test_update_schema_partial(self):
|
||||
from app.routers.maintenance_windows import MaintenanceWindowUpdate
|
||||
|
||||
data = MaintenanceWindowUpdate(name="Updated name")
|
||||
assert data.name == "Updated name"
|
||||
assert data.device_ids is None # all optional
|
||||
|
||||
def test_response_schema(self):
|
||||
from app.routers.maintenance_windows import MaintenanceWindowResponse
|
||||
|
||||
data = MaintenanceWindowResponse(
|
||||
id="abc",
|
||||
tenant_id="def",
|
||||
@@ -92,10 +105,12 @@ class TestRouterRegistration:
|
||||
|
||||
def test_router_importable(self):
|
||||
from app.routers.maintenance_windows import router
|
||||
|
||||
assert router is not None
|
||||
|
||||
def test_router_has_routes(self):
|
||||
from app.routers.maintenance_windows import router
|
||||
|
||||
paths = [r.path for r in router.routes]
|
||||
assert any("maintenance-windows" in p for p in paths)
|
||||
|
||||
@@ -114,8 +129,10 @@ class TestAlertEvaluatorMaintenance:
|
||||
|
||||
def test_maintenance_cache_exists(self):
|
||||
from app.services import alert_evaluator
|
||||
|
||||
assert hasattr(alert_evaluator, "_maintenance_cache")
|
||||
|
||||
def test_is_device_in_maintenance_function_exists(self):
|
||||
from app.services.alert_evaluator import _is_device_in_maintenance
|
||||
|
||||
assert callable(_is_device_in_maintenance)
|
||||
|
||||
@@ -9,7 +9,6 @@ for startup validation, async only for middleware tests.
|
||||
"""
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -114,7 +113,9 @@ class TestSecurityHeadersMiddleware:
|
||||
response = await client.get("/test")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.headers["strict-transport-security"] == "max-age=31536000; includeSubDomains"
|
||||
assert (
|
||||
response.headers["strict-transport-security"] == "max-age=31536000; includeSubDomains"
|
||||
)
|
||||
assert response.headers["x-content-type-options"] == "nosniff"
|
||||
assert response.headers["x-frame-options"] == "DENY"
|
||||
assert response.headers["cache-control"] == "no-store"
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
"""Unit tests for VPN subnet allocation and allowed-IPs validation."""
|
||||
|
||||
import pytest
|
||||
from app.services.vpn_service import _allocate_subnet_index_from_used, _validate_additional_allowed_ips
|
||||
from app.services.vpn_service import (
|
||||
_allocate_subnet_index_from_used,
|
||||
_validate_additional_allowed_ips,
|
||||
)
|
||||
|
||||
|
||||
class TestSubnetAllocation:
|
||||
|
||||
Reference in New Issue
Block a user