Add return and inbound journey support
This commit is contained in:
parent
6ba71447ef
commit
9691632f65
12 changed files with 1687 additions and 486 deletions
|
|
@ -65,6 +65,17 @@ def test_search_redirects_to_results_with_selected_params():
|
|||
)
|
||||
|
||||
|
||||
def test_search_redirects_return_with_return_date():
|
||||
client = _client()
|
||||
|
||||
resp = client.get('/search?journey_type=return&destination=paris&travel_date=2026-04-10&return_date=2026-04-17&station_crs=BRI')
|
||||
|
||||
assert resp.status_code == 302
|
||||
assert resp.headers['Location'].endswith(
|
||||
'/results/BRI/paris/2026-04-10?journey_type=return&return_date=2026-04-17'
|
||||
)
|
||||
|
||||
|
||||
def test_results_shows_same_day_destination_switcher(monkeypatch):
|
||||
_stub_data(monkeypatch)
|
||||
client = _client()
|
||||
|
|
@ -290,6 +301,97 @@ def test_results_preloads_cached_advance_fares(monkeypatch):
|
|||
assert 'cachedAdvanceFares' in html
|
||||
|
||||
|
||||
def test_results_inbound_uses_reverse_legs(monkeypatch):
|
||||
monkeypatch.setattr(app_module, 'get_cached', lambda key, ttl=None: None)
|
||||
monkeypatch.setattr(app_module, 'set_cached', lambda key, data: None)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
'fetch_from_paddington',
|
||||
lambda travel_date, user_agent, station_crs='BRI': [
|
||||
{'depart_paddington': '17:15', 'arrive_destination': '18:55', 'headcode': '1B99'},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.gwr_fares_scraper,
|
||||
'fetch',
|
||||
lambda station_crs, travel_date, direction='to_paddington': {
|
||||
'17:15': {'ticket': 'Off-Peak Single', 'price': 63.60, 'code': 'SVS'}
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.eurostar_scraper,
|
||||
'fetch',
|
||||
lambda destination, travel_date, direction='outbound': [
|
||||
{'depart_destination': '15:12', 'arrive_st_pancras': '16:30',
|
||||
'destination': destination, 'train_number': 'ES 9035',
|
||||
'price': 49, 'seats': 43, 'plus_price': None, 'plus_seats': None},
|
||||
],
|
||||
)
|
||||
client = _client()
|
||||
|
||||
resp = client.get('/results/BRI/paris/2026-04-10?journey_type=inbound')
|
||||
html = resp.get_data(as_text=True)
|
||||
|
||||
assert resp.status_code == 200
|
||||
assert 'Paris Gare du Nord → Bristol Temple Meads' in html
|
||||
assert '15:12 → 16:30' in html
|
||||
assert '17:15 → 18:55' in html
|
||||
assert 'ES 9035' in html
|
||||
|
||||
|
||||
def test_results_return_renders_outbound_and_inbound_tables(monkeypatch):
|
||||
monkeypatch.setattr(app_module, 'get_cached', lambda key, ttl=None: None)
|
||||
monkeypatch.setattr(app_module, 'set_cached', lambda key, data: None)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
'fetch',
|
||||
lambda travel_date, user_agent, station_crs='BRI': [
|
||||
{'depart_bristol': '07:00', 'arrive_paddington': '08:45', 'headcode': '1A23'},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
'fetch_from_paddington',
|
||||
lambda travel_date, user_agent, station_crs='BRI': [
|
||||
{'depart_paddington': '17:15', 'arrive_destination': '18:55', 'headcode': '1B99'},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.gwr_fares_scraper,
|
||||
'fetch',
|
||||
lambda station_crs, travel_date, direction='to_paddington': {
|
||||
'07:00': {'ticket': 'Anytime Day Single', 'price': 138.70, 'code': 'SDS'},
|
||||
'17:15': {'ticket': 'Off-Peak Single', 'price': 63.60, 'code': 'SVS'},
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.eurostar_scraper,
|
||||
'fetch_return',
|
||||
lambda destination, outbound_date, return_date: {
|
||||
'outbound': [
|
||||
{'depart_st_pancras': '10:01', 'arrive_destination': '13:34',
|
||||
'destination': destination, 'train_number': 'ES 9014',
|
||||
'price': 59, 'seats': 42, 'plus_price': None, 'plus_seats': None},
|
||||
],
|
||||
'inbound': [
|
||||
{'depart_destination': '15:12', 'arrive_st_pancras': '16:30',
|
||||
'destination': destination, 'train_number': 'ES 9035',
|
||||
'price': 49, 'seats': 43, 'plus_price': None, 'plus_seats': None},
|
||||
],
|
||||
},
|
||||
)
|
||||
client = _client()
|
||||
|
||||
resp = client.get('/results/BRI/paris/2026-04-10?journey_type=return&return_date=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 'ES 9014' in html
|
||||
assert 'ES 9035' in html
|
||||
|
||||
|
||||
def test_api_advance_fares_returns_json(monkeypatch):
|
||||
monkeypatch.setattr(app_module, 'get_cached', lambda key, ttl=None: None)
|
||||
monkeypatch.setattr(app_module, 'set_cached', lambda key, data: None)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import pytest
|
||||
from scraper.eurostar import _parse_graphql, search_url
|
||||
from scraper.eurostar import _parse_graphql, _parse_graphql_leg, search_url
|
||||
|
||||
|
||||
def _gql_response(journeys: list) -> dict:
|
||||
|
|
@ -110,6 +110,24 @@ def test_parse_graphql_empty_journeys():
|
|||
assert _parse_graphql(data, 'Paris Gare du Nord') == []
|
||||
|
||||
|
||||
def test_parse_graphql_inbound_leg():
|
||||
data = {'data': {'journeySearch': {'inbound': {'journeys': [
|
||||
_journey('17:12', '18:30', price=49, seats=43, service_name='9035')
|
||||
]}}}}
|
||||
services = _parse_graphql_leg(data, 'Paris Gare du Nord', 'inbound', 'inbound')
|
||||
|
||||
assert services == [{
|
||||
'depart_destination': '17:12',
|
||||
'arrive_st_pancras': '18:30',
|
||||
'destination': 'Paris Gare du Nord',
|
||||
'train_number': 'ES 9035',
|
||||
'price': 49.0,
|
||||
'seats': 43,
|
||||
'plus_price': None,
|
||||
'plus_seats': None,
|
||||
}]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# search_url
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -120,3 +138,8 @@ def test_search_url():
|
|||
'https://www.eurostar.com/search/uk-en'
|
||||
'?adult=1&origin=7015400&destination=8727100&outbound=2026-04-10'
|
||||
)
|
||||
|
||||
|
||||
def test_search_url_return():
|
||||
url = search_url('Paris Gare du Nord', '2026-04-10', return_date='2026-04-17')
|
||||
assert url.endswith('&outbound=2026-04-10&inbound=2026-04-17')
|
||||
|
|
|
|||
422
tests/test_playwright_return_fares.py
Normal file
422
tests/test_playwright_return_fares.py
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
import threading
|
||||
|
||||
import pytest
|
||||
from werkzeug.serving import make_server
|
||||
|
||||
import app as app_module
|
||||
|
||||
playwright_sync = pytest.importorskip("playwright.sync_api")
|
||||
sync_playwright = playwright_sync.sync_playwright
|
||||
|
||||
|
||||
def _stub_return_data(monkeypatch):
|
||||
monkeypatch.setattr(app_module, "get_cached", lambda key, ttl=None: None)
|
||||
monkeypatch.setattr(app_module, "set_cached", lambda key, data: None)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
"fetch",
|
||||
lambda travel_date, user_agent, station_crs="BRI": [
|
||||
{
|
||||
"depart_bristol": "07:00",
|
||||
"arrive_paddington": "08:45",
|
||||
"headcode": "1A23",
|
||||
},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
"fetch_from_paddington",
|
||||
lambda travel_date, user_agent, station_crs="BRI": [
|
||||
{
|
||||
"depart_paddington": "17:15",
|
||||
"arrive_destination": "18:55",
|
||||
"headcode": "1B99",
|
||||
},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.gwr_fares_scraper,
|
||||
"fetch",
|
||||
lambda station_crs, travel_date, direction="to_paddington": {
|
||||
"07:00": {
|
||||
"ticket": "Anytime Day Single",
|
||||
"price": 138.70,
|
||||
"code": "SDS",
|
||||
},
|
||||
"17:15": {
|
||||
"ticket": "Off-Peak Single",
|
||||
"price": 63.60,
|
||||
"code": "SVS",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def fake_advance_streaming(station_crs, travel_date, direction="to_paddington"):
|
||||
if direction == "from_paddington":
|
||||
yield {
|
||||
"17:15": {
|
||||
"advance_std": {
|
||||
"ticket": "Advance Single",
|
||||
"price": 25.0,
|
||||
"code": "ADV",
|
||||
},
|
||||
"advance_1st": {
|
||||
"ticket": "1st Advance",
|
||||
"price": 45.0,
|
||||
"code": "AFA",
|
||||
},
|
||||
}
|
||||
}
|
||||
else:
|
||||
yield {
|
||||
"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_streaming",
|
||||
fake_advance_streaming,
|
||||
)
|
||||
|
||||
def fake_advance(station_crs, travel_date, direction="to_paddington"):
|
||||
pages = list(fake_advance_streaming(station_crs, travel_date, direction))
|
||||
return pages[0] if pages else {}
|
||||
|
||||
monkeypatch.setattr(app_module.gwr_fares_scraper, "fetch_advance", fake_advance)
|
||||
monkeypatch.setattr(
|
||||
app_module.eurostar_scraper,
|
||||
"fetch_return",
|
||||
lambda destination, outbound_date, return_date: {
|
||||
"outbound": [
|
||||
{
|
||||
"depart_st_pancras": "10:01",
|
||||
"arrive_destination": "13:34",
|
||||
"destination": destination,
|
||||
"train_number": "ES 9014",
|
||||
"price": 59,
|
||||
"seats": 42,
|
||||
"plus_price": 89,
|
||||
"plus_seats": 5,
|
||||
},
|
||||
],
|
||||
"inbound": [
|
||||
{
|
||||
"depart_destination": "15:12",
|
||||
"arrive_st_pancras": "16:30",
|
||||
"destination": destination,
|
||||
"train_number": "ES 9035",
|
||||
"price": 49,
|
||||
"seats": 43,
|
||||
"plus_price": 79,
|
||||
"plus_seats": 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def _stub_single_data(monkeypatch):
|
||||
monkeypatch.setattr(app_module, "get_cached", lambda key, ttl=None: None)
|
||||
monkeypatch.setattr(app_module, "set_cached", lambda key, data: None)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
"fetch",
|
||||
lambda travel_date, user_agent, station_crs="BRI": [
|
||||
{
|
||||
"depart_bristol": "07:00",
|
||||
"arrive_paddington": "08:45",
|
||||
"headcode": "1A23",
|
||||
},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.gwr_fares_scraper,
|
||||
"fetch",
|
||||
lambda station_crs, travel_date: {
|
||||
"07:00": {
|
||||
"ticket": "Anytime Day Single",
|
||||
"price": 138.70,
|
||||
"code": "SDS",
|
||||
},
|
||||
},
|
||||
)
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.eurostar_scraper,
|
||||
"fetch",
|
||||
lambda destination, travel_date: [
|
||||
{
|
||||
"depart_st_pancras": "10:01",
|
||||
"arrive_destination": "13:34",
|
||||
"destination": destination,
|
||||
"train_number": "ES 9014",
|
||||
"price": 59,
|
||||
"seats": 42,
|
||||
"plus_price": 89,
|
||||
"plus_seats": 5,
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_server(monkeypatch):
|
||||
_stub_return_data(monkeypatch)
|
||||
app_module.app.config["TESTING"] = True
|
||||
server = make_server("127.0.0.1", 0, app_module.app)
|
||||
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
try:
|
||||
yield f"http://127.0.0.1:{server.server_port}"
|
||||
finally:
|
||||
server.shutdown()
|
||||
thread.join(timeout=5)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def single_server(monkeypatch):
|
||||
_stub_single_data(monkeypatch)
|
||||
app_module.app.config["TESTING"] = True
|
||||
server = make_server("127.0.0.1", 0, app_module.app)
|
||||
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
try:
|
||||
yield f"http://127.0.0.1:{server.server_port}"
|
||||
finally:
|
||||
server.shutdown()
|
||||
thread.join(timeout=5)
|
||||
|
||||
|
||||
def _launch_browser(playwright):
|
||||
try:
|
||||
return playwright.chromium.launch(headless=True)
|
||||
except Exception as exc:
|
||||
pytest.skip(f"Chromium browser unavailable for Playwright: {exc}")
|
||||
|
||||
|
||||
def test_single_advance_standard_totals_after_click(single_server):
|
||||
with sync_playwright() as p:
|
||||
browser = _launch_browser(p)
|
||||
page = browser.new_page()
|
||||
page.goto(
|
||||
f"{single_server}/results/BRI/paris/2026-07-20",
|
||||
wait_until="domcontentloaded",
|
||||
)
|
||||
|
||||
page.get_by_role("button", name="Advance Std").click()
|
||||
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£112.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
assert "nr_class=advance_std" in page.url
|
||||
totals = [el.inner_text() for el in page.locator(".total-price").all()]
|
||||
assert totals == ["£112.10"]
|
||||
browser.close()
|
||||
|
||||
|
||||
def test_single_next_date_advance_standard_labels_unreachable_rows(monkeypatch):
|
||||
monkeypatch.setattr(app_module, "get_cached", lambda key, ttl=None: None)
|
||||
monkeypatch.setattr(app_module, "set_cached", lambda key, data: None)
|
||||
monkeypatch.setattr(
|
||||
app_module.rtt_scraper,
|
||||
"fetch",
|
||||
lambda travel_date, user_agent, station_crs="BRI": [
|
||||
{
|
||||
"depart_bristol": "07:00",
|
||||
"arrive_paddington": "08:45",
|
||||
"headcode": "1A23",
|
||||
},
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.gwr_fares_scraper,
|
||||
"fetch",
|
||||
lambda station_crs, travel_date: {
|
||||
"07:00": {
|
||||
"ticket": "Anytime Day Single",
|
||||
"price": 138.70,
|
||||
"code": "SDS",
|
||||
},
|
||||
},
|
||||
)
|
||||
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,
|
||||
},
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
app_module.eurostar_scraper,
|
||||
"fetch",
|
||||
lambda destination, travel_date: [
|
||||
{
|
||||
"depart_st_pancras": "09:30",
|
||||
"arrive_destination": "12:30",
|
||||
"destination": destination,
|
||||
"train_number": "ES 9001",
|
||||
"price": 59,
|
||||
"seats": 42,
|
||||
"plus_price": None,
|
||||
"plus_seats": None,
|
||||
},
|
||||
{
|
||||
"depart_st_pancras": "10:01",
|
||||
"arrive_destination": "13:34",
|
||||
"destination": destination,
|
||||
"train_number": "ES 9014",
|
||||
"price": 59,
|
||||
"seats": 42,
|
||||
"plus_price": None,
|
||||
"plus_seats": None,
|
||||
},
|
||||
],
|
||||
)
|
||||
app_module.app.config["TESTING"] = True
|
||||
server = make_server("127.0.0.1", 0, app_module.app)
|
||||
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
try:
|
||||
with sync_playwright() as p:
|
||||
browser = _launch_browser(p)
|
||||
page = browser.new_page()
|
||||
page.goto(
|
||||
f"http://127.0.0.1:{server.server_port}"
|
||||
"/results/BRI/brussels/2026-06-16",
|
||||
wait_until="domcontentloaded",
|
||||
)
|
||||
page.get_by_role("link", name="Next →").click()
|
||||
page.wait_for_url("**/2026-06-17**", timeout=10000)
|
||||
page.get_by_role("button", name="Advance Std").click()
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£112.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
assert page.get_by_text("No connection").count() == 1
|
||||
totals = [el.inner_text() for el in page.locator(".total-price").all()]
|
||||
assert totals == ["£112.10"]
|
||||
browser.close()
|
||||
finally:
|
||||
server.shutdown()
|
||||
thread.join(timeout=5)
|
||||
|
||||
|
||||
def test_single_advance_standard_premier_totals_on_initial_url(single_server):
|
||||
with sync_playwright() as p:
|
||||
browser = _launch_browser(p)
|
||||
page = browser.new_page()
|
||||
page.goto(
|
||||
f"{single_server}/results/BRI/paris/2026-07-20"
|
||||
"?nr_class=advance_std&es_class=plus",
|
||||
wait_until="domcontentloaded",
|
||||
)
|
||||
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£142.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
totals = [el.inner_text() for el in page.locator(".total-price").all()]
|
||||
assert totals == ["£142.10"]
|
||||
browser.close()
|
||||
|
||||
|
||||
def test_return_advance_first_standard_premier_totals(local_server):
|
||||
with sync_playwright() as p:
|
||||
browser = _launch_browser(p)
|
||||
page = browser.new_page()
|
||||
page.goto(f"{local_server}/", wait_until="domcontentloaded")
|
||||
page.locator("#journey-return").check(force=True)
|
||||
page.locator("#destination-paris").check(force=True)
|
||||
page.locator("#travel_date").fill("2026-07-20")
|
||||
page.locator("#return_date").fill("2026-07-27")
|
||||
page.locator('button[type="submit"]').click()
|
||||
page.wait_for_url("**/results/**", timeout=10000)
|
||||
|
||||
page.get_by_role("button", name="Advance 1st").click()
|
||||
page.get_by_role("button", name="Standard Premier").click()
|
||||
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£172.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£127.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
assert "journey_type=return" in page.url
|
||||
assert "return_date=2026-07-27" 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"]
|
||||
browser.close()
|
||||
|
||||
|
||||
def test_return_advance_first_standard_premier_totals_on_initial_url(local_server):
|
||||
with sync_playwright() as p:
|
||||
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",
|
||||
wait_until="domcontentloaded",
|
||||
)
|
||||
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£172.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
page.wait_for_function(
|
||||
"Array.from(document.querySelectorAll('.total-price'))"
|
||||
".some(el => el.textContent.includes('£127.10'))",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
totals = [el.inner_text() for el in page.locator(".total-price").all()]
|
||||
assert totals == ["£172.10 high", "£127.10 low"]
|
||||
browser.close()
|
||||
|
|
@ -1,5 +1,10 @@
|
|||
import pytest
|
||||
from trip_planner import combine_trips, find_unreachable_morning_eurostars, _fmt_duration
|
||||
from trip_planner import (
|
||||
combine_inbound_trips,
|
||||
combine_trips,
|
||||
find_unreachable_morning_eurostars,
|
||||
_fmt_duration,
|
||||
)
|
||||
|
||||
DATE = '2026-03-30'
|
||||
|
||||
|
|
@ -178,3 +183,28 @@ def test_find_unreachable_eurostars_returns_empty_when_all_connectable():
|
|||
]
|
||||
|
||||
assert find_unreachable_morning_eurostars(gwr, eurostar, DATE) == []
|
||||
|
||||
|
||||
def test_combine_inbound_trips_pairs_eurostar_to_paddington_departure():
|
||||
eurostar = [{
|
||||
'depart_destination': '15:12',
|
||||
'arrive_st_pancras': '16:30',
|
||||
'destination': 'Paris Gare du Nord',
|
||||
'train_number': 'ES 9035',
|
||||
}]
|
||||
gwr = [{
|
||||
'depart_paddington': '17:15',
|
||||
'arrive_destination': '18:55',
|
||||
'headcode': '1B99',
|
||||
}]
|
||||
fares = {'17:15': {'ticket': 'Off-Peak Single', 'price': 63.60, 'code': 'SVS'}}
|
||||
|
||||
trips = combine_inbound_trips(eurostar, gwr, DATE, min_connection_minutes=30, max_connection_minutes=120, gwr_fares=fares)
|
||||
|
||||
assert len(trips) == 1
|
||||
assert trips[0]['depart_destination'] == '15:12'
|
||||
assert trips[0]['arrive_st_pancras'] == '16:30'
|
||||
assert trips[0]['depart_paddington'] == '17:15'
|
||||
assert trips[0]['arrive_uk_station'] == '18:55'
|
||||
assert trips[0]['ticket_price'] == 63.60
|
||||
assert trips[0]['check_in_by'] == '14:42'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue