from unittest.mock import Mock from xml.etree import ElementTree as ET import pytest from shapely.geometry import box from shapely.geometry.base import BaseGeometry from flight_map.curves import interpolate from flight_map.plot import SVG_NS, outside_index @pytest.mark.parametrize( "points", [ [(0, 50), (100, 50)], [(50, 0), (50, 100)], [(20, 30), (60, 40)], [(0, 0), (100, 100)], ], ) @pytest.mark.parametrize("text", ["1", "12", "123"]) def test_indices_are_outside_map_and_inside_page( points: list[tuple[float, float]], text: str, monkeypatch: pytest.MonkeyPatch, ) -> None: group = ET.Element("g") map_rectangle = box(10, 10, 90, 90) outer_rectangle = box(4, 4, 96, 96) occupied: list[BaseGeometry] = [] draw = Mock() monkeypatch.setattr("flight_map.plot.label", draw) outside_index( group, text, interpolate(points), map_rectangle, outer_rectangle, occupied, 1.8, 0.3 ) assert len(occupied) == 1 assert occupied[0].disjoint(map_rectangle) assert outer_rectangle.covers(occupied[0]) draw.assert_called_once() assert group.find(f"{{{SVG_NS}}}path") is not None # Vector leader line. def test_nearby_indices_do_not_overlap(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr("flight_map.plot.label", Mock()) occupied: list[BaseGeometry] = [] curves = interpolate([(0, 50), (100, 50)]) for index in range(1, 7): outside_index( ET.Element("g"), str(index), curves, box(10, 10, 90, 90), box(6, 6, 94, 94), occupied, 1.8, 0.3, ) for index, extent in enumerate(occupied): assert all(extent.disjoint(other) for other in occupied[index + 1 :]) def test_too_narrow_margin_fails_instead_of_putting_index_inside() -> None: with pytest.raises(ValueError, match="outside the map"): outside_index( ET.Element("g"), "12", interpolate([(0, 50), (100, 50)]), box(10, 10, 90, 90), box(9.9, 9.9, 90.1, 90.1), [], 1.8, 0.3, )