Files
Yuzviak bf5b0e3ae2 fix(lint): resolve all ruff E402/I001/F821 errors
- Move pytestmark after all imports in 35 test files (E402: not-at-top)
- Add TYPE_CHECKING guard for FlightProcessor in composition.py (F821)
- Sort import blocks in src/ and tests/ (I001 auto-fix via ruff --fix)
- ruff check src/ tests/ now exits 0 with no errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 19:13:42 +03:00

169 lines
5.6 KiB
Python

"""Tests for domain schemas and configuration."""
from datetime import datetime, timezone
import pytest
from pydantic import ValidationError
from gps_denied.config import get_settings
from gps_denied.schemas import CameraParameters, GPSPoint
from gps_denied.schemas.events import (
FrameProcessedEvent,
SSEEventType,
SSEMessage,
)
from gps_denied.schemas.flight import (
FlightCreateRequest,
Waypoint,
)
pytestmark = [pytest.mark.unit]
# ── GPSPoint ──────────────────────────────────────────────────────────────
@pytest.mark.ac("AC-6.3")
class TestGPSPoint:
def test_valid(self):
p = GPSPoint(lat=48.275, lon=37.385)
assert p.lat == 48.275
def test_lat_out_of_range(self):
with pytest.raises(ValidationError):
GPSPoint(lat=91, lon=0)
def test_lon_out_of_range(self):
with pytest.raises(ValidationError):
GPSPoint(lat=0, lon=181)
def test_serialization_roundtrip(self):
p = GPSPoint(lat=-12.5, lon=130.0)
assert GPSPoint.model_validate_json(p.model_dump_json()) == p
# ── CameraParameters ─────────────────────────────────────────────────────
class TestCameraParameters:
def test_valid(self):
cam = CameraParameters(
focal_length=25,
sensor_width=23.5,
sensor_height=15.6,
resolution_width=6252,
resolution_height=4168,
)
assert cam.resolution_width == 6252
def test_negative_focal_length(self):
with pytest.raises(ValidationError):
CameraParameters(
focal_length=-1,
sensor_width=23.5,
sensor_height=15.6,
resolution_width=6252,
resolution_height=4168,
)
# ── FlightCreateRequest ──────────────────────────────────────────────────
class TestFlightCreateRequest:
def test_minimal_valid(self):
req = FlightCreateRequest(
name="Test_Flight",
start_gps=GPSPoint(lat=48.275, lon=37.385),
camera_params=CameraParameters(
focal_length=25,
sensor_width=23.5,
sensor_height=15.6,
resolution_width=6252,
resolution_height=4168,
),
altitude=400,
)
assert req.name == "Test_Flight"
assert req.description == ""
assert req.geofences.polygons == []
def test_empty_name_rejected(self):
with pytest.raises(ValidationError):
FlightCreateRequest(
name="",
start_gps=GPSPoint(lat=0, lon=0),
camera_params=CameraParameters(
focal_length=25,
sensor_width=23.5,
sensor_height=15.6,
resolution_width=6252,
resolution_height=4168,
),
altitude=400,
)
# ── Waypoint ──────────────────────────────────────────────────────────────
@pytest.mark.ac("AC-6.3")
class TestWaypoint:
def test_valid(self):
wp = Waypoint(
id="wp_001",
lat=48.123,
lon=37.456,
confidence=0.95,
timestamp=datetime.now(tz=timezone.utc),
)
assert wp.refined is False
def test_confidence_out_of_range(self):
with pytest.raises(ValidationError):
Waypoint(
id="wp_001",
lat=48.123,
lon=37.456,
confidence=1.5,
timestamp=datetime.now(tz=timezone.utc),
)
# ── SSE Events ────────────────────────────────────────────────────────────
class TestSSEEvents:
def test_event_types(self):
assert SSEEventType.FRAME_PROCESSED == "frame_processed"
assert SSEEventType.FLIGHT_COMPLETED == "flight_completed"
def test_frame_event_serialization(self):
evt = FrameProcessedEvent(
frame_id=237,
gps=GPSPoint(lat=48.123, lon=37.456),
confidence=0.95,
timestamp=datetime.now(tz=timezone.utc),
)
data = evt.model_dump()
assert data["frame_id"] == 237
def test_sse_message(self):
msg = SSEMessage(
event=SSEEventType.FLIGHT_COMPLETED,
data={"frames_total": 100, "frames_processed": 100},
)
assert msg.event == "flight_completed"
# ── Configuration ─────────────────────────────────────────────────────────
class TestConfig:
def test_defaults(self):
settings = get_settings()
assert "sqlite" in settings.db.url
assert settings.api.port == 8000
assert settings.tiles.provider == "google"
def test_rotation_iterations(self):
settings = get_settings()
assert settings.rotation.rotation_iterations == 12 # 360 / 30
def test_recovery_defaults(self):
settings = get_settings()
assert settings.recovery.search_grid_sizes == [1, 4, 9, 16, 25]