diff --git a/src/uk_bus_stops/static/app.js b/src/uk_bus_stops/static/app.js index fc6463a..d087557 100644 --- a/src/uk_bus_stops/static/app.js +++ b/src/uk_bus_stops/static/app.js @@ -124,6 +124,7 @@ function restoreSearchFromUrl() { : null; if (coordinates) { byId('search-input').value = `${coordinates.lat}, ${coordinates.lon}`; + showLocationImmediately({...coordinates, label: `${coordinates.lat}, ${coordinates.lon}`}); loadUrl(`${API_URLS.stops}?${new URLSearchParams(coordinates)}`); return; } @@ -358,10 +359,21 @@ function renderGeocodeChoices(data) { function chooseLocation(locationResult) { const coordinates = {lat: locationResult.lat, lon: locationResult.lon}; setSearchUrl(new URLSearchParams(coordinates)); + showLocationImmediately(locationResult); const apiParams = new URLSearchParams({...coordinates, label: locationResult.label}); loadUrl(`${API_URLS.stops}?${apiParams}`); } +/** Mark and zoom to known coordinates without waiting for the stop query. */ +function showLocationImmediately(locationResult) { + if (searchMarker) searchMarker.remove(); + searchMarker = L.circleMarker([locationResult.lat, locationResult.lon], { + radius: 7, color: '#0d6efd', fillColor: '#fff', fillOpacity: 1, weight: 3, + }).bindTooltip(locationResult.label || 'Search location').addTo(map); + if (isMobile()) setPanel(true); + moveMap(() => centrePointInVisibleMap(locationResult.lat, locationResult.lon, 16)); +} + /** Choose marker colours that make different transport modes easy to scan. */ function markerColour(stop) { const type = stop.transport_type || ''; @@ -619,6 +631,7 @@ byId('search-form').addEventListener('submit', event => { if (coordinates) { const params = new URLSearchParams(coordinates); setSearchUrl(params); + showLocationImmediately({...coordinates, label: `${coordinates.lat}, ${coordinates.lon}`}); loadUrl(`${API_URLS.stops}?${params}`); } else { const params = new URLSearchParams({q: query}); @@ -637,6 +650,7 @@ byId('locate-button').addEventListener('click', () => { const params = new URLSearchParams(coordinates); setSearchUrl(params); byId('search-input').value = `${coordinates.lat}, ${coordinates.lon}`; + showLocationImmediately({...coordinates, label: 'Your location'}); const apiParams = new URLSearchParams({...coordinates, label: 'Your location'}); loadUrl(`${API_URLS.stops}?${apiParams}`); }, diff --git a/tests/test_uk_bus_stops_playwright.py b/tests/test_uk_bus_stops_playwright.py index 8d58c05..11a1d35 100644 --- a/tests/test_uk_bus_stops_playwright.py +++ b/tests/test_uk_bus_stops_playwright.py @@ -197,6 +197,7 @@ def test_coordinate_url_and_search_input(chromium_browser: Any, flask_url: str) def test_single_postcode_match_opens_directly(chromium_browser: Any, flask_url: str) -> None: """A unique UK postcode result skips the location-choice panel.""" page = chromium_browser.new_page(viewport={"width": 1280, "height": 800}) + pending_stop_requests: list[Any] = [] page.route("**/api/search?*", lambda route: route.fulfill(json={ "kind": "geocode", "query": "SW1A 1AA", @@ -205,15 +206,19 @@ def test_single_postcode_match_opens_directly(chromium_browser: Any, flask_url: "type": "postcode", }], })) - page.route("**/api/stops?*", lambda route: route.fulfill(json={ - "kind": "location", - "location": {"lat": 51.501, "lon": -0.142, "label": "Westminster, London"}, - "stops": [], - })) + page.route("**/api/stops?*", lambda route: pending_stop_requests.append(route)) page.goto(flask_url, wait_until="networkidle") page.get_by_label("Location or ATCO code").fill("SW1A 1AA") page.get_by_role("button", name="Search").click() playwright_api.expect(page).to_have_url(re.compile(r"\?lat=51.501&lon=-0.142$")) + playwright_api.expect(page.locator(".leaflet-interactive")).to_have_count(1) + assert page.evaluate("map.getZoom()") == 16 + assert len(pending_stop_requests) == 1 + pending_stop_requests[0].fulfill(json={ + "kind": "location", + "location": {"lat": 51.501, "lon": -0.142, "label": "Westminster, London"}, + "stops": [], + }) playwright_api.expect(page.locator("#stop-count")).to_have_text("0 found") playwright_api.expect(page.locator("#geocode-panel")).to_be_hidden() page.close()