165 lines
5.0 KiB
Python
165 lines
5.0 KiB
Python
"""
|
|
Tests for Admin Document Routes.
|
|
"""
|
|
|
|
import pytest
|
|
from datetime import datetime
|
|
from io import BytesIO
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
from uuid import UUID
|
|
|
|
from fastapi import HTTPException
|
|
from fastapi.testclient import TestClient
|
|
|
|
from src.data.admin_models import AdminDocument, AdminToken
|
|
from src.web.api.v1.admin.documents import _validate_uuid, create_admin_router
|
|
|
|
|
|
# Test UUID
|
|
TEST_DOC_UUID = "550e8400-e29b-41d4-a716-446655440000"
|
|
TEST_TOKEN = "test-admin-token-12345"
|
|
|
|
|
|
class TestValidateUUID:
|
|
"""Tests for UUID validation."""
|
|
|
|
def test_valid_uuid(self):
|
|
"""Test valid UUID passes validation."""
|
|
_validate_uuid(TEST_DOC_UUID, "test") # Should not raise
|
|
|
|
def test_invalid_uuid_raises_400(self):
|
|
"""Test invalid UUID raises 400."""
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
_validate_uuid("not-a-uuid", "document_id")
|
|
|
|
assert exc_info.value.status_code == 400
|
|
assert "Invalid document_id format" in exc_info.value.detail
|
|
|
|
|
|
class TestAdminRouter:
|
|
"""Tests for admin router creation."""
|
|
|
|
def test_creates_router_with_endpoints(self):
|
|
"""Test router is created with expected endpoints."""
|
|
router = create_admin_router((".pdf", ".png", ".jpg"))
|
|
|
|
# Get route paths (include prefix from router)
|
|
paths = [route.path for route in router.routes]
|
|
|
|
# Paths include the /admin prefix
|
|
assert any("/auth/token" in p for p in paths)
|
|
assert any("/documents" in p for p in paths)
|
|
assert any("/documents/stats" in p for p in paths)
|
|
assert any("{document_id}" in p for p in paths)
|
|
|
|
|
|
class TestCreateTokenEndpoint:
|
|
"""Tests for POST /admin/auth/token endpoint."""
|
|
|
|
@pytest.fixture
|
|
def mock_db(self):
|
|
"""Create mock AdminDB."""
|
|
db = MagicMock()
|
|
db.is_valid_admin_token.return_value = True
|
|
return db
|
|
|
|
def test_create_token_success(self, mock_db):
|
|
"""Test successful token creation."""
|
|
from src.web.schemas.admin import AdminTokenCreate
|
|
|
|
request = AdminTokenCreate(name="Test Token", expires_in_days=30)
|
|
|
|
# The actual endpoint would generate a token
|
|
# This tests the schema validation
|
|
assert request.name == "Test Token"
|
|
assert request.expires_in_days == 30
|
|
|
|
|
|
class TestDocumentUploadEndpoint:
|
|
"""Tests for POST /admin/documents endpoint."""
|
|
|
|
@pytest.fixture
|
|
def sample_pdf_bytes(self):
|
|
"""Create sample PDF-like bytes."""
|
|
# Minimal PDF header
|
|
return b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n"
|
|
|
|
@pytest.fixture
|
|
def mock_admin_db(self):
|
|
"""Create mock AdminDB."""
|
|
db = MagicMock()
|
|
db.is_valid_admin_token.return_value = True
|
|
db.create_document.return_value = TEST_DOC_UUID
|
|
return db
|
|
|
|
def test_rejects_invalid_extension(self):
|
|
"""Test that invalid file extensions are rejected."""
|
|
# Schema validation would happen at the route level
|
|
allowed = (".pdf", ".png", ".jpg")
|
|
file_ext = ".exe"
|
|
|
|
assert file_ext not in allowed
|
|
|
|
|
|
class TestDocumentListEndpoint:
|
|
"""Tests for GET /admin/documents endpoint."""
|
|
|
|
@pytest.fixture
|
|
def sample_documents(self):
|
|
"""Create sample documents."""
|
|
return [
|
|
AdminDocument(
|
|
document_id=UUID(TEST_DOC_UUID),
|
|
admin_token=TEST_TOKEN,
|
|
filename="test.pdf",
|
|
file_size=1024,
|
|
content_type="application/pdf",
|
|
file_path="/tmp/test.pdf",
|
|
page_count=1,
|
|
status="pending",
|
|
),
|
|
]
|
|
|
|
def test_validates_status_filter(self):
|
|
"""Test that invalid status filter is rejected."""
|
|
valid_statuses = ("pending", "auto_labeling", "labeled", "exported")
|
|
|
|
assert "invalid_status" not in valid_statuses
|
|
assert "pending" in valid_statuses
|
|
|
|
|
|
class TestDocumentDetailEndpoint:
|
|
"""Tests for GET /admin/documents/{document_id} endpoint."""
|
|
|
|
def test_requires_valid_uuid(self):
|
|
"""Test that invalid UUID is rejected."""
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
_validate_uuid("invalid", "document_id")
|
|
|
|
assert exc_info.value.status_code == 400
|
|
|
|
|
|
class TestDocumentDeleteEndpoint:
|
|
"""Tests for DELETE /admin/documents/{document_id} endpoint."""
|
|
|
|
def test_validates_document_id(self):
|
|
"""Test that document_id is validated."""
|
|
# Valid UUID should not raise
|
|
_validate_uuid(TEST_DOC_UUID, "document_id")
|
|
|
|
# Invalid should raise
|
|
with pytest.raises(HTTPException):
|
|
_validate_uuid("bad-id", "document_id")
|
|
|
|
|
|
class TestDocumentStatusUpdateEndpoint:
|
|
"""Tests for PATCH /admin/documents/{document_id}/status endpoint."""
|
|
|
|
def test_validates_status_values(self):
|
|
"""Test that only valid statuses are accepted."""
|
|
valid_statuses = ("pending", "labeled", "exported")
|
|
|
|
assert "pending" in valid_statuses
|
|
assert "invalid" not in valid_statuses
|