import { describe, it, expect } from 'vitest' import { getFlightLegs, getTrainLegs, isMultiLegTrain, stripAirportCode, usesStationRoute } from './flightLegs' import type { Reservation } from '../types' function res(partial: Partial): Reservation { return { id: 1, type: 'train', status: 'confirmed', ...partial } as unknown as Reservation } const ep = (role: 'from' | 'to' | 'stop', seq: number, name: string, extra: Record = {}) => ({ role, sequence: seq, name, code: null, lat: 0, lng: 0, timezone: null, local_time: null, local_date: null, ...extra }) describe('getTrainLegs (#1150)', () => { it('reads ordered legs from metadata.legs', () => { const r = res({ metadata: JSON.stringify({ train_number: 'ICE 100', platform: '5', legs: [ { from: 'Berlin Hbf', to: 'Frankfurt Hbf', train_number: 'ICE 100', platform: '5', dep_time: '08:00', arr_time: '12:00' }, { from: 'Frankfurt Hbf', to: 'München Hbf', train_number: 'ICE 500', platform: '9', dep_time: '12:30', arr_time: '15:30' }, ], }), }) const legs = getTrainLegs(r) expect(legs).toHaveLength(2) expect(legs[0]).toMatchObject({ from: 'Berlin Hbf', to: 'Frankfurt Hbf', train_number: 'ICE 100', platform: '5' }) expect(legs[1]).toMatchObject({ from: 'Frankfurt Hbf', to: 'München Hbf', train_number: 'ICE 500', platform: '9' }) expect(isMultiLegTrain(r)).toBe(true) }) it('derives a single leg from endpoints + flat metadata (legacy train)', () => { const r = res({ day_id: 3, end_day_id: 3, metadata: JSON.stringify({ train_number: 'RE 42', platform: '2' }), endpoints: [ep('from', 0, 'Köln Hbf', { local_time: '09:00' }), ep('to', 1, 'Aachen Hbf', { local_time: '10:00' })], }) const legs = getTrainLegs(r) expect(legs).toHaveLength(1) expect(legs[0]).toMatchObject({ from: 'Köln Hbf', to: 'Aachen Hbf', train_number: 'RE 42', platform: '2', dep_time: '09:00', arr_time: '10:00' }) expect(isMultiLegTrain(r)).toBe(false) }) it('returns [] for a train with no stations and no train number', () => { expect(getTrainLegs(res({ metadata: '{}' }))).toEqual([]) }) it('does not disturb getFlightLegs for flights', () => { const flight = res({ type: 'flight', metadata: JSON.stringify({ departure_airport: 'FRA', arrival_airport: 'JFK', airline: 'LH', flight_number: 'LH 400' }) }) const legs = getFlightLegs(flight) expect(legs).toHaveLength(1) expect(legs[0]).toMatchObject({ from: 'FRA', to: 'JFK', airline: 'LH', flight_number: 'LH 400' }) }) }) describe('per-segment booking references (#1943)', () => { it('reads each segment its own code, and leaves a code-less segment undefined', () => { const flight = res({ type: 'flight', confirmation_number: 'BOOK1', metadata: JSON.stringify({ legs: [ { from: 'FRA', to: 'BER', confirmation_number: 'ABC123' }, { from: 'BER', to: 'HND' }, ], }), }) const legs = getFlightLegs(flight) expect(legs[0].confirmation_number).toBe('ABC123') // No fallback to the booking's own code: a segment either has one or it does // not, and the booking's reference is shown separately. expect(legs[1].confirmation_number).toBeUndefined() }) it('reads a train segment code the same way', () => { const train = res({ metadata: JSON.stringify({ legs: [ { from: 'Berlin Hbf', to: 'Frankfurt Hbf', confirmation_number: 'DB-1' }, { from: 'Frankfurt Hbf', to: 'München Hbf', confirmation_number: 'DB-2' }, ], }), }) expect(getTrainLegs(train).map(l => l.confirmation_number)).toEqual(['DB-1', 'DB-2']) }) it('gives the derived single leg of a legacy booking the booking code', () => { const flight = res({ type: 'flight', confirmation_number: 'BOOK1', day_id: 3, metadata: JSON.stringify({ departure_airport: 'FRA', arrival_airport: 'JFK' }), }) expect(getFlightLegs(flight)[0].confirmation_number).toBe('BOOK1') const train = res({ confirmation_number: 'BOOK2', endpoints: [ep('from', 0, 'Köln Hbf'), ep('to', 1, 'Aachen Hbf')], metadata: '{}', }) expect(getTrainLegs(train)[0].confirmation_number).toBe('BOOK2') }) }) describe('stripAirportCode', () => { it('drops the code the forms and the airport backfill append, and nothing else', () => { expect(stripAirportCode('Paris Charles de Gaulle (CDG)')).toBe('Paris Charles de Gaulle') expect(stripAirportCode('Hamburg (HAM) ')).toBe('Hamburg') // A station has no such suffix, and a bracket that is not a code stays. expect(stripAirportCode('Hamburg Hbf')).toBe('Hamburg Hbf') expect(stripAirportCode('Frankfurt (Main)')).toBe('Frankfurt (Main)') expect(stripAirportCode('Munich (muc)')).toBe('Munich (muc)') }) }) describe('usesStationRoute (#1807)', () => { it('covers trains and cruises, nothing else', () => { expect(usesStationRoute('train')).toBe(true) expect(usesStationRoute('cruise')).toBe(true) expect(usesStationRoute('ferry')).toBe(false) expect(usesStationRoute(null)).toBe(false) }) })