diff --git a/api.js b/api.js index 05b83d81..75f31379 100644 --- a/api.js +++ b/api.js @@ -3,6 +3,8 @@ import {profile as dbProfile} from './p/db/index.js'; import {profile as dbnavProfile} from './p/dbnav/index.js'; import {profile as dbwebProfile} from './p/dbweb/index.js'; import {profile as dbrisProfile} from './p/dbris/index.js'; +import {profile as dbbahnhofProfile} from './p/dbbahnhof/index.js'; +import {profile as dbregioguideProfile} from './p/dbregioguide/index.js'; import {mapRouteParsers} from './lib/api-parsers.js'; import {createHafasRestApi as createApi} from 'hafas-rest-api'; @@ -28,6 +30,8 @@ const profiles = { dbnav: dbnavProfile, dbweb: dbwebProfile, dbris: dbrisProfile, + dbbahnhof: dbbahnhofProfile, + dbregioguide: dbregioguideProfile, }; const start = async () => { diff --git a/cspell.config.json b/cspell.config.json index 5f40ffd4..4a450270 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -625,11 +625,14 @@ "bestprice", "intervalle", "Intervalle", - "tagesbest" + "tagesbest", + "dbbahnhof", + "cancelation" ], "ignorePaths": [ "docs/dumps/**", "test/e2e/fixtures/**", + "test/fixtures/**", "test/parse/remarks.js", "test/parse/dbnav-journey.js" ], diff --git a/index.js b/index.js index 2ad93bea..9cc4d079 100644 --- a/index.js +++ b/index.js @@ -99,6 +99,7 @@ const createClient = (profile, userAgent, opt = {}) => { // departures at related stations // e.g. those that belong together on the metro map. includeRelatedStations: true, + moreStops: null, // also include departures/arrivals for array of up to nine additional station evaNumbers (not supported with dbnav and dbweb) }, opt); opt.when = new Date(opt.when || Date.now()); if (Number.isNaN(Number(opt.when))) { @@ -110,7 +111,7 @@ const createClient = (profile, userAgent, opt = {}) => { const {res} = await profile.request({profile, opt}, userAgent, req); const ctx = {profile, opt, common, res}; - let results = (res[resultsField] || res.items || res.bahnhofstafelAbfahrtPositionen || res.bahnhofstafelAnkunftPositionen || res.entries) + let results = (res[resultsField] || res.items || res.bahnhofstafelAbfahrtPositionen || res.bahnhofstafelAnkunftPositionen || res.entries.flat()) .map(res => parse(ctx, res)); // TODO sort?, slice if (!opt.includeRelatedStations) { diff --git a/lib/request.js b/lib/request.js index 386eee6b..32247de6 100644 --- a/lib/request.js +++ b/lib/request.js @@ -67,9 +67,9 @@ const checkIfResponseIsOk = (_) => { }; }; - if (body.fehlerNachricht) { // TODO better handling + if (body.fehlerNachricht || body.errors) { // TODO better handling const {Error: HafasError, message, props} = getError(body); - throw new HafasError(message, body.err, {...errProps, ...props}); + throw new HafasError(message, body.err || body.errors, {...errProps, ...props}); } }; @@ -105,6 +105,7 @@ const request = async (ctx, userAgent, reqData) => { if (reqOptions.query) { url += '?' + stringify(reqOptions.query, {arrayFormat: 'brackets', encodeValuesOnly: true}); } + console.log(url); const reqId = randomBytesHexString(6); const fetchReq = new Request(url, reqOptions); profile.logRequest(ctx, fetchReq, reqId); diff --git a/p/dbbahnhof/base.json b/p/dbbahnhof/base.json new file mode 100644 index 00000000..6493b108 --- /dev/null +++ b/p/dbbahnhof/base.json @@ -0,0 +1,4 @@ +{ + "boardEndpoint": "https://www.bahnhof.de/api/boards/", + "defaultLanguage": "en" +} diff --git a/p/dbbahnhof/index.js b/p/dbbahnhof/index.js new file mode 100644 index 00000000..b5764dde --- /dev/null +++ b/p/dbbahnhof/index.js @@ -0,0 +1,31 @@ +import baseProfile from './base.json' with { type: 'json' }; +import {products} from '../../lib/products.js'; +import {formatStationBoardReq} from './station-board-req.js'; + +const profile = { + ...baseProfile, + locale: 'de-DE', + timezone: 'Europe/Berlin', + + products, + + formatStationBoardReq, + + journeysOutFrwd: false, + departuresGetPasslist: true, + departuresStbFltrEquiv: true, + trip: false, + radar: false, + refreshJourney: false, + journeysFromTrip: false, + refreshJourneyUseOutReconL: false, + tripsByName: false, + remarks: false, + remarksGetPolyline: false, + reachableFrom: false, + lines: false, +}; + +export { + profile, +}; diff --git a/p/dbbahnhof/station-board-req.js b/p/dbbahnhof/station-board-req.js new file mode 100644 index 00000000..0a711f24 --- /dev/null +++ b/p/dbbahnhof/station-board-req.js @@ -0,0 +1,30 @@ +import {stringify} from 'qs'; + +const formatStationBoardReq = (ctx, station, type) => { + const {profile, opt} = ctx; + + if (opt.departure || opt.arrival) { + throw new Error('opt.departure/opt.arrival is not supported for profile dbbahnhof, can only query for current time.'); + } + const evaNumbers = [station]; + if (opt.moreStops) { + evaNumbers.push(...opt.moreStops); + } + const query = { + filterTransports: profile.formatProductsFilter(ctx, opt.products || {}, 'ris_alt'), + evaNumbers: evaNumbers, + duration: opt.duration, + sortBy: 'TIME_SCHEDULE', + locale: opt.language, + }; + + return { + endpoint: profile.boardEndpoint, + path: type + '?' + stringify(query, {arrayFormat: 'repeat', encodeValuesOnly: true}), + method: 'get', + }; +}; + +export { + formatStationBoardReq, +}; diff --git a/parse/arrival-or-departure.js b/parse/arrival-or-departure.js index 27231bb6..69003e07 100644 --- a/parse/arrival-or-departure.js +++ b/parse/arrival-or-departure.js @@ -11,12 +11,12 @@ const createParseArrOrDep = (prefix) => { const cancelled = profile.parseCancelled(d); const res = { tripId: d.journeyID || d.journeyId || d.train?.journeyId || d.zuglaufId, - stop: profile.parseLocation(ctx, d.station || d.abfrageOrt || {bahnhofsId: d.bahnhofsId}), + stop: profile.parseLocation(ctx, d.station || d.abfrageOrt || d.stopPlace || {bahnhofsId: d.bahnhofsId}), ...profile.parseWhen( ctx, null, d.timeSchedule || d.time || d.zeit || d.abgangsDatum || d.ankunftsDatum, - d.timeType != 'SCHEDULE' ? d.timePredicted || d.time || d.ezZeit || d.ezAbgangsDatum || d.ezAnkunftsDatum : null, + d.timeType != 'SCHEDULE' ? d.timePredicted || d.timeDelayed || d.time || d.ezZeit || d.ezAbgangsDatum || d.ezAnkunftsDatum : null, cancelled), ...profile.parsePlatform(ctx, d.platformSchedule || d.platform || d.gleis, d.platformPredicted || d.platform || d.ezGleis, cancelled), // prognosisType: TODO @@ -45,8 +45,8 @@ const createParseArrOrDep = (prefix) => { if (Array.isArray(d.ueber)) { stopovers = d.ueber .map(viaName => profile.parseStopover(ctx, {name: viaName}, null)); - } else if (Array.isArray(d.transport?.via)) { - stopovers = (d.transport?.via) + } else if (Array.isArray(d.transport?.via) || Array.isArray(d.viaStops)) { + stopovers = (d.transport?.via || d.viaStops) .map(via => profile.parseStopover(ctx, via, null)); } if (stopovers) { diff --git a/parse/line.js b/parse/line.js index 9f1974f1..0d972782 100644 --- a/parse/line.js +++ b/parse/line.js @@ -2,20 +2,20 @@ import slugg from 'slugg'; const parseLine = (ctx, p) => { const profile = ctx.profile; - const fahrtNr = p.verkehrsmittel?.nummer || p.transport?.number || p.train?.no || p.no || ((p.risZuglaufId || '') + '_').split('_')[1] || p.verkehrsmittelNummer || (p.verkehrmittel?.langText || p.verkehrsmittel?.langText || p.mitteltext || p.zugName || '').replace(/\D/g, ''); + const fahrtNr = p.verkehrsmittel?.nummer || p.transport?.number || p.train?.no || p.no || ((p.risZuglaufId || '') + '_').split('_')[1] || p.verkehrsmittelNummer || (p.verkehrmittel?.langText || p.verkehrsmittel?.langText || p.mitteltext || p.zugName || p.lineName || '').replace(/\D/g, ''); const res = { type: 'line', - id: slugg(p.verkehrsmittel?.langText || p.verkehrmittel?.langText || p.transport?.journeyDescription || p.risZuglaufId || p.train && p.train.category + ' ' + p.train.lineName + ' ' + p.train.no || p.no && p.name + ' ' + p.no || p.langtext || p.mitteltext || p.zugName), // TODO terrible + id: slugg(p.verkehrsmittel?.langText || p.verkehrmittel?.langText || p.transport?.journeyDescription || p.risZuglaufId || p.train && p.train.category + ' ' + p.train.lineName + ' ' + p.train.no || p.no && p.name + ' ' + p.no || p.langtext || p.mitteltext || p.zugName || p.lineName), // TODO terrible fahrtNr: String(fahrtNr), - name: p.verkehrsmittel?.name || p.verkehrsmittel?.langText || p.verkehrmittel?.name || p.verkehrmittel?.langText || p.zugName || p.transport && p.transport.category + ' ' + p.transport.line || p.train && p.train.category + ' ' + p.train.lineName || p.name || p.mitteltext || p.langtext, + name: p.verkehrsmittel?.name || p.verkehrsmittel?.langText || p.verkehrmittel?.name || p.verkehrmittel?.langText || p.zugName || p.transport && p.transport.category + ' ' + p.transport.line || p.train && p.train.category + ' ' + p.train.lineName || p.name || p.mitteltext || p.langtext || p.lineName, public: true, }; - const adminCode = p.administrationId || p.administration?.id || p.administration?.administrationID; + const adminCode = p.administrationID || p.administrationId || p.administration?.id || p.administration?.administrationID; if (adminCode) { res.adminCode = adminCode; } - res.productName = p.verkehrsmittel?.kurzText || p.verkehrmittel?.kurzText || p.transport?.category || p.train?.category || p.category || p.kurztext; + res.productName = p.verkehrsmittel?.kurzText || p.verkehrmittel?.kurzText || p.transport?.category || p.train?.category || p.category || p.kurztext || p.lineName?.replace(/\d/g, ''); const foundProduct = profile.products.find(pp => pp.vendo == p.verkehrsmittel?.produktGattung || pp.vendo == p.verkehrmittel?.produktGattung || pp.ris == p.transport?.type || pp.ris == p.train?.type || pp.ris == p.type || pp.ris_alt == p.train?.type || pp.ris_alt == p.type || pp.dbnav_short == p.produktGattung); res.mode = foundProduct?.mode; res.product = foundProduct?.id; diff --git a/parse/remarks.js b/parse/remarks.js index a03f1b25..b5278917 100644 --- a/parse/remarks.js +++ b/parse/remarks.js @@ -10,7 +10,12 @@ const parseRemarks = (ctx, ref) => { ref.himNotizen || [], ref.hims || [], ref.serviceNotiz && [ref.serviceNotiz] || [], - ref.messages || [], + ref.messages?.common || [], + ref.messages?.delay || [], + ref.messages?.cancelation || [], + ref.messages?.destination || [], + ref.messages?.via || [], + Array.isArray(ref.messages) ? ref.messages : [], ref.meldungen || [], ref.meldungenAsObject || [], ref.attributNotizen || [], @@ -28,12 +33,12 @@ const parseRemarks = (ctx, ref) => { if (remark.prioritaet || remark.prio || remark.type) { type = 'status'; } - if (!remark.priority && !remark.kategorie && remark.key || remark.disruptionID + if (!remark.priority && !remark.kategorie && remark.key || remark.disruptionID || remark.important || remark.prioritaet && remark.prioritaet == 'HOCH' || remark.prio && remark.prio == 'HOCH' || remark.priority && remark.priority < 100) { type = 'warning'; } let res = { - code: remark.code || remark.key || remark.id, + code: remark.code || remark.key || remark.id || remark.type, summary: remark.nachrichtKurz || remark.value || remark.ueberschrift || remark.text || remark.shortText || Object.values(remark.descriptions || {}) .shift()?.textShort, diff --git a/test/dbbahnhof-departures.js b/test/dbbahnhof-departures.js new file mode 100644 index 00000000..9d81cd50 --- /dev/null +++ b/test/dbbahnhof-departures.js @@ -0,0 +1,29 @@ +import tap from 'tap'; + +import {createClient} from '../index.js'; +import {profile as rawProfile} from '../p/dbbahnhof/index.js'; +import res from './fixtures/dbbahnhof-departures.json' with { type: 'json' }; +import {dbDepartures as expected} from './fixtures/dbbahnhof-departures.js'; + +const client = createClient(rawProfile, 'public-transport/hafas-client:test', {enrichStations: false}); +const {profile} = client; + +const opt = { + direction: null, + duration: 10, + linesOfStops: true, + remarks: true, + stopovers: false, + includeRelatedStations: true, + when: '2019-08-19T20:30:00+02:00', + products: {}, +}; + +tap.test('parses a bahnhof.de departure correctly', (t) => { + const ctx = {profile, opt, common: null, res}; + const arrivals = res.entries.flat() + .map(d => profile.parseArrival(ctx, d)); + + t.same(arrivals, expected); + t.end(); +}); diff --git a/test/dbris-arrivals.js b/test/dbris-arrivals.js index 7b8b7af8..f249c9f2 100644 --- a/test/dbris-arrivals.js +++ b/test/dbris-arrivals.js @@ -1,7 +1,7 @@ import tap from 'tap'; import {createClient} from '../index.js'; -import {profile as rawProfile} from '../p/dbweb/index.js'; +import {profile as rawProfile} from '../p/dbris/index.js'; import res from './fixtures/dbris-arrivals.json' with { type: 'json' }; import {dbArrivals as expected} from './fixtures/dbris-arrivals.js'; diff --git a/test/dbris-departures.js b/test/dbris-departures.js new file mode 100644 index 00000000..eda40f87 --- /dev/null +++ b/test/dbris-departures.js @@ -0,0 +1,28 @@ +import tap from 'tap'; + +import {createClient} from '../index.js'; +import {profile as rawProfile} from '../p/dbris/index.js'; +import res from './fixtures/dbris-departures.json' with { type: 'json' }; +import {dbDepartures as expected} from './fixtures/dbris-departures.js'; + +const client = createClient(rawProfile, 'public-transport/hafas-client:test', {enrichStations: false}); +const {profile} = client; + +const opt = { + direction: null, + duration: 10, + linesOfStops: true, + remarks: true, + stopovers: false, + includeRelatedStations: true, + when: '2019-08-19T20:30:00+02:00', + products: {}, +}; + +tap.test('parses a RIS::Boards departure correctly', (t) => { + const ctx = {profile, opt, common: null, res}; + const arrivals = res.departures.map(d => profile.parseArrival(ctx, d)); + + t.same(arrivals, expected); + t.end(); +}); diff --git a/test/e2e/dbbahnhof.js b/test/e2e/dbbahnhof.js new file mode 100644 index 00000000..fab925b3 --- /dev/null +++ b/test/e2e/dbbahnhof.js @@ -0,0 +1,146 @@ +import tap from 'tap'; +import isRoughlyEqual from 'is-roughly-equal'; + +import {createWhen} from './lib/util.js'; +import {createClient} from '../../index.js'; +import {profile as dbProfile} from '../../p/dbregioguide/index.js'; +import { + createValidateStation, + createValidateTrip, +} from './lib/validators.js'; +import {createValidateFptfWith as createValidate} from './lib/validate-fptf-with.js'; +import {testJourneysStationToStation} from './lib/journeys-station-to-station.js'; +import {testJourneysStationToAddress} from './lib/journeys-station-to-address.js'; +import {testJourneysStationToPoi} from './lib/journeys-station-to-poi.js'; +import {testEarlierLaterJourneys} from './lib/earlier-later-journeys.js'; +import {testLegCycleAlternatives} from './lib/leg-cycle-alternatives.js'; +import {testRefreshJourney} from './lib/refresh-journey.js'; +import {journeysFailsWithNoProduct} from './lib/journeys-fails-with-no-product.js'; +import {testDepartures} from './lib/departures.js'; +import {testArrivals} from './lib/arrivals.js'; +import {testJourneysWithDetour} from './lib/journeys-with-detour.js'; + +const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o); +const minute = 60 * 1000; + +const T_MOCK = 1747040400 * 1000; // 2025-05-12T08:00:00+01:00 +const when = createWhen(dbProfile.timezone, dbProfile.locale, T_MOCK); + +const cfg = { + when, + stationCoordsOptional: true, // TODO + products: dbProfile.products, + minLatitude: 46.673100, + maxLatitude: 55.030671, + minLongitude: 6.896517, + maxLongitude: 16.180237, +}; + +const validate = createValidate(cfg); + +const assertValidPrice = (t, p) => { + t.ok(p); + if (p.amount !== null) { + t.equal(typeof p.amount, 'number'); + t.ok(p.amount > 0); + } + if (p.hint !== null) { + t.equal(typeof p.hint, 'string'); + t.ok(p.hint); + } +}; + +const assertValidTickets = (test, tickets) => { + test.ok(Array.isArray(tickets)); + for (let fare of tickets) { + test.equal(typeof fare.name, 'string', 'Mandatory field "name" is missing or not a string'); + test.ok(fare.name); + + test.ok(isObj(fare.priceObj), 'Mandatory field "priceObj" is missing or not an object'); + test.equal(typeof fare.priceObj.amount, 'number', 'Mandatory field "amount" in "priceObj" is missing or not a number'); + test.ok(fare.priceObj.amount > 0); + if ('currency' in fare.priceObj) { + test.equal(typeof fare.priceObj.currency, 'string'); + } + + // Check optional fields + if ('addData' in fare) { + test.equal(typeof fare.addData, 'string'); + } + if ('addDataTicketInfo' in fare) { + test.equal(typeof fare.addDataTicketInfo, 'string'); + } + if ('addDataTicketDetails' in fare) { + test.equal(typeof fare.addDataTicketDetails, 'string'); + } + if ('addDataTravelInfo' in fare) { + test.equal(typeof fare.addDataTravelInfo, 'string'); + } + if ('addDataTravelDetails' in fare) { + test.equal(typeof fare.firstClass, 'boolean'); + } + } +}; + +const client = createClient(dbProfile, 'public-transport/hafas-client:test', {enrichStations: false}); + +const berlinHbf = '8011160'; +const münchenHbf = '8000261'; +const jungfernheide = '8011167'; +const blnSchwedterStr = '732652'; +const westhafen = '8089116'; +const wedding = '8089131'; +const württembergallee = '731084'; +const regensburgHbf = '8000309'; +const blnOstbahnhof = '8010255'; +const blnTiergarten = '8089091'; +const blnJannowitzbrücke = '8089019'; +const potsdamHbf = '8012666'; +const berlinSüdkreuz = '8011113'; +const kölnHbf = '8000207'; + + +tap.test('departures at Berlin Schwedter Str.', async (t) => { + const res = await client.departures(blnSchwedterStr, { + duration: 5, when, + }); + + await testDepartures({ + test: t, + res, + validate, + id: blnSchwedterStr, + }); + t.end(); +}); + +tap.test('departures with station object', async (t) => { + const res = await client.departures({ + type: 'station', + id: jungfernheide, + name: 'Berlin Jungfernheide', + location: { + type: 'location', + latitude: 1.23, + longitude: 2.34, + }, + }, {when}); + + validate(t, res, 'departuresResponse', 'res'); + t.end(); +}); + +tap.test('arrivals at Berlin Schwedter Str.', async (t) => { + const res = await client.arrivals(blnSchwedterStr, { + duration: 5, when, + }); + + await testArrivals({ + test: t, + res, + validate, + id: blnSchwedterStr, + }); + t.end(); +}); + diff --git a/test/fixtures/dbbahnhof-departures.js b/test/fixtures/dbbahnhof-departures.js new file mode 100644 index 00000000..32f6ddda --- /dev/null +++ b/test/fixtures/dbbahnhof-departures.js @@ -0,0 +1,492 @@ +const dbDepartures = [ + { + tripId: '20250322-f6cd6d71-510f-378c-b825-fbb9380f5b03', + stop: { + type: 'station', + id: '8000105', + name: 'Frankfurt(Main)Hbf', + }, + when: '2025-03-22T00:42:00+01:00', + plannedWhen: '2025-03-22T00:42:00+01:00', + delay: 0, + platform: '11', + plannedPlatform: '11', + direction: 'Fulda', + provenance: null, + line: { + type: 'line', + id: 'rb51', + fahrtNr: '51', + name: 'RB51', + public: true, + adminCode: '8005KG', + productName: 'RB', + mode: 'train', + product: 'regional', + operator: null, + }, + remarks: [ + { + code: 'bicycle-transport', + summary: 'Limited bicycle transport possible', + text: 'Limited bicycle transport possible', + type: 'status', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000115', + name: 'Fulda', + }, + }, + { + tripId: '20250321-69f912f7-2b47-3ffd-b00f-708e8c568f6b', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:43:00+01:00', + plannedWhen: '2025-03-22T00:42:00+01:00', + delay: 60, + platform: '103', + plannedPlatform: '103', + direction: 'Wiesbaden Hbf', + provenance: null, + line: { + type: 'line', + id: 's1', + fahrtNr: '1', + name: 'S1', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'bicycle-transport', + summary: 'Limited bicycle transport possible', + text: 'Limited bicycle transport possible', + type: 'status', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000250', + name: 'Wiesbaden Hbf', + }, + }, + { + tripId: '20250322-fcf0de07-fc6e-3aeb-9757-3b08e6760c3f', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:44:00+01:00', + plannedWhen: '2025-03-22T00:44:00+01:00', + delay: null, + platform: null, + plannedPlatform: null, + direction: 'Bad Soden(Taunus)', + provenance: null, + line: { + type: 'line', + id: 'sev', + fahrtNr: '', + name: 'SEV', + public: true, + adminCode: 'B4', + productName: 'SEV', + mode: 'train', + product: 'regional', + operator: null, + }, + remarks: [ + { + code: 'replacement-service', + summary: 'Replacement bus for {{1}}', + text: 'Replacement bus for {{1}}', + type: 'status', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000752', + name: 'Bad Soden(Taunus)', + }, + }, + { + tripId: '20250321-bff43415-303b-36ad-ae4e-8d9605fc3f1e', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: null, + plannedWhen: '2025-03-22T00:44:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '102', + prognosedPlatform: '102', + direction: 'Offenbach(Main)Ost', + provenance: null, + line: { + type: 'line', + id: 's8', + fahrtNr: '8', + name: 'S8', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'unplanned-info', + summary: 'Defective signal box', + text: 'Defective signal box', + type: 'status', + }, + { + code: 'canceled-trip', + summary: 'Trip cancelled', + text: 'Trip cancelled', + type: 'warning', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8004645', + name: 'Offenbach(Main)Ost', + }, + cancelled: true, + }, + { + tripId: '20250322-1423f343-0076-3f29-b1e8-004dc1f27068', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:47:00+01:00', + plannedWhen: '2025-03-22T00:47:00+01:00', + delay: 0, + platform: '101', + plannedPlatform: '101', + direction: 'Darmstadt Hbf', + provenance: null, + line: { + type: 'line', + id: 's6', + fahrtNr: '6', + name: 'S6', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'bicycle-transport', + summary: 'Limited bicycle transport possible', + text: 'Limited bicycle transport possible', + type: 'status', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000068', + name: 'Darmstadt Hbf', + }, + }, + { + tripId: '20250322-f2c61208-75b1-3c19-a580-172988addf2c', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: null, + plannedWhen: '2025-03-22T00:47:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '103', + prognosedPlatform: '103', + direction: 'Wiesbaden Hbf', + provenance: null, + line: { + type: 'line', + id: 's8', + fahrtNr: '8', + name: 'S8', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'unplanned-info', + summary: 'Defective signal box', + text: 'Defective signal box', + type: 'status', + }, + { + code: 'canceled-trip', + summary: 'Trip cancelled', + text: 'Trip cancelled', + type: 'warning', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000250', + name: 'Wiesbaden Hbf', + }, + cancelled: true, + }, + { + tripId: '20250322-841901b7-7420-3890-8691-05c8cbbacdce', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T01:05:00+01:00', + plannedWhen: '2025-03-22T00:49:00+01:00', + delay: 960, + platform: '102', + plannedPlatform: '102', + direction: 'Rödermark-Ober Roden', + provenance: null, + line: { + type: 'line', + id: 's1', + fahrtNr: '1', + name: 'S1', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'unplanned-info', + summary: 'Repair on the turnout', + text: 'Repair on the turnout', + type: 'status', + }, + { + code: 'bicycle-transport', + summary: 'Limited bicycle transport possible', + text: 'Limited bicycle transport possible', + type: 'status', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000285', + name: 'Rödermark-Ober Roden', + }, + }, + { + tripId: '20250322-08673537-4773-3e90-afa3-ab467119a609', + stop: { + type: 'station', + id: '100010', + name: 'Hauptbahnhof, Frankfurt a.M.', + }, + when: '2025-03-22T00:50:00+01:00', + plannedWhen: '2025-03-22T00:50:00+01:00', + delay: 0, + platform: null, + plannedPlatform: null, + direction: 'Bockenheimer Warte, Frankfurt a.M.', + provenance: null, + line: { + type: 'line', + id: 'u4', + fahrtNr: '4', + name: 'U4', + public: true, + adminCode: 'rmv255', + productName: 'U', + mode: 'train', + product: 'subway', + operator: null, + }, + remarks: [], + origin: null, + destination: { + type: 'station', + id: '101201', + name: 'Bockenheimer Warte, Frankfurt a.M.', + }, + }, + { + tripId: '20250322-29a07ddd-969e-3660-ae2e-4d6c6af4a866', + stop: { + type: 'station', + id: '8000105', + name: 'Frankfurt(Main)Hbf', + }, + when: null, + plannedWhen: '2025-03-22T00:50:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '2', + prognosedPlatform: '2', + direction: 'Riedstadt-Goddelau', + provenance: null, + line: { + type: 'line', + id: 's7', + fahrtNr: '7', + name: 'S7', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'unplanned-info', + summary: 'Short-term unavailability of employees', + text: 'Short-term unavailability of employees', + type: 'status', + }, + { + code: 'canceled-trip', + summary: 'Trip cancelled', + text: 'Trip cancelled', + type: 'warning', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000126', + name: 'Riedstadt-Goddelau', + }, + cancelled: true, + }, + { + tripId: '20250322-01575b72-00ad-36da-bc88-49410d87321a', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:52:00+01:00', + plannedWhen: '2025-03-22T00:52:00+01:00', + delay: 0, + platform: '103', + plannedPlatform: '103', + direction: 'Niedernhausen(Taunus)', + provenance: null, + line: { + type: 'line', + id: 's2', + fahrtNr: '2', + name: 'S2', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'bicycle-transport', + summary: 'Limited bicycle transport possible', + text: 'Limited bicycle transport possible', + type: 'status', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8004400', + name: 'Niedernhausen(Taunus)', + }, + }, + { + tripId: '20250322-2b5b5913-2b2d-39da-b29d-2fff067ba6a2', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: null, + plannedWhen: '2025-03-22T00:52:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '101', + prognosedPlatform: '101', + direction: 'Frankfurt(Main)Süd', + provenance: null, + line: { + type: 'line', + id: 's4', + fahrtNr: '4', + name: 'S4', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: null, + }, + remarks: [ + { + code: 'unplanned-info', + summary: 'Defective signal box', + text: 'Defective signal box', + type: 'status', + }, + { + code: 'canceled-trip', + summary: 'Trip cancelled', + text: 'Trip cancelled', + type: 'warning', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8002041', + name: 'Frankfurt(Main)Süd', + }, + cancelled: true, + }, +]; + +export { + dbDepartures, +}; diff --git a/test/fixtures/dbbahnhof-departures.json b/test/fixtures/dbbahnhof-departures.json new file mode 100644 index 00000000..378ea503 --- /dev/null +++ b/test/fixtures/dbbahnhof-departures.json @@ -0,0 +1 @@ +{"globalMessages":[],"entries":[[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"8000105_D_1","timeSchedule":"2025-03-22T00:42:00+01:00","timeDelayed":"2025-03-22T00:42:00+01:00","delayed":false,"platform":"11","platformSchedule":"11","timeType":"PREVIEW","canceled":false,"administrationID":"8005KG","virtual":false,"lineName":"RB51","type":"REGIONAL_TRAIN","kind":"default","journeyID":"20250322-f6cd6d71-510f-378c-b825-fbb9380f5b03","stopPlace":{"evaNumber":"8000105","name":"Frankfurt(Main)Hbf","canceled":false},"arrivalOrDepartureId":"8000105_D_1","destination":{"evaNumber":"8000115","name":"Fulda","canceled":false,"slug":"fulda","nameParts":[{"type":"default","value":"Fulda"}]},"viaStops":[{"evaNumber":"8002041","name":"Frankfurt(Main)Süd","canceled":false,"additional":false,"displayPriority":1,"separation":false,"slug":"frankfurt-main-sued","nameParts":[{"type":"default","value":"Frankfurt "},{"type":"region","value":"(Main)"},{"type":"default","value":" Süd"}]},{"evaNumber":"8000349","name":"Offenbach(Main)Hbf","canceled":false,"additional":false,"displayPriority":3,"separation":false,"slug":"offenbach-main-hbf","nameParts":[{"type":"default","value":"Offenbach "},{"type":"region","value":"(Main)"},{"type":"default","value":" Hbf","valueSpeech":" Hauptbahnhof"}]},{"evaNumber":"8000150","name":"Hanau Hbf","canceled":false,"additional":false,"displayPriority":2,"separation":false,"slug":"hanau-hbf","nameParts":[{"type":"default","value":"Hanau Hbf","valueSpeech":"Hanau Hauptbahnhof"}]},{"evaNumber":"8006548","name":"Wolfgang(Kr Hanau)","canceled":false,"additional":false,"displayPriority":15,"separation":false,"slug":"wolfgang-kr-hanau","nameParts":[{"type":"default","value":"Wolfgang "},{"type":"region","value":"(Kr Hanau)","valueSpeech":"(Kreis Hanau)"}]},{"evaNumber":"8004402","name":"Rodenbach(b Hanau)","canceled":false,"additional":false,"displayPriority":8,"separation":false,"slug":"rodenbach-bei-hanau","nameParts":[{"type":"default","value":"Rodenbach "},{"type":"region","value":"bei Hanau"}]},{"evaNumber":"8003550","name":"Langenselbold","canceled":false,"additional":false,"displayPriority":4,"separation":false,"slug":"langenselbold","nameParts":[{"type":"default","value":"Langenselbold"}]},{"evaNumber":"8004395","name":"Niedermittlau","canceled":false,"additional":false,"displayPriority":9,"separation":false,"slug":"niedermittlau","nameParts":[{"type":"default","value":"Niedermittlau"}]},{"evaNumber":"8002526","name":"Hailer-Meerholz","canceled":false,"additional":false,"displayPriority":10,"separation":false,"slug":"hailer-meerholz","nameParts":[{"type":"default","value":"Hailer-Meerholz"}]},{"evaNumber":"8000117","name":"Gelnhausen","canceled":false,"additional":false,"displayPriority":5,"separation":false,"slug":"gelnhausen","nameParts":[{"type":"default","value":"Gelnhausen"}]},{"evaNumber":"8002532","name":"Haitz-Höchst","canceled":false,"additional":false,"displayPriority":16,"separation":false,"slug":"haitz-hoechst","nameParts":[{"type":"default","value":"Haitz-Höchst"}]},{"evaNumber":"8006499","name":"Wirtheim","canceled":false,"additional":false,"displayPriority":17,"separation":false,"slug":"wirtheim","nameParts":[{"type":"default","value":"Wirtheim"}]},{"evaNumber":"8006132","name":"Wächtersbach","canceled":false,"additional":false,"displayPriority":6,"separation":false,"slug":"waechtersbach","nameParts":[{"type":"default","value":"Wächtersbach"}]},{"evaNumber":"8005261","name":"Bad Soden-Salmünster","canceled":false,"additional":false,"displayPriority":11,"separation":false,"slug":"bad-soden-salmuenster","nameParts":[{"type":"city","value":"Bad Soden","valueSpeech":"Ba​d Soden"},{"type":"city-separator","value":"-"},{"type":"default","value":"Salmünster"}]},{"evaNumber":"8005690","name":"Steinau(Straße)","canceled":false,"additional":false,"displayPriority":12,"separation":false,"slug":"steinau-strasse","nameParts":[{"type":"default","value":"Steinau "},{"type":"region","value":"(Straße)"}]},{"evaNumber":"8000891","name":"Schlüchtern","canceled":false,"additional":false,"displayPriority":7,"separation":false,"slug":"schluechtern","nameParts":[{"type":"default","value":"Schlüchtern"}]},{"evaNumber":"8002010","name":"Flieden","canceled":false,"additional":false,"displayPriority":13,"separation":false,"slug":"flieden","nameParts":[{"type":"default","value":"Flieden"}]},{"evaNumber":"8004295","name":"Neuhof(Kr Fulda)","canceled":false,"additional":false,"displayPriority":14,"separation":false,"slug":"neuhof-kr-fulda","nameParts":[{"type":"default","value":"Neuhof "},{"type":"region","value":"(Kr Fulda)","valueSpeech":"(Kreis Fulda)"}]}],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Limited bicycle transport possible","locale":"en","type":"bicycle-transport","change":false,"important":false,"open":false,"links":[]}],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:42:00+01:00","timeDelayed":"2025-03-22T00:43:00+01:00","delayed":true,"platform":"103","platformSchedule":"103","timeType":"PREVIEW","canceled":false,"administrationID":"800528","virtual":false,"lineName":"S1","type":"CITY_TRAIN","kind":"default","journeyID":"20250321-69f912f7-2b47-3ffd-b00f-708e8c568f6b","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":false},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8000250","name":"Wiesbaden Hbf","canceled":false,"slug":"wiesbaden-hbf","nameParts":[{"type":"default","value":"Wiesbaden Hbf","valueSpeech":"Wiesbaden Hauptbahnhof"}]},"viaStops":[{"evaNumber":"8002046","name":"Frankfurt-Griesheim","canceled":false,"additional":false,"displayPriority":2,"separation":false,"slug":"frankfurt-griesheim","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Griesheim"}]},{"evaNumber":"8002049","name":"Frankfurt-Nied","canceled":false,"additional":false,"displayPriority":8,"separation":false,"slug":"frankfurt-nied","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Nied"}]},{"evaNumber":"8000106","name":"Frankfurt-Höchst","canceled":false,"additional":false,"displayPriority":1,"separation":false,"slug":"frankfurt-hoechst","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Höchst"}]},{"evaNumber":"8002051","name":"Frankfurt-Höchst Farbwerke","canceled":false,"additional":false,"displayPriority":9,"separation":false,"slug":"frankfurt-hoechst-farbwerke","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Höchst Farbwerke"}]},{"evaNumber":"8002053","name":"Frankfurt-Sindlingen","canceled":false,"additional":false,"displayPriority":10,"separation":false,"slug":"frankfurt-sindlingen","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Sindlingen"}]},{"evaNumber":"8002637","name":"Hattersheim(Main)","canceled":false,"additional":false,"displayPriority":3,"separation":false,"slug":"hattersheim-main","nameParts":[{"type":"default","value":"Hattersheim "},{"type":"region","value":"(Main)"}]},{"evaNumber":"8001659","name":"Eddersheim","canceled":false,"additional":false,"displayPriority":11,"separation":false,"slug":"eddersheim","nameParts":[{"type":"default","value":"Eddersheim"}]},{"evaNumber":"8002013","name":"Flörsheim(Main)","canceled":false,"additional":false,"displayPriority":4,"separation":false,"slug":"floersheim-main","nameParts":[{"type":"default","value":"Flörsheim "},{"type":"region","value":"(Main)"}]},{"evaNumber":"8002872","name":"Hochheim(Main)","canceled":false,"additional":false,"displayPriority":5,"separation":false,"slug":"hochheim-main","nameParts":[{"type":"default","value":"Hochheim "},{"type":"region","value":"(Main)"}]},{"evaNumber":"8000615","name":"Mainz-Kastel","canceled":false,"additional":false,"displayPriority":6,"separation":false,"slug":"mainz-kastel","nameParts":[{"type":"city","value":"Mainz"},{"type":"city-separator","value":"-"},{"type":"default","value":"Kastel"}]},{"evaNumber":"8006404","name":"Wiesbaden Ost","canceled":false,"additional":false,"displayPriority":7,"separation":false,"slug":"wiesbaden-ost","nameParts":[{"type":"default","value":"Wiesbaden Ost"}]}],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Limited bicycle transport possible","locale":"en","type":"bicycle-transport","change":false,"important":false,"open":false,"links":[]}],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:44:00+01:00","timeDelayed":"2025-03-22T00:44:00+01:00","delayed":false,"platform":"","platformSchedule":"","timeType":"SCHEDULE","canceled":false,"administrationID":"B4","virtual":false,"lineName":"SEV","type":"REGIONAL_TRAIN","replacementServiceType":"BUS","kind":"replacement-service","journeyID":"20250322-fcf0de07-fc6e-3aeb-9757-3b08e6760c3f","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":false},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8000752","name":"Bad Soden(Taunus)","canceled":false,"slug":"bad-soden-taunus","nameParts":[{"type":"default","value":"Bad Soden ","valueSpeech":"Ba​d Soden "},{"type":"region","value":"(Taunus)"}]},"viaStops":[{"evaNumber":"8006690","name":"Frankfurt(M)Galluswarte","canceled":false,"additional":false,"displayPriority":3,"separation":false,"slug":"frankfurt-main-galluswarte","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Galluswarte"}]},{"evaNumber":"8079632","name":"Frankfurt(Main)Messe","canceled":false,"additional":false,"displayPriority":4,"separation":false,"slug":"frankfurt-am-main-messe","nameParts":[{"type":"city","value":"Frankfurt am Main"},{"type":"city-separator","value":" "},{"type":"default","value":"Messe"}]},{"evaNumber":"8002042","name":"Frankfurt(Main)West","canceled":false,"additional":false,"displayPriority":1,"separation":false,"slug":"frankfurt-main-west","nameParts":[{"type":"default","value":"Frankfurt "},{"type":"region","value":"(Main)"},{"type":"default","value":" West"}]},{"evaNumber":"8002052","name":"Frankfurt-Rödelheim","canceled":false,"additional":false,"displayPriority":2,"separation":false,"slug":"frankfurt-roedelheim","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Rödelheim"}]},{"evaNumber":"8001871","name":"Eschborn Süd","canceled":false,"additional":false,"displayPriority":5,"separation":false,"slug":"eschborn-sued","nameParts":[{"type":"default","value":"Eschborn Süd"}]},{"evaNumber":"8001870","name":"Eschborn","canceled":false,"additional":false,"displayPriority":6,"separation":false,"slug":"eschborn","nameParts":[{"type":"default","value":"Eschborn"}]},{"evaNumber":"8004380","name":"Niederhöchstadt","canceled":false,"additional":false,"displayPriority":7,"separation":false,"slug":"niederhoechstadt","nameParts":[{"type":"default","value":"Niederhöchstadt"}]},{"evaNumber":"8005456","name":"Schwalbach(Taunus)Nord","canceled":false,"additional":false,"displayPriority":9,"separation":false,"slug":"schwalbach-nord","nameParts":[{"type":"default","value":"Schwalbach Nord"}]},{"evaNumber":"8005455","name":"Schwalbach(Taunus)Limes","canceled":false,"additional":false,"displayPriority":8,"separation":false,"slug":"schwalbach-a-ts-limes","nameParts":[{"type":"default","value":"Schwalbach "},{"type":"region","value":"a Ts (Limes)","valueSpeech":"am Taunus (Limes)"}]},{"evaNumber":"8005799","name":"Sulzbach(Taunus)Nord","canceled":false,"additional":false,"displayPriority":10,"separation":false,"slug":"sulzbach-taunus-nord","nameParts":[{"type":"default","value":"Sulzbach "},{"type":"region","value":"(Taunus)"},{"type":"default","value":" Nord"}]}],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Replacement bus for {{1}}","locale":"en","type":"replacement-service","change":true,"important":false,"open":true,"links":[{"type":"replacement-service-map","label":"Where is the bus stop?"},{"type":"line","lineName":"S 3","transportType":"CITY_TRAIN","isCanceled":false,"isReplacementBusService":false}],"aside":"{{0}}"}],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":false}],[{"canceledStopsAfterActualDestination":[{"evaNumber":"8006691","name":"Frankfurt(M)Taunusanlage","canceled":true,"additional":false,"displayPriority":1},{"evaNumber":"8006692","name":"Frankfurt(M)Hauptwache","canceled":true,"additional":false,"displayPriority":2},{"evaNumber":"8004429","name":"Frankfurt(M)Konstablerwache","canceled":true,"additional":false,"displayPriority":3},{"evaNumber":"8002058","name":"Frankfurt(M)Ostendstraße","canceled":true,"additional":false,"displayPriority":4},{"evaNumber":"8002034","name":"Frankfurt(M)Mühlberg","canceled":true,"additional":false,"displayPriority":5},{"evaNumber":"8070092","name":"Offenbach(Main) Kaiserlei","canceled":true,"additional":false,"displayPriority":6},{"evaNumber":"8070091","name":"Offenbach(Main) Ledermuseum","canceled":true,"additional":false,"displayPriority":7},{"evaNumber":"8070090","name":"Offenbach(Main) Marktplatz","canceled":true,"additional":false,"displayPriority":8}],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:44:00+01:00","timeDelayed":"2025-03-22T00:44:00+01:00","delayed":false,"platform":"102","platformSchedule":"102","timeType":"SCHEDULE","canceled":true,"administrationID":"800528","virtual":false,"lineName":"S8","type":"CITY_TRAIN","kind":"canceled","journeyID":"20250321-bff43415-303b-36ad-ae4e-8d9605fc3f1e","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":true},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8004645","name":"Offenbach(Main)Ost","canceled":true,"slug":"offenbach-main-ost","nameParts":[{"type":"default","value":"Offenbach "},{"type":"region","value":"(Main)"},{"type":"default","value":" Ost"}]},"viaStops":[],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Defective signal box","type":"unplanned-info","change":true,"important":false,"open":true,"links":[],"locale":"en"}],"delay":[],"cancelation":[{"text":"Trip cancelled","locale":"en","type":"canceled-trip","change":true,"important":true,"open":true,"links":[]}],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:47:00+01:00","timeDelayed":"2025-03-22T00:47:00+01:00","delayed":false,"platform":"101","platformSchedule":"101","timeType":"PREVIEW","canceled":false,"administrationID":"800528","virtual":false,"lineName":"S6","type":"CITY_TRAIN","kind":"default","journeyID":"20250322-1423f343-0076-3f29-b1e8-004dc1f27068","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":false},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8000068","name":"Darmstadt Hbf","canceled":false,"slug":"darmstadt-hbf","nameParts":[{"type":"default","value":"Darmstadt Hbf","valueSpeech":"Darmstadt Hauptbahnhof"}]},"viaStops":[{"evaNumber":"8006691","name":"Frankfurt(M)Taunusanlage","canceled":false,"additional":false,"displayPriority":2,"separation":false,"slug":"frankfurt-main-taunusanlage","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Taunusanlage"}]},{"evaNumber":"8006692","name":"Frankfurt(M)Hauptwache","canceled":false,"additional":false,"displayPriority":3,"separation":false,"slug":"frankfurt-main-hauptwache","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Hauptwache"}]},{"evaNumber":"8004429","name":"Frankfurt(M)Konstablerwache","canceled":false,"additional":false,"displayPriority":4,"separation":false,"slug":"frankfurt-main-konstablerwache","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Konstablerwache"}]},{"evaNumber":"8002058","name":"Frankfurt(M)Ostendstraße","canceled":false,"additional":false,"displayPriority":5,"separation":false,"slug":"frankfurt-main-ostendstrasse","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Ostendstraße"}]},{"evaNumber":"8002038","name":"Frankfurt(M)Lokalbahnhof","canceled":false,"additional":false,"displayPriority":6,"separation":false,"slug":"frankfurt-main-lokalbahnhof","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Lokalbahnhof"}]},{"evaNumber":"8002041","name":"Frankfurt(Main)Süd","canceled":false,"additional":false,"displayPriority":1,"separation":false,"slug":"frankfurt-main-sued","nameParts":[{"type":"default","value":"Frankfurt "},{"type":"region","value":"(Main)"},{"type":"default","value":" Süd"}]},{"evaNumber":"8002059","name":"Frankfurt(M)Stresemannallee","canceled":false,"additional":false,"displayPriority":7,"separation":false,"slug":"frankfurt-main-stresemannallee","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Stresemannallee"}]},{"evaNumber":"8002047","name":"Frankfurt-Louisa","canceled":false,"additional":false,"displayPriority":8,"separation":false,"slug":"frankfurt-louisa","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Louisa"}]},{"evaNumber":"8004246","name":"Neu-Isenburg","canceled":false,"additional":false,"displayPriority":9,"separation":false,"slug":"neu-isenburg","nameParts":[{"type":"default","value":"Neu Isenburg"}]},{"evaNumber":"8001236","name":"Dreieich-Buchschlag","canceled":false,"additional":false,"displayPriority":10,"separation":false,"slug":"dreieich-buchschlag","nameParts":[{"type":"city","value":"Dreieich"},{"type":"city-separator","value":"-"},{"type":"default","value":"Buchschlag"}]},{"evaNumber":"8003526","name":"Langen-Flugsicherung","canceled":false,"additional":false,"displayPriority":13,"separation":false,"slug":"langen-flugsicherung","nameParts":[{"type":"city","value":"Langen"},{"type":"city-separator","value":"-"},{"type":"default","value":"Flugsicherung"}]},{"evaNumber":"8003523","name":"Langen(Hess)","canceled":false,"additional":false,"displayPriority":11,"separation":false,"slug":"langen-hess","nameParts":[{"type":"default","value":"Langen "},{"type":"region","value":"(Hess)","valueSpeech":"(Hessen)"}]},{"evaNumber":"8001672","name":"Egelsbach","canceled":false,"additional":false,"displayPriority":14,"separation":false,"slug":"egelsbach","nameParts":[{"type":"default","value":"Egelsbach"}]},{"evaNumber":"8001864","name":"Erzhausen","canceled":false,"additional":false,"displayPriority":12,"separation":false,"slug":"erzhausen","nameParts":[{"type":"default","value":"Erzhausen"}]},{"evaNumber":"8006528","name":"Darmstadt-Wixhausen","canceled":false,"additional":false,"displayPriority":15,"separation":false,"slug":"darmstadt-wixhausen","nameParts":[{"type":"city","value":"Darmstadt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Wixhausen"}]},{"evaNumber":"8001378","name":"Darmstadt-Arheilgen","canceled":false,"additional":false,"displayPriority":16,"separation":false,"slug":"darmstadt-arheilgen","nameParts":[{"type":"city","value":"Darmstadt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Arheilgen"}]}],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Limited bicycle transport possible","locale":"en","type":"bicycle-transport","change":false,"important":false,"open":false,"links":[]}],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[{"evaNumber":"8002050","name":"Frankfurt-Niederrad","canceled":true,"additional":false,"displayPriority":3},{"evaNumber":"8002040","name":"Frankfurt am Main - Stadion","canceled":true,"additional":false,"displayPriority":4},{"evaNumber":"8070003","name":"Frankfurt(M) Flughafen Fernbf","canceled":true,"additional":false,"displayPriority":1},{"evaNumber":"8004962","name":"Raunheim","canceled":true,"additional":false,"displayPriority":7},{"evaNumber":"8005220","name":"Rüsselsheim","canceled":true,"additional":false,"displayPriority":5},{"evaNumber":"8005221","name":"Rüsselsheim Opelwerk","canceled":true,"additional":false,"displayPriority":8},{"evaNumber":"8000241","name":"Mainz-Bischofsheim","canceled":true,"additional":false,"displayPriority":9},{"evaNumber":"8003818","name":"Mainz-Gustavsburg","canceled":true,"additional":false,"displayPriority":10},{"evaNumber":"8003816","name":"Mainz Römisches Theater","canceled":true,"additional":false,"displayPriority":6},{"evaNumber":"8000240","name":"Mainz Hbf","canceled":true,"additional":false,"displayPriority":2},{"evaNumber":"8003815","name":"Mainz Nord","canceled":true,"additional":false,"displayPriority":12},{"evaNumber":"8006404","name":"Wiesbaden Ost","canceled":true,"additional":false,"displayPriority":11}],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:47:00+01:00","timeDelayed":"2025-03-22T00:47:00+01:00","delayed":false,"platform":"103","platformSchedule":"103","timeType":"SCHEDULE","canceled":true,"administrationID":"800528","virtual":false,"lineName":"S8","type":"CITY_TRAIN","kind":"canceled","journeyID":"20250322-f2c61208-75b1-3c19-a580-172988addf2c","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":true},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8000250","name":"Wiesbaden Hbf","canceled":true,"slug":"wiesbaden-hbf","nameParts":[{"type":"default","value":"Wiesbaden Hbf","valueSpeech":"Wiesbaden Hauptbahnhof"}]},"viaStops":[],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Defective signal box","type":"unplanned-info","change":true,"important":false,"open":true,"links":[],"locale":"en"}],"delay":[],"cancelation":[{"text":"Trip cancelled","locale":"en","type":"canceled-trip","change":true,"important":true,"open":true,"links":[]}],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:49:00+01:00","timeDelayed":"2025-03-22T01:05:00+01:00","delayed":true,"platform":"102","platformSchedule":"102","timeType":"PREVIEW","canceled":false,"administrationID":"800528","virtual":false,"lineName":"S1","type":"CITY_TRAIN","kind":"default","journeyID":"20250322-841901b7-7420-3890-8691-05c8cbbacdce","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":false},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8000285","name":"Rödermark-Ober Roden","canceled":false,"slug":"roedermark-ober-roden","nameParts":[{"type":"default","value":"Rödermark-Ober Roden"}]},"viaStops":[{"evaNumber":"8006691","name":"Frankfurt(M)Taunusanlage","canceled":false,"additional":false,"displayPriority":1,"separation":false,"slug":"frankfurt-main-taunusanlage","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Taunusanlage"}]},{"evaNumber":"8006692","name":"Frankfurt(M)Hauptwache","canceled":false,"additional":false,"displayPriority":2,"separation":false,"slug":"frankfurt-main-hauptwache","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Hauptwache"}]},{"evaNumber":"8004429","name":"Frankfurt(M)Konstablerwache","canceled":false,"additional":false,"displayPriority":3,"separation":false,"slug":"frankfurt-main-konstablerwache","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Konstablerwache"}]},{"evaNumber":"8002058","name":"Frankfurt(M)Ostendstraße","canceled":false,"additional":false,"displayPriority":4,"separation":false,"slug":"frankfurt-main-ostendstrasse","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Ostendstraße"}]},{"evaNumber":"8002034","name":"Frankfurt(M)Mühlberg","canceled":false,"additional":false,"displayPriority":6,"separation":false,"slug":"frankfurt-main-muehlberg","nameParts":[{"type":"city","value":"Frankfurt (Main)"},{"type":"city-separator","value":" "},{"type":"default","value":"Mühlberg"}]},{"evaNumber":"8070092","name":"Offenbach(Main) Kaiserlei","canceled":false,"additional":false,"displayPriority":7,"separation":false,"slug":"offenbach-kaiserlei","nameParts":[{"type":"city","value":"Offenbach"},{"type":"city-separator","value":"-"},{"type":"default","value":"Kaiserlei"}]},{"evaNumber":"8070091","name":"Offenbach(Main) Ledermuseum","canceled":false,"additional":false,"displayPriority":8,"separation":false,"slug":"offenbach-ledermuseum","nameParts":[{"type":"city","value":"Offenbach"},{"type":"city-separator","value":" "},{"type":"default","value":"Ledermuseum"}]},{"evaNumber":"8070090","name":"Offenbach(Main) Marktplatz","canceled":false,"additional":false,"displayPriority":9,"separation":false,"slug":"offenbach-marktplatz","nameParts":[{"type":"city","value":"Offenbach"},{"type":"city-separator","value":" "},{"type":"default","value":"Marktplatz"}]},{"evaNumber":"8004645","name":"Offenbach(Main)Ost","canceled":false,"additional":false,"displayPriority":5,"separation":false,"slug":"offenbach-main-ost","nameParts":[{"type":"default","value":"Offenbach "},{"type":"region","value":"(Main)"},{"type":"default","value":" Ost"}]},{"evaNumber":"8004647","name":"Offenbach-Bieber","canceled":false,"additional":false,"displayPriority":10,"separation":false,"slug":"offenbach-bieber","nameParts":[{"type":"city","value":"Offenbach"},{"type":"city-separator","value":"-"},{"type":"default","value":"Bieber"}]},{"evaNumber":"8004640","name":"Offenbach-Waldhof","canceled":false,"additional":false,"displayPriority":11,"separation":false,"slug":"offenbach-waldhof","nameParts":[{"type":"city","value":"Offenbach"},{"type":"city-separator","value":"-"},{"type":"default","value":"Waldhof"}]},{"evaNumber":"8004593","name":"Obertshausen(Kr Of)","canceled":false,"additional":false,"displayPriority":12,"separation":false,"slug":"obertshausen-kr-offenbach","nameParts":[{"type":"default","value":"Obertshausen "},{"type":"region","value":"(Kr Offenbach)","valueSpeech":"(Kreis Offenbach)"}]},{"evaNumber":"8006293","name":"Rodgau-Weiskirchen","canceled":false,"additional":false,"displayPriority":13,"separation":false,"slug":"rodgau-weiskirchen","nameParts":[{"type":"default","value":"Rodgau-Weiskirchen"}]},{"evaNumber":"8002528","name":"Rodgau-Hainhausen","canceled":false,"additional":false,"displayPriority":14,"separation":false,"slug":"rodgau-hainhausen","nameParts":[{"type":"default","value":"Rodgau-Hainhausen"}]},{"evaNumber":"8003131","name":"Rodgau-Jügesheim","canceled":false,"additional":false,"displayPriority":15,"separation":false,"slug":"rodgau-juegesheim","nameParts":[{"type":"default","value":"Rodgau-Jügesheim"}]},{"evaNumber":"8001567","name":"Rodgau-Dudenhofen","canceled":false,"additional":false,"displayPriority":16,"separation":false,"slug":"rodgau-dudenhofen","nameParts":[{"type":"default","value":"Rodgau-Dudenhofen"}]},{"evaNumber":"8004351","name":"Rodgau-Nieder Roden","canceled":false,"additional":false,"displayPriority":17,"separation":false,"slug":"rodgau-nieder-roden","nameParts":[{"type":"default","value":"Rodgau-Nieder Roden"}]},{"evaNumber":"8005156","name":"Rodgau-Rollwald","canceled":false,"additional":false,"displayPriority":18,"separation":false,"slug":"rodgau-rollwald","nameParts":[{"type":"default","value":"Rodgau-Rollwald"}]}],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Repair on the turnout","type":"unplanned-info","change":true,"important":false,"open":false,"links":[],"locale":"en"},{"text":"Limited bicycle transport possible","locale":"en","type":"bicycle-transport","change":false,"important":false,"open":false,"links":[]}],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"100010_D_1","timeSchedule":"2025-03-22T00:50:00+01:00","timeDelayed":"2025-03-22T00:50:00+01:00","delayed":false,"platform":"","platformSchedule":"","timeType":"PREVIEW","canceled":false,"administrationID":"rmv255","virtual":false,"lineName":"U4","type":"SUBWAY","kind":"default","journeyID":"20250322-08673537-4773-3e90-afa3-ab467119a609","stopPlace":{"evaNumber":"100010","name":"Hauptbahnhof, Frankfurt a.M.","canceled":false},"arrivalOrDepartureId":"100010_D_1","destination":{"evaNumber":"101201","name":"Bockenheimer Warte, Frankfurt a.M.","canceled":false},"viaStops":[{"evaNumber":"100210","name":"Festhalle/Messe, Frankfurt a.M.","canceled":false,"additional":false,"displayPriority":1,"separation":false}],"additionalStops":[],"canceledStops":[],"messages":{"common":[],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":false}],[{"canceledStopsAfterActualDestination":[{"evaNumber":"8002050","name":"Frankfurt-Niederrad","canceled":true,"additional":false,"displayPriority":1},{"evaNumber":"8002040","name":"Frankfurt am Main - Stadion","canceled":true,"additional":false,"displayPriority":2},{"evaNumber":"8006648","name":"Zeppelinheim","canceled":true,"additional":false,"displayPriority":6},{"evaNumber":"8006175","name":"Walldorf(Hess)","canceled":true,"additional":false,"displayPriority":5},{"evaNumber":"8004065","name":"Mörfelden","canceled":true,"additional":false,"displayPriority":4},{"evaNumber":"8002386","name":"Groß Gerau-Dornberg","canceled":true,"additional":false,"displayPriority":3},{"evaNumber":"8001511","name":"Groß Gerau-Dornheim","canceled":true,"additional":false,"displayPriority":7},{"evaNumber":"8003605","name":"Riedstadt-Wolfskehlen","canceled":true,"additional":false,"displayPriority":8}],"direction":"departure","id":"8000105_D_1","timeSchedule":"2025-03-22T00:50:00+01:00","timeDelayed":"2025-03-22T00:50:00+01:00","delayed":false,"platform":"2","platformSchedule":"2","timeType":"SCHEDULE","canceled":true,"administrationID":"800528","virtual":false,"lineName":"S7","type":"CITY_TRAIN","kind":"canceled","journeyID":"20250322-29a07ddd-969e-3660-ae2e-4d6c6af4a866","stopPlace":{"evaNumber":"8000105","name":"Frankfurt(Main)Hbf","canceled":true},"arrivalOrDepartureId":"8000105_D_1","destination":{"evaNumber":"8000126","name":"Riedstadt-Goddelau","canceled":true,"slug":"riedstadt-goddelau","nameParts":[{"type":"default","value":"Riedstadt-Goddelau"}]},"viaStops":[],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Short-term unavailability of employees","type":"unplanned-info","change":true,"important":false,"open":true,"links":[],"locale":"en"}],"delay":[],"cancelation":[{"text":"Trip cancelled","locale":"en","type":"canceled-trip","change":true,"important":true,"open":true,"links":[]}],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:52:00+01:00","timeDelayed":"2025-03-22T00:52:00+01:00","delayed":false,"platform":"103","platformSchedule":"103","timeType":"PREVIEW","canceled":false,"administrationID":"800528","virtual":false,"lineName":"S2","type":"CITY_TRAIN","kind":"default","journeyID":"20250322-01575b72-00ad-36da-bc88-49410d87321a","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":false},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8004400","name":"Niedernhausen(Taunus)","canceled":false,"slug":"niedernhausen-taunus","nameParts":[{"type":"default","value":"Niedernhausen "},{"type":"region","value":"(Taunus)"}]},"viaStops":[{"evaNumber":"8002046","name":"Frankfurt-Griesheim","canceled":false,"additional":false,"displayPriority":3,"separation":false,"slug":"frankfurt-griesheim","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Griesheim"}]},{"evaNumber":"8002049","name":"Frankfurt-Nied","canceled":false,"additional":false,"displayPriority":8,"separation":false,"slug":"frankfurt-nied","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Nied"}]},{"evaNumber":"8000106","name":"Frankfurt-Höchst","canceled":false,"additional":false,"displayPriority":1,"separation":false,"slug":"frankfurt-hoechst","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Höchst"}]},{"evaNumber":"8002051","name":"Frankfurt-Höchst Farbwerke","canceled":false,"additional":false,"displayPriority":9,"separation":false,"slug":"frankfurt-hoechst-farbwerke","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Höchst Farbwerke"}]},{"evaNumber":"8002055","name":"Frankfurt-Zeilsheim","canceled":false,"additional":false,"displayPriority":10,"separation":false,"slug":"frankfurt-zeilsheim","nameParts":[{"type":"city","value":"Frankfurt"},{"type":"city-separator","value":"-"},{"type":"default","value":"Zeilsheim"}]},{"evaNumber":"8003442","name":"Kriftel","canceled":false,"additional":false,"displayPriority":4,"separation":false,"slug":"kriftel","nameParts":[{"type":"default","value":"Kriftel"}]},{"evaNumber":"8002935","name":"Hofheim(Taunus)","canceled":false,"additional":false,"displayPriority":2,"separation":false,"slug":"hofheim-taunus","nameParts":[{"type":"default","value":"Hofheim "},{"type":"region","value":"(Taunus)"}]},{"evaNumber":"8003754","name":"Lorsbach","canceled":false,"additional":false,"displayPriority":5,"separation":false,"slug":"lorsbach","nameParts":[{"type":"default","value":"Lorsbach"}]},{"evaNumber":"8001815","name":"Eppstein","canceled":false,"additional":false,"displayPriority":6,"separation":false,"slug":"eppstein","nameParts":[{"type":"default","value":"Eppstein"}]},{"evaNumber":"8001816","name":"Eppstein-Bremthal","canceled":false,"additional":false,"displayPriority":11,"separation":false,"slug":"eppstein-bremthal","nameParts":[{"type":"default","value":"Eppstein-Bremthal"}]},{"evaNumber":"8004382","name":"Niederjosbach","canceled":false,"additional":false,"displayPriority":7,"separation":false,"slug":"niederjosbach","nameParts":[{"type":"default","value":"Niederjosbach"}]}],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Limited bicycle transport possible","locale":"en","type":"bicycle-transport","change":false,"important":false,"open":false,"links":[]}],"delay":[],"cancelation":[],"destination":[],"via":[]},"providesVehicleSequence":true}],[{"canceledStopsAfterActualDestination":[{"evaNumber":"8006691","name":"Frankfurt(M)Taunusanlage","canceled":true,"additional":false,"displayPriority":1},{"evaNumber":"8006692","name":"Frankfurt(M)Hauptwache","canceled":true,"additional":false,"displayPriority":2},{"evaNumber":"8004429","name":"Frankfurt(M)Konstablerwache","canceled":true,"additional":false,"displayPriority":3},{"evaNumber":"8002058","name":"Frankfurt(M)Ostendstraße","canceled":true,"additional":false,"displayPriority":4},{"evaNumber":"8002038","name":"Frankfurt(M)Lokalbahnhof","canceled":true,"additional":false,"displayPriority":5}],"direction":"departure","id":"8098105_D_1","timeSchedule":"2025-03-22T00:52:00+01:00","timeDelayed":"2025-03-22T00:52:00+01:00","delayed":false,"platform":"101","platformSchedule":"101","timeType":"SCHEDULE","canceled":true,"administrationID":"800528","virtual":false,"lineName":"S4","type":"CITY_TRAIN","kind":"canceled","journeyID":"20250322-2b5b5913-2b2d-39da-b29d-2fff067ba6a2","stopPlace":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)","canceled":true},"arrivalOrDepartureId":"8098105_D_1","destination":{"evaNumber":"8002041","name":"Frankfurt(Main)Süd","canceled":true,"slug":"frankfurt-main-sued","nameParts":[{"type":"default","value":"Frankfurt "},{"type":"region","value":"(Main)"},{"type":"default","value":" Süd"}]},"viaStops":[],"additionalStops":[],"canceledStops":[],"messages":{"common":[{"text":"Defective signal box","type":"unplanned-info","change":true,"important":false,"open":true,"links":[],"locale":"en"}],"delay":[],"cancelation":[{"text":"Trip cancelled","locale":"en","type":"canceled-trip","change":true,"important":true,"open":true,"links":[]}],"destination":[],"via":[]},"providesVehicleSequence":true}]]} \ No newline at end of file diff --git a/test/fixtures/dbris-departures.js b/test/fixtures/dbris-departures.js new file mode 100644 index 00000000..11ea85a6 --- /dev/null +++ b/test/fixtures/dbris-departures.js @@ -0,0 +1,580 @@ +const dbDepartures = [ + { + tripId: '20250321-69f912f7-2b47-3ffd-b00f-708e8c568f6b', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:43:00+01:00', + plannedWhen: '2025-03-22T00:42:00+01:00', + delay: 60, + platform: '103', + plannedPlatform: '103', + direction: 'Wiesbaden Hbf', + provenance: null, + line: { + type: 'line', + id: 's-1', + fahrtNr: '35182', + name: 'S 1', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: '43', + summary: 'Verspätung eines vorausfahrenden Zuges', + text: 'Verspätung eines vorausfahrenden Zuges', + type: 'status', + }, + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000250', + name: 'Wiesbaden Hbf', + }, + }, + { + tripId: '20250322-fcf0de07-fc6e-3aeb-9757-3b08e6760c3f', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:44:00+01:00', + plannedWhen: '2025-03-22T00:44:00+01:00', + delay: null, + platform: null, + plannedPlatform: null, + direction: null, + provenance: null, + line: { + type: 'line', + id: 'bus-sev-353821', + fahrtNr: '353821', + name: 'Bus SEV', + public: true, + adminCode: 'B4', + productName: 'Bus', + mode: 'train', + product: 'regional', + operator: { + type: 'operator', + id: '---', + name: 'Busse/SEV S-Bahn Rhein-Main', + }, + }, + remarks: [], + origin: null, + destination: { + type: 'station', + id: '8000752', + name: 'Bad Soden(Taunus)', + }, + }, + { + tripId: '20250321-bff43415-303b-36ad-ae4e-8d9605fc3f1e', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: null, + plannedWhen: '2025-03-22T00:44:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '102', + prognosedPlatform: '102', + direction: 'Offenbach(Main)Ost', + provenance: null, + line: { + type: 'line', + id: 's-8', + fahrtNr: '35883', + name: 'S 8', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: undefined, + summary: 'S8: Kein Betrieb möglich. Grund: Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Ersatzverkehr mit Bussen eingerichtet. Andere Verkehrsmittel mit einbeziehen. Reiseverbindung frühzeitig prüfen.', + text: 'Auf der S8 ist kein Betrieb möglich. Der Grund ist eine Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Wir haben für Sie einen Ersatzverkehr mit 8 Bussen der Firma Holiday-Reisen GmbH zwischen Wiesbaden Hbf und Frankfurt(M) Flughafen Regionalbf eingerichtet. Außerdem haben wir für Sie ab ca. 01:00 Uhr einen Ersatzverkehr mit 4 Bussen der Firma Holiday-Reisen GmbH zwischen Hanau Hbf und Offenbach(Main)Ost eingerichtet. Beziehen Sie auch andere Verkehrsmittel mit ein, um an Ihr Reiseziel zu gelangen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.', + type: 'warning', + }, + { + code: '40', + summary: 'defektes Stellwerk', + text: 'defektes Stellwerk', + type: 'status', + }, + { + code: 'CUSTOMER_TEXT', + summary: 'Auf der S8 und S9 kommt es zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Der Grund sind Bauarbeiten. Auf dem jeweils ausfallenden Abschnitt haben wir für Sie einen Ersatzverkehr mit Bussen eingerichtet. Die Mitnahme von Fahrrädern im Bus ist ausgeschlossen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können. Die Fahrplanänderungen zu dieser Baumaßnahme sind in die Online-Fahrplanauskünfte eingearbeitet.', + text: 'Auf der S8 und S9 kommt es zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Der Grund sind Bauarbeiten. Auf dem jeweils ausfallenden Abschnitt haben wir für Sie einen Ersatzverkehr mit Bussen eingerichtet. Die Mitnahme von Fahrrädern im Bus ist ausgeschlossen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können. Die Fahrplanänderungen zu dieser Baumaßnahme sind in die Online-Fahrplanauskünfte eingearbeitet.', + type: 'status', + }, + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8004645', + name: 'Offenbach(Main)Ost', + }, + cancelled: true, + }, + { + tripId: '20250322-f2c61208-75b1-3c19-a580-172988addf2c', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: null, + plannedWhen: '2025-03-22T00:47:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '103', + prognosedPlatform: '103', + direction: 'Wiesbaden Hbf', + provenance: null, + line: { + type: 'line', + id: 's-8', + fahrtNr: '35884', + name: 'S 8', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: undefined, + summary: 'S8: Kein Betrieb möglich. Grund: Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Ersatzverkehr mit Bussen eingerichtet. Andere Verkehrsmittel mit einbeziehen. Reiseverbindung frühzeitig prüfen.', + text: 'Auf der S8 ist kein Betrieb möglich. Der Grund ist eine Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Wir haben für Sie einen Ersatzverkehr mit 8 Bussen der Firma Holiday-Reisen GmbH zwischen Wiesbaden Hbf und Frankfurt(M) Flughafen Regionalbf eingerichtet. Außerdem haben wir für Sie ab ca. 01:00 Uhr einen Ersatzverkehr mit 4 Bussen der Firma Holiday-Reisen GmbH zwischen Hanau Hbf und Offenbach(Main)Ost eingerichtet. Beziehen Sie auch andere Verkehrsmittel mit ein, um an Ihr Reiseziel zu gelangen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.', + type: 'warning', + }, + { + code: '40', + summary: 'defektes Stellwerk', + text: 'defektes Stellwerk', + type: 'status', + }, + { + code: 'CUSTOMER_TEXT', + summary: 'Die Halte Frankfurt(Main)-Gateway Gardens, Frankfurt(M) Flughafen Regionalbf und Kelsterbach entfallen. Bitte prüfen Sie Ihre Reiseverbindung kurz vor der Abfahrt des Zuges.', + text: 'Die Halte Frankfurt(Main)-Gateway Gardens, Frankfurt(M) Flughafen Regionalbf und Kelsterbach entfallen. Bitte prüfen Sie Ihre Reiseverbindung kurz vor der Abfahrt des Zuges.', + type: 'status', + }, + { + code: 'CUSTOMER_TEXT', + summary: 'Auf der S8 und S9 kommt es zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Der Grund sind Bauarbeiten. Auf dem jeweils ausfallenden Abschnitt haben wir für Sie einen Ersatzverkehr mit Bussen eingerichtet. Die Mitnahme von Fahrrädern im Bus ist ausgeschlossen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können. Die Fahrplanänderungen zu dieser Baumaßnahme sind in die Online-Fahrplanauskünfte eingearbeitet.', + text: 'Auf der S8 und S9 kommt es zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Der Grund sind Bauarbeiten. Auf dem jeweils ausfallenden Abschnitt haben wir für Sie einen Ersatzverkehr mit Bussen eingerichtet. Die Mitnahme von Fahrrädern im Bus ist ausgeschlossen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können. Die Fahrplanänderungen zu dieser Baumaßnahme sind in die Online-Fahrplanauskünfte eingearbeitet.', + type: 'status', + }, + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000250', + name: 'Wiesbaden Hbf', + }, + cancelled: true, + }, + { + tripId: '20250322-1423f343-0076-3f29-b1e8-004dc1f27068', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:47:00+01:00', + plannedWhen: '2025-03-22T00:47:00+01:00', + delay: 0, + platform: '101', + plannedPlatform: '101', + direction: 'Darmstadt Hbf', + provenance: null, + line: { + type: 'line', + id: 's-6', + fahrtNr: '36683', + name: 'S 6', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000068', + name: 'Darmstadt Hbf', + }, + }, + { + tripId: '20250322-841901b7-7420-3890-8691-05c8cbbacdce', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T01:05:00+01:00', + plannedWhen: '2025-03-22T00:49:00+01:00', + delay: 960, + platform: '102', + plannedPlatform: '102', + direction: 'Rödermark-Ober Roden', + provenance: null, + line: { + type: 'line', + id: 's-1', + fahrtNr: '35185', + name: 'S 1', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: '64', + summary: 'Reparatur an einer Weiche', + text: 'Reparatur an einer Weiche', + type: 'status', + }, + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000285', + name: 'Rödermark-Ober Roden', + }, + }, + { + tripId: '20250322-08673537-4773-3e90-afa3-ab467119a609', + stop: { + type: 'station', + id: '100010', + name: 'Hauptbahnhof, Frankfurt a.M.', + }, + when: '2025-03-22T00:50:00+01:00', + plannedWhen: '2025-03-22T00:50:00+01:00', + delay: 0, + platform: null, + plannedPlatform: null, + direction: 'Bockenheimer Warte, Frankfurt a.M.', + provenance: null, + line: { + type: 'line', + id: 'u-4', + fahrtNr: '1954', + name: 'U 4', + public: true, + adminCode: 'rmv255', + productName: 'U', + mode: 'train', + product: 'subway', + operator: { + type: 'operator', + id: 'DPN', + name: 'Nahreisezug', + }, + }, + remarks: [], + origin: null, + destination: { + type: 'station', + id: '101201', + name: 'Bockenheimer Warte, Frankfurt a.M.', + }, + }, + { + tripId: '20250322-29a07ddd-969e-3660-ae2e-4d6c6af4a866', + stop: { + type: 'station', + id: '8000105', + name: 'Frankfurt(Main)Hbf', + }, + when: null, + plannedWhen: '2025-03-22T00:50:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '2', + prognosedPlatform: '2', + direction: 'Riedstadt-Goddelau', + provenance: null, + line: { + type: 'line', + id: 's-7', + fahrtNr: '35787', + name: 'S 7', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: undefined, + summary: 'S7: Kein Betrieb möglich. Grund: Kurzfristige Erkrankung von Personal. Am 21.03.25/22.03.25 von 18:00 Uhr bis voraussichtlich 03:00 Uhr. Alternative Reisemöglichkeit: RE70. Die Züge halten zusätzlich in Riedstadt-Wolfskehlen - Groß Gerau-Dornheim - Zeppelinheim. Reiseverbindung frühzeitig prüfen.', + text: 'Auf der S7 ist kein Betrieb möglich. Der Grund ist eine kurzfristige Erkrankung von Personal. Die Beeinträchtigung ist am 21.03.25/22.03.25 von 18:00 Uhr bis voraussichtlich 03:00 Uhr. Alternative Reisemöglichkeit: RE70. Die Züge halten zusätzlich für Sie in Riedstadt-Wolfskehlen - Groß Gerau-Dornheim - Zeppelinheim zum Ein- und Ausstieg. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.', + type: 'warning', + }, + { + code: '49', + summary: 'kurzfristiger Personalausfall', + text: 'kurzfristiger Personalausfall', + type: 'status', + }, + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8000126', + name: 'Riedstadt-Goddelau', + }, + cancelled: true, + }, + { + tripId: '20250322-01575b72-00ad-36da-bc88-49410d87321a', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: '2025-03-22T00:52:00+01:00', + plannedWhen: '2025-03-22T00:52:00+01:00', + delay: 0, + platform: '103', + plannedPlatform: '103', + direction: 'Niedernhausen(Taunus)', + provenance: null, + line: { + type: 'line', + id: 's-2', + fahrtNr: '35284', + name: 'S 2', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8004400', + name: 'Niedernhausen(Taunus)', + }, + }, + { + tripId: '20250322-2b5b5913-2b2d-39da-b29d-2fff067ba6a2', + stop: { + type: 'station', + id: '8098105', + name: 'Frankfurt Hbf (tief)', + }, + when: null, + plannedWhen: '2025-03-22T00:52:00+01:00', + prognosedWhen: null, + delay: null, + platform: null, + plannedPlatform: '101', + prognosedPlatform: '101', + direction: 'Frankfurt(Main)Süd', + provenance: null, + line: { + type: 'line', + id: 's-4', + fahrtNr: '35483', + name: 'S 4', + public: true, + adminCode: '800528', + productName: 'S', + mode: 'train', + product: 'suburban', + operator: { + type: 'operator', + id: 'DB', + name: 'DB Regio, S-Bahn Rhein-Main', + }, + }, + remarks: [ + { + code: undefined, + summary: 'S3 und S4: Kein Betrieb möglich. Am 21./22.03.25 von 20:00 Uhr bis voraussichtlich 04:00 Uhr. Grund: Erkrankung von Stellwerkspersonal. Ersatzverkehr mit Bussen eingerichtet. Reiseverbindung frühzeitig prüfen.', + text: 'Auf der S3 und S4 ist kein Betrieb möglich. Die Beeinträchtigung ist am 21./22.03.25 von 20:00 Uhr bis voraussichtlich 04:00 Uhr. Der Grund ist eine Erkrankung von Stellwerkspersonal. Wir haben für Sie einen Ersatzverkehr mit 8 Bussen der Firma Holiday-Reisen GmbH zwischen Frankfurt(Main)Hbf und Bad Soden(Taunus) eingerichtet. Außerdem haben wir für Sie einen Ersatzverkehr mit 7 Bussen der Firma Holiday-Reisen GmbH zwischen Frankfurt(Main)Hbf und Kronberg(Taunus) eingerichtet. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.', + type: 'warning', + }, + { + code: '40', + summary: 'defektes Stellwerk', + text: 'defektes Stellwerk', + type: 'status', + }, + { + code: 'FK', + summary: 'Fahrradmitnahme begrenzt möglich', + text: 'Fahrradmitnahme begrenzt möglich', + type: 'hint', + }, + { + code: 'EH', + summary: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + text: 'Fahrzeuggebundene Einstiegshilfe vorhanden', + type: 'hint', + }, + ], + origin: null, + destination: { + type: 'station', + id: '8002041', + name: 'Frankfurt(Main)Süd', + }, + cancelled: true, + }, +]; + +export { + dbDepartures, +}; diff --git a/test/fixtures/dbris-departures.json b/test/fixtures/dbris-departures.json new file mode 100644 index 00000000..fab29876 --- /dev/null +++ b/test/fixtures/dbris-departures.json @@ -0,0 +1 @@ +{"departures":[{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250321-69f912f7-2b47-3ffd-b00f-708e8c568f6b","timeSchedule":"2025-03-22T00:42:00+01:00","timeType":"PREVIEW","time":"2025-03-22T00:43:00+01:00","onDemand":false,"platformSchedule":"103","platform":"103","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[{"code":"43","type":"CUSTOMER_REASON","displayPriority":null,"category":null,"text":"Verspätung eines vorausfahrenden Zuges","textShort":null}],"disruptions":[],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 1","label":"","category":"S","categoryInternal":"s","number":35182,"line":"1","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8000250","name":"Wiesbaden Hbf"}]},"journeyID":"20250321-69f912f7-2b47-3ffd-b00f-708e8c568f6b","destination":{"evaNumber":"8000250","name":"Wiesbaden Hbf","canceled":false},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":false,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":false},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250322-fcf0de07-fc6e-3aeb-9757-3b08e6760c3f","timeSchedule":"2025-03-22T00:44:00+01:00","timeType":"SCHEDULE","time":"2025-03-22T00:44:00+01:00","onDemand":false,"platformSchedule":"","platform":"","administration":{"administrationID":"B4","operatorCode":"---","operatorName":"Busse/SEV S-Bahn Rhein-Main"},"messages":[],"disruptions":[],"attributes":[],"departureID":"8098105_D_1","transport":{"type":"REGIONAL_TRAIN","journeyDescription":"Bus SEV (353821)","label":"","category":"Bus","categoryInternal":"Bsv","number":353821,"line":"SEV","replacementTransport":{"realType":"BUS"},"direction":null,"journeyID":"20250322-fcf0de07-fc6e-3aeb-9757-3b08e6760c3f","destination":{"evaNumber":"8000752","name":"Bad Soden(Taunus)","canceled":false},"differingDestination":null,"via":[]},"journeyType":"REPLACEMENT","additional":false,"canceled":false,"reliefFor":[],"reliefBy":[],"replacementFor":[{"type":"CITY_TRAIN","journeyDescription":"S 3","label":"","category":"S","categoryInternal":"s","number":35382,"line":"3","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8000752","name":"Bad Soden(Taunus)"}]},"journeyID":"20250322-31e90274-7fb5-3722-bbfb-76b74f446aca","destination":{"evaNumber":"8000752","name":"Bad Soden(Taunus)","canceled":true},"differingDestination":null}],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":false},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250321-bff43415-303b-36ad-ae4e-8d9605fc3f1e","timeSchedule":"2025-03-22T00:44:00+01:00","timeType":"SCHEDULE","time":"2025-03-22T00:44:00+01:00","onDemand":false,"platformSchedule":"102","platform":"102","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[{"code":"40","type":"CUSTOMER_REASON","displayPriority":null,"category":null,"text":"defektes Stellwerk","textShort":null},{"code":null,"type":"CUSTOMER_TEXT","displayPriority":50,"category":"HIM_Bauarbeiten","text":"Auf der S8 und S9 kommt es zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Der Grund sind Bauarbeiten. Auf dem jeweils ausfallenden Abschnitt haben wir für Sie einen Ersatzverkehr mit Bussen eingerichtet. Die Mitnahme von Fahrrädern im Bus ist ausgeschlossen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können. Die Fahrplanänderungen zu dieser Baumaßnahme sind in die Online-Fahrplanauskünfte eingearbeitet.","textShort":"S8 und S9 zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 kommt es zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Grund: Bauarbeiten. Ersatzverkehr."}],"disruptions":[{"disruptionID":"d75a63f7-14bd-35c1-a0dc-acbd82739046","disruptionCommunicationID":null,"displayPriority":50,"descriptions":{"DE":{"text":"Auf der S8 ist kein Betrieb möglich. Der Grund ist eine Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Wir haben für Sie einen Ersatzverkehr mit 8 Bussen der Firma Holiday-Reisen GmbH zwischen Wiesbaden Hbf und Frankfurt(M) Flughafen Regionalbf eingerichtet. Außerdem haben wir für Sie ab ca. 01:00 Uhr einen Ersatzverkehr mit 4 Bussen der Firma Holiday-Reisen GmbH zwischen Hanau Hbf und Offenbach(Main)Ost eingerichtet. Beziehen Sie auch andere Verkehrsmittel mit ein, um an Ihr Reiseziel zu gelangen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.","textShort":"S8: Kein Betrieb möglich. Grund: Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Ersatzverkehr mit Bussen eingerichtet. Andere Verkehrsmittel mit einbeziehen. Reiseverbindung frühzeitig prüfen."}}}],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 8","label":"","category":"S","categoryInternal":"s","number":35883,"line":"8","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8004645","name":"Offenbach(Main)Ost"}]},"journeyID":"20250321-bff43415-303b-36ad-ae4e-8d9605fc3f1e","destination":{"evaNumber":"8004645","name":"Offenbach(Main)Ost","canceled":true},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":true,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":true},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250322-f2c61208-75b1-3c19-a580-172988addf2c","timeSchedule":"2025-03-22T00:47:00+01:00","timeType":"SCHEDULE","time":"2025-03-22T00:47:00+01:00","onDemand":false,"platformSchedule":"103","platform":"103","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[{"code":"40","type":"CUSTOMER_REASON","displayPriority":null,"category":null,"text":"defektes Stellwerk","textShort":null},{"code":null,"type":"CUSTOMER_TEXT","displayPriority":15,"category":"HIM_Bauarbeiten","text":"Die Halte Frankfurt(Main)-Gateway Gardens, Frankfurt(M) Flughafen Regionalbf und Kelsterbach entfallen. Bitte prüfen Sie Ihre Reiseverbindung kurz vor der Abfahrt des Zuges.","textShort":"Halte Frankfurt(Main)-Gateway Gardens, Frankfurt(M) Flughafen Regionalbf und Kelsterbach entfallen. Bitte Reiseverbindung vor Abfahrt des Zuges prüfen."},{"code":null,"type":"CUSTOMER_TEXT","displayPriority":50,"category":"HIM_Bauarbeiten","text":"Auf der S8 und S9 kommt es zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Der Grund sind Bauarbeiten. Auf dem jeweils ausfallenden Abschnitt haben wir für Sie einen Ersatzverkehr mit Bussen eingerichtet. Die Mitnahme von Fahrrädern im Bus ist ausgeschlossen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können. Die Fahrplanänderungen zu dieser Baumaßnahme sind in die Online-Fahrplanauskünfte eingearbeitet.","textShort":"S8 und S9 zwischen Wiesbaden Hbf - Frankfurt(M) Flughafen Regionalbf - Frankfurt(Main)Hbf - Offenbach(Main)Ost in den Nächten bis zum 22.03.25 kommt es zu geänderten Fahrtzeiten, einzelnen Umleitungen, Teil- und Zugausfällen. Grund: Bauarbeiten. Ersatzverkehr."}],"disruptions":[{"disruptionID":"d75a63f7-14bd-35c1-a0dc-acbd82739046","disruptionCommunicationID":null,"displayPriority":50,"descriptions":{"DE":{"text":"Auf der S8 ist kein Betrieb möglich. Der Grund ist eine Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Wir haben für Sie einen Ersatzverkehr mit 8 Bussen der Firma Holiday-Reisen GmbH zwischen Wiesbaden Hbf und Frankfurt(M) Flughafen Regionalbf eingerichtet. Außerdem haben wir für Sie ab ca. 01:00 Uhr einen Ersatzverkehr mit 4 Bussen der Firma Holiday-Reisen GmbH zwischen Hanau Hbf und Offenbach(Main)Ost eingerichtet. Beziehen Sie auch andere Verkehrsmittel mit ein, um an Ihr Reiseziel zu gelangen. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.","textShort":"S8: Kein Betrieb möglich. Grund: Erkrankung von Stellwerkspersonal. Dauer der Beeinträchtigung bis Betriebsschluss. Ersatzverkehr mit Bussen eingerichtet. Andere Verkehrsmittel mit einbeziehen. Reiseverbindung frühzeitig prüfen."}}}],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 8","label":"","category":"S","categoryInternal":"s","number":35884,"line":"8","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8000250","name":"Wiesbaden Hbf"}]},"journeyID":"20250322-f2c61208-75b1-3c19-a580-172988addf2c","destination":{"evaNumber":"8000250","name":"Wiesbaden Hbf","canceled":true},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":true,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":true},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250322-1423f343-0076-3f29-b1e8-004dc1f27068","timeSchedule":"2025-03-22T00:47:00+01:00","timeType":"PREVIEW","time":"2025-03-22T00:47:00+01:00","onDemand":false,"platformSchedule":"101","platform":"101","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[],"disruptions":[],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 6","label":"","category":"S","categoryInternal":"s","number":36683,"line":"6","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8000068","name":"Darmstadt Hbf"}]},"journeyID":"20250322-1423f343-0076-3f29-b1e8-004dc1f27068","destination":{"evaNumber":"8000068","name":"Darmstadt Hbf","canceled":false},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":false,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":false},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250322-841901b7-7420-3890-8691-05c8cbbacdce","timeSchedule":"2025-03-22T00:49:00+01:00","timeType":"PREVIEW","time":"2025-03-22T01:05:00+01:00","onDemand":false,"platformSchedule":"102","platform":"102","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[{"code":"64","type":"CUSTOMER_REASON","displayPriority":null,"category":null,"text":"Reparatur an einer Weiche","textShort":null}],"disruptions":[],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 1","label":"","category":"S","categoryInternal":"s","number":35185,"line":"1","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8000285","name":"Rödermark-Ober Roden"}]},"journeyID":"20250322-841901b7-7420-3890-8691-05c8cbbacdce","destination":{"evaNumber":"8000285","name":"Rödermark-Ober Roden","canceled":false},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":false,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":false},{"station":{"evaNumber":"100010","name":"Hauptbahnhof, Frankfurt a.M."},"journeyID":"20250322-08673537-4773-3e90-afa3-ab467119a609","timeSchedule":"2025-03-22T00:50:00+01:00","timeType":"PREVIEW","time":"2025-03-22T00:50:00+01:00","onDemand":false,"platformSchedule":"","platform":"","administration":{"administrationID":"rmv255","operatorCode":"DPN","operatorName":"Nahreisezug"},"messages":[],"disruptions":[],"attributes":[],"departureID":"100010_D_1","transport":{"type":"SUBWAY","journeyDescription":"U 4","label":"","category":"U","categoryInternal":"U","number":1954,"line":"4","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"101201","name":"Bockenheimer Warte, Frankfurt a.M."}]},"journeyID":"20250322-08673537-4773-3e90-afa3-ab467119a609","destination":{"evaNumber":"101201","name":"Bockenheimer Warte, Frankfurt a.M.","canceled":false},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":false,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":false},{"station":{"evaNumber":"8000105","name":"Frankfurt(Main)Hbf"},"journeyID":"20250322-29a07ddd-969e-3660-ae2e-4d6c6af4a866","timeSchedule":"2025-03-22T00:50:00+01:00","timeType":"SCHEDULE","time":"2025-03-22T00:50:00+01:00","onDemand":false,"platformSchedule":"2","platform":"2","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[{"code":"49","type":"CUSTOMER_REASON","displayPriority":null,"category":null,"text":"kurzfristiger Personalausfall","textShort":null}],"disruptions":[{"disruptionID":"1e3e29ee-aee9-3b6b-8a38-6963f6eb26b3","disruptionCommunicationID":null,"displayPriority":32,"descriptions":{"DE":{"text":"Auf der S7 ist kein Betrieb möglich. Der Grund ist eine kurzfristige Erkrankung von Personal. Die Beeinträchtigung ist am 21.03.25/22.03.25 von 18:00 Uhr bis voraussichtlich 03:00 Uhr. Alternative Reisemöglichkeit: RE70. Die Züge halten zusätzlich für Sie in Riedstadt-Wolfskehlen - Groß Gerau-Dornheim - Zeppelinheim zum Ein- und Ausstieg. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.","textShort":"S7: Kein Betrieb möglich. Grund: Kurzfristige Erkrankung von Personal. Am 21.03.25/22.03.25 von 18:00 Uhr bis voraussichtlich 03:00 Uhr. Alternative Reisemöglichkeit: RE70. Die Züge halten zusätzlich in Riedstadt-Wolfskehlen - Groß Gerau-Dornheim - Zeppelinheim. Reiseverbindung frühzeitig prüfen."}}}],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8000105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 7","label":"","category":"S","categoryInternal":"s","number":35787,"line":"7","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8000126","name":"Riedstadt-Goddelau"}]},"journeyID":"20250322-29a07ddd-969e-3660-ae2e-4d6c6af4a866","destination":{"evaNumber":"8000126","name":"Riedstadt-Goddelau","canceled":true},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":true,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":true},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250322-01575b72-00ad-36da-bc88-49410d87321a","timeSchedule":"2025-03-22T00:52:00+01:00","timeType":"PREVIEW","time":"2025-03-22T00:52:00+01:00","onDemand":false,"platformSchedule":"103","platform":"103","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[],"disruptions":[],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 2","label":"","category":"S","categoryInternal":"s","number":35284,"line":"2","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8004400","name":"Niedernhausen(Taunus)"}]},"journeyID":"20250322-01575b72-00ad-36da-bc88-49410d87321a","destination":{"evaNumber":"8004400","name":"Niedernhausen(Taunus)","canceled":false},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":false,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":false},{"station":{"evaNumber":"8098105","name":"Frankfurt Hbf (tief)"},"journeyID":"20250322-2b5b5913-2b2d-39da-b29d-2fff067ba6a2","timeSchedule":"2025-03-22T00:52:00+01:00","timeType":"SCHEDULE","time":"2025-03-22T00:52:00+01:00","onDemand":false,"platformSchedule":"101","platform":"101","administration":{"administrationID":"800528","operatorCode":"DB","operatorName":"DB Regio, S-Bahn Rhein-Main"},"messages":[{"code":"40","type":"CUSTOMER_REASON","displayPriority":null,"category":null,"text":"defektes Stellwerk","textShort":null}],"disruptions":[{"disruptionID":"be2b574e-7fae-3804-a348-a58500b592b4","disruptionCommunicationID":null,"displayPriority":50,"descriptions":{"DE":{"text":"Auf der S3 und S4 ist kein Betrieb möglich. Die Beeinträchtigung ist am 21./22.03.25 von 20:00 Uhr bis voraussichtlich 04:00 Uhr. Der Grund ist eine Erkrankung von Stellwerkspersonal. Wir haben für Sie einen Ersatzverkehr mit 8 Bussen der Firma Holiday-Reisen GmbH zwischen Frankfurt(Main)Hbf und Bad Soden(Taunus) eingerichtet. Außerdem haben wir für Sie einen Ersatzverkehr mit 7 Bussen der Firma Holiday-Reisen GmbH zwischen Frankfurt(Main)Hbf und Kronberg(Taunus) eingerichtet. Bitte informieren Sie sich frühzeitig über Ihre geplanten Verbindungen und wählen Sie gegebenenfalls eine frühere Zugverbindung, um Ihre Anschlüsse an Ihren Umsteigebahnhöfen erreichen zu können.","textShort":"S3 und S4: Kein Betrieb möglich. Am 21./22.03.25 von 20:00 Uhr bis voraussichtlich 04:00 Uhr. Grund: Erkrankung von Stellwerkspersonal. Ersatzverkehr mit Bussen eingerichtet. Reiseverbindung frühzeitig prüfen."}}}],"attributes":[{"displayPriority":null,"displayPriorityDetail":null,"code":"FK","text":"Fahrradmitnahme begrenzt möglich","textShort":null},{"displayPriority":null,"displayPriorityDetail":null,"code":"EH","text":"Fahrzeuggebundene Einstiegshilfe vorhanden","textShort":null}],"departureID":"8098105_D_1","transport":{"type":"CITY_TRAIN","journeyDescription":"S 4","label":"","category":"S","categoryInternal":"s","number":35483,"line":"4","replacementTransport":null,"direction":{"text":null,"stopPlaces":[{"evaNumber":"8002041","name":"Frankfurt(Main)Süd"}]},"journeyID":"20250322-2b5b5913-2b2d-39da-b29d-2fff067ba6a2","destination":{"evaNumber":"8002041","name":"Frankfurt(Main)Süd","canceled":true},"differingDestination":null,"via":[]},"journeyType":"REGULAR","additional":false,"canceled":true,"reliefFor":[],"reliefBy":[],"replacementFor":[],"replacedBy":[],"continuationBy":null,"travelsWith":[],"codeshares":[],"futureDisruptions":true}],"disruptions":[]} \ No newline at end of file diff --git a/test/fixtures/dbweb-departures.js b/test/fixtures/dbweb-departures.js index ec3ff151..e52a592f 100644 --- a/test/fixtures/dbweb-departures.js +++ b/test/fixtures/dbweb-departures.js @@ -1290,7 +1290,7 @@ const dbwebDepartures = [ }, remarks: [ { - code: undefined, + code: 'HALT_AUSFALL', summary: 'Halt entfällt', text: 'Halt entfällt', type: 'warning',