309 lines
11 KiB
Python
309 lines
11 KiB
Python
"""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
|