"""Regression tests for trip page route wiring and rendering.""" from datetime import date, datetime import typing from unittest import mock import flask import agenda.trip import agenda.trip_schengen import agenda.weather import web_view from agenda.types import Trip def test_trip_page_passes_data_dir_to_unbooked_flight_helper() -> None: """Trip page should call helper with routes, coordinates and data_dir.""" trip = Trip(start=date(2025, 1, 28)) captured: dict[str, str] = {} with web_view.app.app_context(): def fake_add_coordinates( _routes: list[typing.Any], _coordinates: list[typing.Any], data_dir: str, ) -> None: captured["data_dir"] = data_dir with ( mock.patch.object(web_view, "get_trip_list", return_value=[trip]), mock.patch.object( agenda.trip_schengen, "add_schengen_compliance_to_trip", side_effect=lambda t: t, ), mock.patch.object(agenda.trip, "collect_trip_coordinates", return_value=[]), mock.patch.object(agenda.trip, "get_trip_routes", return_value=[]), mock.patch.object( agenda.trip, "add_coordinates_for_unbooked_flights", side_effect=fake_add_coordinates, ), mock.patch.object(agenda.weather, "get_trip_weather", return_value=[]), mock.patch.object(flask, "render_template", return_value="ok"), ): with web_view.app.test_request_context("/trip/2025-01-28"): result = web_view.trip_page("2025-01-28") assert result == "ok" assert captured["data_dir"] == web_view.app.config["PERSONAL_DATA"] def test_trip_page_renders_with_mixed_date_and_datetime_train_leg() -> None: """Trip page should render when train leg times mix dates and datetimes.""" trip = Trip( start=date(2025, 1, 28), travel=[ { "type": "train", "depart": date(2025, 1, 28), "from": "A", "to": "B", "from_station": { "name": "A", "country": "gb", "latitude": 51.5, "longitude": -0.1, }, "to_station": { "name": "B", "country": "gb", "latitude": 51.6, "longitude": -0.2, }, "legs": [ { "from": "A", "to": "B", "depart": date(2025, 1, 28), "arrive": datetime(2025, 1, 28, 16, 49), "from_station": { "name": "A", "country": "gb", "latitude": 51.5, "longitude": -0.1, }, "to_station": { "name": "B", "country": "gb", "latitude": 51.6, "longitude": -0.2, }, "operator": "Test Rail", } ], } ], ) with web_view.app.app_context(): with ( mock.patch.object(web_view, "get_trip_list", return_value=[trip]), mock.patch.object(agenda.weather, "get_trip_weather", return_value=[]), ): web_view.app.config["TESTING"] = True with web_view.app.test_client() as client: response = client.get("/trip/2025-01-28") assert response.status_code == 200 assert b"Test Rail" in response.data def test_trip_page_hides_train_times_for_date_only_train_leg() -> None: """Trip page should not show midnight times for unbooked date-only trains.""" trip = Trip( start=date(2026, 8, 23), travel=[ { "type": "train", "depart": date(2026, 8, 23), "arrive": date(2026, 8, 23), "from": "London St Pancras", "to": "Paris Gare du Nord", "from_station": { "name": "London St Pancras", "country": "gb", "latitude": 51.532, "longitude": -0.126, }, "to_station": { "name": "Paris Gare du Nord", "country": "fr", "latitude": 48.88, "longitude": 2.355, }, "legs": [ { "from": "London St Pancras", "to": "Paris Gare du Nord", "depart": date(2026, 8, 23), "arrive": date(2026, 8, 23), "from_station": { "name": "London St Pancras", "country": "gb", "latitude": 51.532, "longitude": -0.126, }, "to_station": { "name": "Paris Gare du Nord", "country": "fr", "latitude": 48.88, "longitude": 2.355, }, "operator": "Eurostar", "class": "Eurostar Plus", } ], } ], ) with web_view.app.app_context(): with ( mock.patch.object(web_view, "get_trip_list", return_value=[trip]), mock.patch.object(agenda.weather, "get_trip_weather", return_value=[]), ): web_view.app.config["TESTING"] = True with web_view.app.test_client() as client: response = client.get("/trip/2026-08-23") assert response.status_code == 200 page = response.data.decode() assert "London St Pancras → Paris Gare du Nord" in page assert "Eurostar" in page assert "Eurostar Plus" in page assert "00:00" not in page assert "🕒" not in page def test_trip_page_uses_seat_icon_for_day_train_coach() -> None: """Same-day train coach details should not use the sleeper bed icon.""" trip = Trip( start=date(2026, 2, 4), travel=[ { "type": "train", "depart": datetime(2026, 2, 4, 10, 0), "arrive": datetime(2026, 2, 4, 12, 0), "from": "London", "to": "Manchester", "from_station": { "name": "London", "country": "gb", "latitude": 51.5, "longitude": -0.1, }, "to_station": { "name": "Manchester", "country": "gb", "latitude": 53.48, "longitude": -2.24, }, "legs": [ { "from": "London", "to": "Manchester", "depart": datetime(2026, 2, 4, 10, 0), "arrive": datetime(2026, 2, 4, 12, 0), "from_station": { "name": "London", "country": "gb", "latitude": 51.5, "longitude": -0.1, }, "to_station": { "name": "Manchester", "country": "gb", "latitude": 53.48, "longitude": -2.24, }, "coach": "C", "seat": 12, } ], } ], ) with web_view.app.app_context(): with ( mock.patch.object(web_view, "get_trip_list", return_value=[trip]), mock.patch.object(agenda.weather, "get_trip_weather", return_value=[]), ): web_view.app.config["TESTING"] = True with web_view.app.test_client() as client: response = client.get("/trip/2026-02-04") assert response.status_code == 200 page = response.data.decode() assert "💺 Coach C, Seat 12" in page assert "🛏️ Coach C, Seat 12" not in page def test_trip_page_uses_bed_icon_for_overnight_train_coach() -> None: """Overnight train coach details keep the sleeper bed icon.""" trip = Trip( start=date(2026, 2, 4), travel=[ { "type": "train", "depart": datetime(2026, 2, 4, 22, 0), "arrive": datetime(2026, 2, 5, 7, 0), "from": "London", "to": "Edinburgh", "from_station": { "name": "London", "country": "gb", "latitude": 51.5, "longitude": -0.1, }, "to_station": { "name": "Edinburgh", "country": "gb", "latitude": 55.95, "longitude": -3.19, }, "legs": [ { "from": "London", "to": "Edinburgh", "depart": datetime(2026, 2, 4, 22, 0), "arrive": datetime(2026, 2, 5, 7, 0), "from_station": { "name": "London", "country": "gb", "latitude": 51.5, "longitude": -0.1, }, "to_station": { "name": "Edinburgh", "country": "gb", "latitude": 55.95, "longitude": -3.19, }, "coach": "S", "seat": 4, } ], } ], ) with web_view.app.app_context(): with ( mock.patch.object(web_view, "get_trip_list", return_value=[trip]), mock.patch.object(agenda.weather, "get_trip_weather", return_value=[]), ): web_view.app.config["TESTING"] = True with web_view.app.test_client() as client: response = client.get("/trip/2026-02-04") assert response.status_code == 200 page = response.data.decode() assert "🛏️ Coach S, Seat 4" in page