Remove obsolete connection template context

This commit is contained in:
Edward Betts 2026-05-27 00:27:16 +01:00
parent 1c230ce0d6
commit 5272956050
9 changed files with 423 additions and 229 deletions

View file

@ -73,12 +73,12 @@ def test_search_redirects_to_results_with_selected_params() -> None:
client = _client()
resp = client.get(
"/search?destination=rotterdam&travel_date=2026-04-10&min_connection=60&max_connection=120&station_crs=BRI"
"/search?destination=rotterdam&travel_date=2026-04-10&min_connection=60&station_crs=BRI"
)
assert resp.status_code == 302
assert resp.headers["Location"].endswith(
"/results/BRI/rotterdam/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/rotterdam/out/2026-04-10?min_connection=60"
)
@ -106,6 +106,35 @@ def test_search_redirects_inbound_to_back_path() -> None:
assert resp.headers["Location"].endswith("/results/BRI/paris/back/2026-04-10")
def test_search_uses_back_connection_fields_for_inbound() -> None:
client = _client()
resp = client.get(
"/search?journey_type=inbound&destination=paris&travel_date=2026-04-10"
"&station_crs=BRI&min_connection=50"
"&min_connection_back=40"
)
assert resp.status_code == 302
assert resp.headers["Location"].endswith(
"/results/BRI/paris/back/2026-04-10?min_connection=40"
)
def test_search_redirects_return_with_return_leg_connection() -> None:
client = _client()
resp = client.get(
"/search?journey_type=return&destination=paris&travel_date=2026-04-10"
"&return_date=2026-04-17&station_crs=BRI&min_connection_in=40"
)
assert resp.status_code == 302
assert resp.headers["Location"].endswith(
"/results/BRI/paris/return/2026-04-10/2026-04-17?min_connection_in=40"
)
def test_nr_weekday_cache_key_includes_timetable_period() -> None:
key = app_module._nr_weekday_cache_key("to_paddington", "BRI", "2026-06-22")
@ -117,7 +146,7 @@ def test_results_shows_same_day_destination_switcher(monkeypatch: Any) -> None:
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -125,11 +154,11 @@ def test_results_shows_same_day_destination_switcher(monkeypatch: Any) -> None:
assert "Switch destination for Friday 10 April 2026" in html
assert '<span class="chip-current">Paris Gare du Nord</span>' in html
assert (
"/results/BRI/brussels/out/2026-04-10?min_connection=60&amp;max_connection=120"
"/results/BRI/brussels/out/2026-04-10?min_connection=60"
in html
)
assert (
"/results/BRI/rotterdam/out/2026-04-10?min_connection=60&amp;max_connection=120"
"/results/BRI/rotterdam/out/2026-04-10?min_connection=60"
in html
)
assert "ES 9014" in html
@ -155,6 +184,13 @@ def test_results_can_render_from_weekday_timetable_cache(monkeypatch: Any) -> No
"train_number": "ES 9014",
},
],
app_module._walkon_weekday_cache_key("to_paddington", "BRI", travel_date): {
"07:00": {
"ticket": "Anytime Day Single",
"price": 138.70,
"code": "SDS",
},
},
}
monkeypatch.setattr(app_module, "get_cached", lambda key, ttl=None: cache.get(key))
monkeypatch.setattr(app_module, "set_cached", lambda key, data: None)
@ -182,7 +218,7 @@ def test_results_can_render_from_weekday_timetable_cache(monkeypatch: Any) -> No
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-06-22?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-06-22?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -190,6 +226,8 @@ def test_results_can_render_from_weekday_timetable_cache(monkeypatch: Any) -> No
assert "07:00 &rarr; 08:45" in html
assert "10:01 &rarr; 13:34" in html
assert "ES 9014" in html
assert "£138.70" in html
assert "Anytime Day Single" in html
assert "checking exact timetable" in html
assert "/api/results_refresh/BRI/paris/out/2026-06-22" in html
assert "refreshFullResults()" in html
@ -403,7 +441,7 @@ def test_results_title_and_social_meta_include_destination(monkeypatch: Any) ->
client = _client()
resp = client.get(
"/results/BRI/lille/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/lille/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -418,7 +456,7 @@ def test_results_title_and_social_meta_include_destination(monkeypatch: Any) ->
'to Lille Europe on Friday 10 April 2026 via Paddington, St Pancras, and Eurostar.">'
) in html
assert (
'<meta property="og:url" content="http://localhost/results/BRI/lille/out/2026-04-10?min_connection=60&amp;max_connection=120">'
'<meta property="og:url" content="http://localhost/results/BRI/lille/out/2026-04-10?min_connection=60">'
in html
)
@ -509,7 +547,7 @@ def test_results_marks_trips_within_five_minutes_of_fastest_and_slowest(
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -578,7 +616,7 @@ def test_results_shows_only_pre_first_reachable_unreachable_services(
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -594,7 +632,7 @@ def test_results_shows_eurostar_price_and_total(monkeypatch: Any) -> None:
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -651,7 +689,7 @@ def test_results_uses_unique_row_keys_for_same_eurostar(monkeypatch: Any) -> Non
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -696,7 +734,7 @@ def test_results_shows_unreachable_service_when_no_trips(monkeypatch: Any) -> No
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -714,7 +752,7 @@ def test_results_shows_eurostar_plus_price(monkeypatch: Any) -> None:
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -729,7 +767,7 @@ def test_results_selectors_present(monkeypatch: Any) -> None:
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)
@ -786,7 +824,7 @@ def test_results_preloads_cached_advance_fares(monkeypatch: Any) -> None:
client = _client()
resp = client.get(
"/results/BRI/paris/out/2026-04-10?min_connection=60&max_connection=120"
"/results/BRI/paris/out/2026-04-10?min_connection=60"
)
html = resp.get_data(as_text=True)

View file

@ -239,6 +239,72 @@ def _launch_browser(playwright: Any) -> Any:
pytest.skip(f"Chromium browser unavailable for Playwright: {exc}")
def test_back_search_uses_back_connection_defaults(local_server: str) -> None:
with sync_playwright() as p:
browser = _launch_browser(p)
page = browser.new_page()
page.goto(f"{local_server}/", wait_until="domcontentloaded")
page.locator("#journey-inbound").check(force=True)
assert page.locator("#outbound-connection-fields").is_hidden()
assert page.locator("#back-connection-fields").is_visible()
assert page.locator("#min_connection_back").input_value() == "30"
page.locator("#cal-next").click()
page.get_by_role("button", name="10 June 2026").click()
page.locator('button[type="submit"]').click()
page.wait_for_url("**/results/BRI/paris/back/2026-06-10", timeout=10000)
assert "min_connection=50" not in page.url
browser.close()
def test_progressive_results_do_not_redeclare_trip_fares(local_server: str) -> None:
with sync_playwright() as p:
browser = _launch_browser(p)
page = browser.new_page()
errors: list[str] = []
page.on("pageerror", lambda exc: errors.append(str(exc)))
page.on(
"console",
lambda msg: errors.append(msg.text) if msg.type == "error" else None,
)
page.goto(
f"{local_server}/results/BRI/brussels/return/2026-08-04/2026-08-11?progressive=1",
wait_until="domcontentloaded",
)
page.get_by_role(
"heading", name="Outbound: Bristol Temple Meads → Brussels Midi"
).wait_for(timeout=10000)
page.get_by_role(
"heading", name="Return: Brussels Midi → Bristol Temple Meads"
).wait_for(timeout=10000)
assert errors == []
assert "Could not load results" not in page.locator("body").inner_text()
browser.close()
def test_all_return_table_headers_are_sticky(local_server: str) -> None:
with sync_playwright() as p:
browser = _launch_browser(p)
page = browser.new_page()
page.goto(
f"{local_server}/results/BRI/brussels/return/2026-08-04/2026-08-11",
wait_until="domcontentloaded",
)
tables = page.locator(".results-table")
assert tables.count() == 2
for index in range(2):
positions = tables.nth(index).locator("thead th").evaluate_all(
"(headers) => headers.map((header) => getComputedStyle(header).position)"
)
assert positions == ["sticky", "sticky", "sticky", "sticky"]
browser.close()
def test_single_advance_standard_totals_after_click(single_server: str) -> None:
with sync_playwright() as p:
browser = _launch_browser(p)
@ -261,6 +327,81 @@ def test_single_advance_standard_totals_after_click(single_server: str) -> None:
browser.close()
def test_gwr_fare_update_keeps_existing_eurostar_price(single_server: str) -> None:
with sync_playwright() as p:
browser = _launch_browser(p)
page = browser.new_page()
page.goto(
f"{single_server}/results/BRI/paris/out/2026-07-20",
wait_until="domcontentloaded",
)
page.evaluate(
"""
() => {
eurostarRefreshPending = true;
mergeWalkonFares('main', {
'07:00': {
price: 138.70,
ticket: 'Anytime Day Single'
}
});
updateDisplay();
}
"""
)
page.wait_for_function(
"Array.from(document.querySelectorAll('.total-price'))"
".some(el => el.textContent.includes('£200.80'))",
timeout=10000,
)
assert "Checking Eurostar price" not in page.locator("body").inner_text()
browser.close()
def test_eurostar_fare_update_uses_existing_gwr_price(single_server: str) -> None:
with sync_playwright() as p:
browser = _launch_browser(p)
page = browser.new_page()
page.goto(
f"{single_server}/results/BRI/paris/out/2026-07-20",
wait_until="domcontentloaded",
)
page.evaluate(
"""
() => {
for (const key in TRIP_FARES) {
const row = TRIP_FARES[key];
row.walkon = {
price: 138.70,
ticket: 'Anytime Day Single'
};
row.es_standard = null;
row.es_standard_status = undefined;
}
eurostarRefreshPending = true;
updateDisplay();
mergeEurostarPrices({
'main:10:01': {
es_standard: {price: 59, seats: 42},
es_standard_status: null
}
});
updateDisplay();
}
"""
)
page.wait_for_function(
"Array.from(document.querySelectorAll('.total-price'))"
".some(el => el.textContent.includes('£200.80'))",
timeout=10000,
)
browser.close()
def test_single_next_date_advance_standard_labels_unreachable_rows(
monkeypatch: Any,
) -> None: