from __future__ import annotations import pathlib import pytest from PIL import Image from planemapper.models import Aircraft from planemapper.renderer.projection import MapBounds from planemapper.renderer.renderer import Renderer FIXTURE_DIR = pathlib.Path(__file__).parent / "fixtures" @pytest.fixture def white_base_map() -> Image.Image: return Image.new("RGB", (800, 480), color=(255, 255, 255)) @pytest.fixture def bounds() -> MapBounds: return MapBounds(home_lat=53.0, home_lon=-6.0, radius_nm=100.0) @pytest.fixture def renderer( white_base_map: Image.Image, bounds: MapBounds, monkeypatch: pytest.MonkeyPatch ) -> Renderer: monkeypatch.setattr( "planemapper.renderer.airspace.AIRSPACE_PATH", FIXTURE_DIR / "airspace_sample.geojson", ) return Renderer(white_base_map, bounds) def _aircraft(icao: str = "ABC123", **kwargs) -> Aircraft: defaults = {"lat": 53.1, "lon": -6.1} defaults.update(kwargs) return Aircraft(icao=icao, **defaults) def test_render_returns_800x480(renderer: Renderer) -> None: result = renderer.render([]) assert isinstance(result, Image.Image) assert result.size == (800, 480) def test_trail_accumulated_across_renders(renderer: Renderer) -> None: ac = _aircraft(icao="ABC123") renderer.render([ac]) renderer.render([ac]) assert "ABC123" in renderer._trails assert len(renderer._trails["ABC123"]) == 2 def test_absent_aircraft_trail_retained(renderer: Renderer) -> None: ac = _aircraft(icao="ABC123") renderer.render([ac]) renderer.render([]) # aircraft absent assert "ABC123" in renderer._trails assert len(renderer._trails["ABC123"]) == 1