This commit is contained in:
Yaojia Wang
2026-01-27 00:47:10 +01:00
parent e83a0cae36
commit 58bf75db68
141 changed files with 24814 additions and 3884 deletions

View File

@@ -0,0 +1,197 @@
"""
Tests for Admin Annotation Routes.
"""
import pytest
from datetime import datetime
from unittest.mock import MagicMock, patch
from uuid import UUID
from fastapi import HTTPException
from src.data.admin_models import AdminAnnotation, AdminDocument, FIELD_CLASSES
from src.web.api.v1.admin.annotations import _validate_uuid, create_annotation_router
from src.web.schemas.admin import (
AnnotationCreate,
AnnotationUpdate,
AutoLabelRequest,
BoundingBox,
)
# Test UUIDs
TEST_DOC_UUID = "550e8400-e29b-41d4-a716-446655440000"
TEST_ANN_UUID = "660e8400-e29b-41d4-a716-446655440001"
TEST_TOKEN = "test-admin-token-12345"
class TestAnnotationRouterCreation:
"""Tests for annotation router creation."""
def test_creates_router_with_endpoints(self):
"""Test router is created with expected endpoints."""
router = create_annotation_router()
# Get route paths (includes prefix)
paths = [route.path for route in router.routes]
# Paths include the /admin/documents prefix
assert any("{document_id}/annotations" in p for p in paths)
assert any("{annotation_id}" in p for p in paths)
assert any("auto-label" in p for p in paths)
assert any("images" in p for p in paths)
class TestAnnotationCreateSchema:
"""Tests for AnnotationCreate schema."""
def test_valid_annotation(self):
"""Test valid annotation creation."""
ann = AnnotationCreate(
page_number=1,
class_id=0,
bbox=BoundingBox(x=100, y=100, width=200, height=50),
text_value="12345",
)
assert ann.page_number == 1
assert ann.class_id == 0
assert ann.bbox.x == 100
assert ann.text_value == "12345"
def test_class_id_range(self):
"""Test class_id must be 0-9."""
# Valid class IDs
for class_id in range(10):
ann = AnnotationCreate(
page_number=1,
class_id=class_id,
bbox=BoundingBox(x=0, y=0, width=100, height=50),
)
assert ann.class_id == class_id
def test_bbox_validation(self):
"""Test bounding box validation."""
bbox = BoundingBox(x=0, y=0, width=100, height=50)
assert bbox.width >= 1
assert bbox.height >= 1
class TestAnnotationUpdateSchema:
"""Tests for AnnotationUpdate schema."""
def test_partial_update(self):
"""Test partial update with only some fields."""
update = AnnotationUpdate(
text_value="new value",
)
assert update.text_value == "new value"
assert update.class_id is None
assert update.bbox is None
def test_bbox_update(self):
"""Test bounding box update."""
update = AnnotationUpdate(
bbox=BoundingBox(x=50, y=50, width=150, height=75),
)
assert update.bbox.x == 50
assert update.bbox.width == 150
class TestAutoLabelRequestSchema:
"""Tests for AutoLabelRequest schema."""
def test_valid_request(self):
"""Test valid auto-label request."""
request = AutoLabelRequest(
field_values={
"InvoiceNumber": "12345",
"Amount": "1000.00",
},
replace_existing=True,
)
assert len(request.field_values) == 2
assert request.field_values["InvoiceNumber"] == "12345"
assert request.replace_existing is True
def test_requires_field_values(self):
"""Test that field_values is required."""
with pytest.raises(Exception):
AutoLabelRequest(replace_existing=True)
class TestFieldClasses:
"""Tests for field class mapping."""
def test_all_classes_defined(self):
"""Test all 10 field classes are defined."""
assert len(FIELD_CLASSES) == 10
def test_class_ids_sequential(self):
"""Test class IDs are 0-9."""
assert set(FIELD_CLASSES.keys()) == set(range(10))
def test_known_field_names(self):
"""Test known field names are present."""
names = list(FIELD_CLASSES.values())
assert "invoice_number" in names
assert "invoice_date" in names
assert "amount" in names
assert "bankgiro" in names
assert "ocr_number" in names
class TestAnnotationModel:
"""Tests for AdminAnnotation model."""
def test_annotation_creation(self):
"""Test annotation model creation."""
ann = AdminAnnotation(
document_id=UUID(TEST_DOC_UUID),
page_number=1,
class_id=0,
class_name="invoice_number",
x_center=0.5,
y_center=0.5,
width=0.2,
height=0.05,
bbox_x=100,
bbox_y=100,
bbox_width=200,
bbox_height=50,
text_value="12345",
confidence=0.95,
source="manual",
)
assert str(ann.document_id) == TEST_DOC_UUID
assert ann.class_id == 0
assert ann.x_center == 0.5
assert ann.source == "manual"
def test_normalized_coordinates(self):
"""Test normalized coordinates are 0-1 range."""
# Valid normalized coords
ann = AdminAnnotation(
document_id=UUID(TEST_DOC_UUID),
page_number=1,
class_id=0,
class_name="test",
x_center=0.5,
y_center=0.5,
width=0.2,
height=0.05,
bbox_x=0,
bbox_y=0,
bbox_width=100,
bbox_height=50,
)
assert 0 <= ann.x_center <= 1
assert 0 <= ann.y_center <= 1
assert 0 <= ann.width <= 1
assert 0 <= ann.height <= 1