diff --git a/client/src/components/Planner/TransitSearchPanel.test.tsx b/client/src/components/Planner/TransitSearchPanel.test.tsx
index 6d0b66cb2..eb2296a0c 100644
--- a/client/src/components/Planner/TransitSearchPanel.test.tsx
+++ b/client/src/components/Planner/TransitSearchPanel.test.tsx
@@ -1,4 +1,4 @@
-// FE-PLANNER-TRANSIT-001 to FE-PLANNER-TRANSIT-027 — the transit search panel
+// FE-PLANNER-TRANSIT-001 to FE-PLANNER-TRANSIT-030 — the transit search panel
// (embedded as the TransportModal's Automated mode).
import { render, screen, fireEvent, waitFor } from '../../../tests/helpers/render'
import userEvent from '@testing-library/user-event'
@@ -36,6 +36,27 @@ const ITINERARY = {
],
}
+const stop = (name: string, lat: number, lng: number, time: string, track: string | null = null) =>
+ ({ name, lat, lng, time, scheduledTime: null, track })
+
+// The shape MOTIS actually returns for the reported connection: every journey is
+// bracketed in walking legs, and a change between two stations adds one in the
+// middle (#2106).
+const WALK_BRACKETED = {
+ startTime: '2025-06-01T06:30:00Z',
+ endTime: '2025-06-01T09:10:00Z',
+ duration: 9600,
+ transfers: 1,
+ walkSeconds: 1080,
+ legs: [
+ { mode: 'WALK', from: stop('Aachen, Bushof', 50.777, 6.09, '2025-06-01T06:30:00Z'), to: stop('Aachen Hbf', 50.768, 6.091, '2025-06-01T06:34:00Z'), duration: 240, distance: 300, headsign: null, line: null, lineColor: null, lineTextColor: null, agency: null, intermediateStops: 0 },
+ { mode: 'HIGHSPEED_RAIL', from: stop('Aachen Hbf', 50.768, 6.091, '2025-06-01T06:40:00Z', '2'), to: stop('Koeln Hbf', 50.943, 6.959, '2025-06-01T07:30:00Z'), duration: 3000, distance: null, headsign: 'Koeln', line: 'ICE 10', lineColor: null, lineTextColor: null, agency: 'DB', intermediateStops: 1 },
+ { mode: 'WALK', from: stop('Koeln Hbf', 50.943, 6.959, '2025-06-01T07:32:00Z'), to: stop('Koeln Messe/Deutz', 50.941, 6.974, '2025-06-01T07:40:00Z'), duration: 480, distance: 600, headsign: null, line: null, lineColor: null, lineTextColor: null, agency: null, intermediateStops: 0 },
+ { mode: 'HIGHSPEED_RAIL', from: stop('Koeln Messe/Deutz', 50.941, 6.974, '2025-06-01T07:50:00Z', '11'), to: stop('Frankfurt(Main)Hbf', 50.107, 8.663, '2025-06-01T08:57:00Z'), duration: 4020, distance: null, headsign: 'Frankfurt', line: 'ICE 610', lineColor: null, lineTextColor: null, agency: 'DB', intermediateStops: 2 },
+ { mode: 'WALK', from: stop('Frankfurt(Main)Hbf', 50.107, 8.663, '2025-06-01T09:00:00Z'), to: stop('Frankfurt Flughafen Fernbf', 50.053, 8.57, '2025-06-01T09:10:00Z'), duration: 600, distance: 800, headsign: null, line: null, lineColor: null, lineTextColor: null, agency: null, intermediateStops: 0 },
+ ],
+}
+
const day = buildDay({ id: 10, trip_id: 1, date: '2025-06-01', title: 'Berlin Day' })
function makeProps(overrides = {}) {
@@ -517,8 +538,59 @@ describe('TransitSearchPanel', () => {
await user.click(await screen.findByText(/08:30 – 09:00/))
expect(await screen.findByText('BVG')).toBeInTheDocument()
expect(screen.getByText(/Platform 2/)).toBeInTheDocument()
- expect(screen.getByText('Walk to Alexanderplatz')).toBeInTheDocument()
+ // Rows are anchored at the leg's start, so the access walk carries the picked
+ // origin and not the station the next row already names (#2106).
+ expect(screen.getByText('Start')).toBeInTheDocument()
+ expect(screen.queryByText('Walk to Alexanderplatz')).not.toBeInTheDocument()
expect(screen.getByText('300 m')).toBeInTheDocument()
expect(screen.getByText('6 stops')).toBeInTheDocument()
})
+
+ // #2106 — the walking legs printed their DESTINATION as the row heading, which is
+ // the stop the next row already names. The stop you actually get off at is a
+ // walking leg's origin, so it had no row at all and disappeared from the card.
+ it('FE-PLANNER-TRANSIT-028: the stop you get off at is listed, with the arrival time', async () => {
+ const user = userEvent.setup()
+ transitApiMock.plan.mockResolvedValueOnce({ itineraries: [WALK_BRACKETED] })
+ render(