"""Tests for trip map coordinate assembly.""" from datetime import date import agenda.trip import pytest from agenda.types import Trip from web_view import app def test_add_coordinates_for_unbooked_flights_adds_missing_airports() -> None: """Unbooked routes should contribute missing airport pins.""" routes = [ { "type": "unbooked_flight", "key": "LHR_Paris_fr", "from_iata": "LHR", "to_iata": "CDG", "from": (51.47, -0.45), "to": (49.01, 2.55), } ] coordinates = [ { "name": "Heathrow Airport", "type": "airport", "latitude": 51.47, "longitude": -0.45, } ] airports = { "LHR": { "name": "Heathrow Airport", "latitude": 51.47, "longitude": -0.45, }, "CDG": { "name": "Paris Charles de Gaulle Airport", "latitude": 49.01, "longitude": 2.55, }, } with app.app_context(): original_parse_yaml = agenda.trip.travel.parse_yaml try: agenda.trip.travel.parse_yaml = lambda _name, _data_dir: airports agenda.trip.add_coordinates_for_unbooked_flights( routes, coordinates, app.config["PERSONAL_DATA"] ) finally: agenda.trip.travel.parse_yaml = original_parse_yaml airport_names = { coord["name"] for coord in coordinates if coord["type"] == "airport" } assert airport_names == {"Heathrow Airport", "Paris Charles de Gaulle Airport"} def test_get_coordinates_and_routes_adds_unbooked_flight_airports() -> None: """Trip list map data should include pins for unbooked flights.""" trips = [Trip(start=date(2026, 7, 20))] unbooked_routes = [ { "type": "unbooked_flight", "key": "LHR_Paris_fr", "from_iata": "LHR", "to_iata": "CDG", "from": (51.47, -0.45), "to": (49.01, 2.55), } ] airports = { "LHR": { "name": "Heathrow Airport", "latitude": 51.47, "longitude": -0.45, }, "CDG": { "name": "Paris Charles de Gaulle Airport", "latitude": 49.01, "longitude": 2.55, }, } with app.app_context(): original_collect_trip_coordinates = agenda.trip.collect_trip_coordinates original_get_trip_routes = agenda.trip.get_trip_routes original_parse_yaml = agenda.trip.travel.parse_yaml try: agenda.trip.collect_trip_coordinates = lambda _trip: [] agenda.trip.get_trip_routes = lambda _trip, _data_dir: unbooked_routes agenda.trip.travel.parse_yaml = lambda _name, _data_dir: airports coordinates, _routes = agenda.trip.get_coordinates_and_routes(trips) finally: agenda.trip.collect_trip_coordinates = original_collect_trip_coordinates agenda.trip.get_trip_routes = original_get_trip_routes agenda.trip.travel.parse_yaml = original_parse_yaml airport_names = { coord["name"] for coord in coordinates if coord["type"] == "airport" } assert airport_names == {"Heathrow Airport", "Paris Charles de Gaulle Airport"} def test_get_trip_routes_assumes_unbooked_paris_trip_is_by_train( monkeypatch: pytest.MonkeyPatch, ) -> None: """Paris conferences without booked travel should show rail, not flight.""" trip = Trip( start=date(2026, 7, 20), conferences=[ { "name": "Paris Conf", "location": "Paris", "country": "fr", } ], ) stations = [ { "name": "London St Pancras", "latitude": 51.531921, "longitude": -0.126361, "routes": {"Paris Gare du Nord": "London_St_Pancras_to_Paris_Gare_du_Nord"}, }, { "name": "Paris Gare du Nord", "latitude": 48.88111111111111, "longitude": 2.355277777777778, "routes": {"London St Pancras": "London_St_Pancras_to_Paris_Gare_du_Nord"}, }, ] def fake_parse_yaml(name: str, data_dir: str) -> object: if name == "stations": return stations if name == "airports": return { "LHR": { "name": "Heathrow Airport", "latitude": 51.47, "longitude": -0.45, }, "CDG": { "name": "Paris Charles de Gaulle Airport", "city": "Paris", "country": "fr", "latitude": 49.01, "longitude": 2.55, }, } raise AssertionError(f"unexpected YAML load: {name}") monkeypatch.setattr(agenda.trip.travel, "parse_yaml", fake_parse_yaml) monkeypatch.setattr( agenda.trip, "load_flight_destination_rules", lambda _data_dir: [] ) routes = agenda.trip.get_trip_routes(trip, "/tmp/personal-data") assert routes == [ { "type": "train", "key": "train_London St Pancras_Paris Gare du Nord", "geojson_filename": "train_routes/London_St_Pancras_to_Paris_Gare_du_Nord", } ]