Files
planeMapper/tests/test_aircraft_draw.py
Matt Edholm f530185e31 feat(renderer): implement per-aircraft drawing — story 2-5
Implements draw_aircraft() with heading arrow (filled/outlined for MLAT),
callsign+altitude label, and a 5-dot fade trail. Adds 5 tests covering
all ACs; all 94 tests pass, ruff lint and format clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 23:27:36 -04:00

61 lines
1.8 KiB
Python

from __future__ import annotations
import collections
from PIL import Image
from planemapper.models import Aircraft
from planemapper.renderer.aircraft import draw_aircraft
def _white_image() -> Image.Image:
return Image.new("RGB", (800, 480), color=(255, 255, 255))
def _aircraft(**kwargs) -> Aircraft:
defaults = {"icao": "ABC123", "lat": 53.0, "lon": -6.0}
defaults.update(kwargs)
return Aircraft(**defaults)
def test_heading_east_changes_pixels() -> None:
img = _white_image()
ac = _aircraft(heading=90.0, altitude_ft=10000)
draw_aircraft(img, ac, (400, 240), collections.deque())
# Arrow should have painted at least one non-white pixel near centre
changed = any(
img.getpixel((x, y)) != (255, 255, 255) for x in range(388, 413) for y in range(228, 253)
)
assert changed
def test_label_with_callsign_no_exception() -> None:
img = _white_image()
ac = _aircraft(callsign="BAW1", altitude_ft=28000)
result = draw_aircraft(img, ac, (400, 240), collections.deque())
assert result is None
def test_trail_drawn_no_exception() -> None:
img = _white_image()
ac = _aircraft(altitude_ft=5000)
trail: collections.deque[tuple[int, int]] = collections.deque(
[(390, 230), (380, 220), (370, 210)]
)
result = draw_aircraft(img, ac, (400, 240), trail)
assert result is None
def test_mlat_aircraft_no_exception() -> None:
img = _white_image()
ac = _aircraft(is_mlat=True, altitude_ft=8000)
result = draw_aircraft(img, ac, (400, 240), collections.deque())
assert result is None
def test_empty_callsign_no_exception() -> None:
img = _white_image()
ac = _aircraft(callsign="", altitude_ft=15000)
result = draw_aircraft(img, ac, (400, 240), collections.deque())
assert result is None