diff --git a/p/dbnav/journeys-req.js b/p/dbnav/journeys-req.js index 4c07bf1f..8cc8631f 100644 --- a/p/dbnav/journeys-req.js +++ b/p/dbnav/journeys-req.js @@ -31,7 +31,7 @@ const formatJourneysReq = (ctx, from, to, when, outFrwd, journeysRef) => { from = profile.formatLocation(profile, from, 'from'); to = profile.formatLocation(profile, to, 'to'); const filters = profile.formatProductsFilter({profile}, opt.products || {}, 'dbnav'); - const transfers = profile.formatTransfers(opt.transfers) ?? undefined; // `dbnav` does not allow `undefined` here + const transfers = profile.formatTransfers(opt.transfers) ?? undefined; // `dbnav` does not allow `null` here // TODO opt.accessibility // TODO routingMode let query = formatBaseJourneysReq(ctx); diff --git a/readme.md b/readme.md index 479d0bce..6e7dc98a 100644 --- a/readme.md +++ b/readme.md @@ -30,7 +30,8 @@ Depending on the configured profile, db-vendo-client will use multiple different | cancelled trips | not contained in boards | contained with cancelled flag | | tickets | only for `refreshJourney()` | only for `refreshJourney()`, mutually exclusive with polylines | | polylines | only for `trip()` | only for `refreshJourney()/trip()`, mutually exclusive with tickets | -| trip ids used | HAFAS trip ids for journeys, RIS trip ids for boards | HAFAS trip ids | +| trip ids used | HAFAS trip ids for journeys, RIS trip ids for boards (static on train splits?) | HAFAS trip ids | +| line.id/fahrtNr used | unreliable/route id for journeys, actual fahrtNr for boards | unreliable/route id | | `stop()` | ❌ | ✅ | | assumed backend API stability | less stable | more stable | diff --git a/test/format/dbnav-journeys-query.js b/test/format/dbnav-journeys-query.js new file mode 100644 index 00000000..b5fb6342 --- /dev/null +++ b/test/format/dbnav-journeys-query.js @@ -0,0 +1,136 @@ +import tap from 'tap'; + +import {createClient} from '../../index.js'; +import {profile as rawProfile} from '../../p/dbnav/index.js'; +import {data as loyaltyCards} from '../../format/loyalty-cards.js'; + +const client = createClient(rawProfile, 'public-transport/hafas-client:test'); +const {profile} = client; + +const opt = { + results: null, + via: null, + stopovers: false, + transfers: null, + transferTime: 0, + accessibility: 'none', + bike: false, + walkingSpeed: 'normal', + startWithWalking: true, + tickets: false, + polylines: false, + subStops: true, + entrances: true, + remarks: true, + scheduledDays: false, + departure: '2023-09-12T08:09:10+02:00', + products: {}, + + firstClass: false, + age: 24, + loyaltyCard: { + type: loyaltyCards.BAHNCARD, + discount: 25, + }, +}; + +const berlinWienQuery0 = Object.freeze( + { + autonomeReservierung: false, + reservierungsKontingenteVorhanden: false, + einstiegsTypList: [ + 'STANDARD', + ], + klasse: 'KLASSE_2', + reiseHin: { + wunsch: { + abgangsLocationId: 'A=1@L=8098160@', + verkehrsmittel: [ + 'ALL', + ], + zeitWunsch: { + reiseDatum: '2024-12-07T23:50:12+01:00', + zeitPunktArt: 'ABFAHRT', + }, + viaLocations: undefined, + zielLocationId: 'A=1@L=8000284@', + maxUmstiege: undefined, + minUmstiegsdauer: undefined, + fahrradmitnahme: false, + }, + }, + }); + +tap.test('formats a journeys() request correctly (DBnav)', (t) => { + const _opt = {...opt}; + delete _opt.loyaltyCard; + delete _opt.age; + const ctx = {profile, opt: _opt}; + + const req = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + t.same(req.body, { + ...berlinWienQuery0, + reisendenProfil: { + reisende: [ + { + ermaessigungen: [ + 'KEINE_ERMAESSIGUNG KLASSENLOS', + ], + reisendenTyp: 'ERWACHSENER', + alter: undefined, + }, + ], + }, + }); + t.end(); +}); + + +tap.test('formats a journeys() request with BC correctly (DBnav)', (t) => { + const ctx = {profile, opt}; + + const req = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + + t.same(req.body, { + ...berlinWienQuery0, + reisendenProfil: { + reisende: [ + { + ermaessigungen: [ + 'BAHNCARD25 KLASSE_2', + ], + reisendenTyp: 'JUGENDLICHER', + alter: 24, + }, + ], + }, + }); + t.end(); +}); + +tap.test('formats a journeys() request with unlimited transfers (DBnav)', (t) => { + const _opt = {...opt}; + const ctx = {profile, opt: _opt}; + + ctx.opt.transfers = 1; // 1 transfer + const reqOneTransfer = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + t.equal(reqOneTransfer.body.reiseHin.wunsch.maxUmstiege, 1); + + ctx.opt.transfers = 0; // no transfers + const reqZeroTransfers = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + t.equal(reqZeroTransfers.body.reiseHin.wunsch.maxUmstiege, 0); + + ctx.opt.transfers = null; // unconstrained transfers implicit + const reqUnlimitedTransfersImplicitNull = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + t.equal(reqUnlimitedTransfersImplicitNull.body.reiseHin.wunsch.maxUmstiege, undefined); + + ctx.opt.transfers = undefined; // unconstrained transfers implicit + const reqUnlimitedTransfersImplicit = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + t.equal(reqUnlimitedTransfersImplicit.body.reiseHin.wunsch.maxUmstiege, undefined); + + ctx.opt.transfers = -1; // unconstrained transfers explicit + const reqUnlimitedTransfersExplicit = profile.formatJourneysReq(ctx, '8098160', '8000284', new Date('2024-12-07T23:50:12+01:00'), true, null); + t.equal(reqUnlimitedTransfersExplicit.body.reiseHin.wunsch.maxUmstiege, undefined); + + t.end(); +});