Improve progressive results loading

This commit is contained in:
Edward Betts 2026-05-21 09:52:58 +01:00
parent 9691632f65
commit 378d2484d0
6 changed files with 369 additions and 60 deletions

View file

@ -1,4 +1,7 @@
from datetime import datetime
import app as app_module
import trip_planner as trip_planner_module
def _client():
@ -72,7 +75,7 @@ def test_search_redirects_return_with_return_date():
assert resp.status_code == 302
assert resp.headers['Location'].endswith(
'/results/BRI/paris/2026-04-10?journey_type=return&return_date=2026-04-17'
'/results/BRI/paris/2026-04-10/return/2026-04-17'
)
@ -91,6 +94,23 @@ def test_results_shows_same_day_destination_switcher(monkeypatch):
assert 'ES 9014' in html
def test_results_progressive_shell_loads_without_scraping(monkeypatch):
def fail_fetch(*args, **kwargs):
raise AssertionError("progressive shell should not fetch data")
monkeypatch.setattr(app_module.rtt_scraper, 'fetch', fail_fetch)
monkeypatch.setattr(app_module.eurostar_scraper, 'fetch', fail_fetch)
monkeypatch.setattr(app_module.gwr_fares_scraper, 'fetch', fail_fetch)
client = _client()
resp = client.get('/results/BRI/paris/2026-04-10?progressive=1')
html = resp.get_data(as_text=True)
assert resp.status_code == 200
assert 'Loading train times and fares' in html
assert 'render=full' in html
def test_results_title_and_social_meta_include_destination(monkeypatch):
_stub_data(monkeypatch)
client = _client()
@ -380,14 +400,39 @@ def test_results_return_renders_outbound_and_inbound_tables(monkeypatch):
],
},
)
monkeypatch.setattr(
trip_planner_module.circle_line,
'upcoming_services',
lambda earliest_board, count=2, direction='pad_to_kx': (
[
(datetime(2026, 4, 10, 9, 10), datetime(2026, 4, 10, 9, 25)),
(datetime(2026, 4, 10, 9, 15), datetime(2026, 4, 10, 9, 30)),
]
if direction == 'pad_to_kx'
else [
(datetime(2026, 4, 17, 16, 40), datetime(2026, 4, 17, 16, 55)),
(datetime(2026, 4, 17, 16, 45), datetime(2026, 4, 17, 17, 0)),
]
),
)
client = _client()
resp = client.get('/results/BRI/paris/2026-04-10?journey_type=return&return_date=2026-04-17')
resp = client.get('/results/BRI/paris/2026-04-10/return/2026-04-17')
html = resp.get_data(as_text=True)
assert resp.status_code == 200
assert 'Outbound: Bristol Temple Meads → Paris Gare du Nord' in html
assert 'Return: Paris Gare du Nord → Bristol Temple Meads' in html
assert '/results/BRI/paris/2026-04-09/return/2026-04-17' in html
assert '/results/BRI/paris/2026-04-11/return/2026-04-17' in html
assert "/results/BRI/paris/2026-04-10/return/2026-04-17" in html
assert 'journey_type=return' not in html
assert 'return_date=2026-04-17' not in html
assert 'Circle 09:10 → KX 09:25' in html
assert 'next 09:15 → KX 09:30' in html
assert 'Circle 16:40 → PAD 16:55' in html
assert 'next 16:45 → PAD 17:00' in html
assert 'title="Tight connection">⚠️</span>' in html
assert 'ES 9014' in html
assert 'ES 9035' in html

View file

@ -151,23 +151,29 @@ def _stub_single_data(monkeypatch):
},
},
)
advance_fares = {
"07:00": {
"advance_std": {
"ticket": "Advance Single",
"price": 50.0,
"code": "ADV",
},
"advance_1st": {
"ticket": "1st Advance",
"price": 80.0,
"code": "AFA",
},
},
}
monkeypatch.setattr(
app_module.gwr_fares_scraper,
"fetch_advance",
lambda station_crs, travel_date: {
"07:00": {
"advance_std": {
"ticket": "Advance Single",
"price": 50.0,
"code": "ADV",
},
"advance_1st": {
"ticket": "1st Advance",
"price": 80.0,
"code": "AFA",
},
},
},
lambda station_crs, travel_date: advance_fares,
)
monkeypatch.setattr(
app_module.gwr_fares_scraper,
"fetch_advance_streaming",
lambda station_crs, travel_date: iter([advance_fares]),
)
monkeypatch.setattr(
app_module.eurostar_scraper,
@ -269,19 +275,25 @@ def test_single_next_date_advance_standard_labels_unreachable_rows(monkeypatch):
},
},
)
advance_fares = {
"07:00": {
"advance_std": {
"ticket": "Advance Single",
"price": 50.0,
"code": "ADV",
},
"advance_1st": None,
},
}
monkeypatch.setattr(
app_module.gwr_fares_scraper,
"fetch_advance",
lambda station_crs, travel_date: {
"07:00": {
"advance_std": {
"ticket": "Advance Single",
"price": 50.0,
"code": "ADV",
},
"advance_1st": None,
},
},
lambda station_crs, travel_date: advance_fares,
)
monkeypatch.setattr(
app_module.gwr_fares_scraper,
"fetch_advance_streaming",
lambda station_crs, travel_date: iter([advance_fares]),
)
monkeypatch.setattr(
app_module.eurostar_scraper,
@ -386,12 +398,13 @@ def test_return_advance_first_standard_premier_totals(local_server):
timeout=10000,
)
assert "journey_type=return" in page.url
assert "return_date=2026-07-27" in page.url
assert "/results/BRI/paris/2026-07-20/return/2026-07-27" in page.url
assert "journey_type=return" not in page.url
assert "return_date=2026-07-27" not in page.url
assert "nr_class=advance_1st" in page.url
assert "es_class=plus" in page.url
totals = [el.inner_text() for el in page.locator(".total-price").all()]
assert totals == ["£172.10 high", "£127.10 low"]
assert totals == ["£172.10 💸", "£127.10 🪙"]
browser.close()
@ -400,9 +413,8 @@ def test_return_advance_first_standard_premier_totals_on_initial_url(local_serve
browser = _launch_browser(p)
page = browser.new_page()
page.goto(
f"{local_server}/results/BRI/paris/2026-07-20"
"?journey_type=return&return_date=2026-07-27"
"&nr_class=advance_1st&es_class=plus",
f"{local_server}/results/BRI/paris/2026-07-20/return/2026-07-27"
"?nr_class=advance_1st&es_class=plus",
wait_until="domcontentloaded",
)
@ -418,5 +430,5 @@ def test_return_advance_first_standard_premier_totals_on_initial_url(local_serve
)
totals = [el.inner_text() for el in page.locator(".total-price").all()]
assert totals == ["£172.10 high", "£127.10 low"]
assert totals == ["£172.10 💸", "£127.10 🪙"]
browser.close()