arrivals/departures: return obj with realtimeDataUpdatedAt & results 💥📝

This commit is contained in:
Jannis R 2021-12-29 21:11:07 +01:00
parent 1000e48dfd
commit c4470ca962
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
33 changed files with 198 additions and 148 deletions

View file

@ -55,7 +55,7 @@ await client.departures('900000024101', {products: {tram: false, ferry: false}})
*Note:* As stated in the [*Friendly Public Transport Format* v2 draft spec](https://github.com/public-transport/friendly-public-transport-format/blob/3bd36faa721e85d9f5ca58fb0f38cdbedb87bbca/spec/readme.md), the `when` field includes the current delay. The `delay` field, if present, expresses how much the former differs from the schedule. *Note:* As stated in the [*Friendly Public Transport Format* v2 draft spec](https://github.com/public-transport/friendly-public-transport-format/blob/3bd36faa721e85d9f5ca58fb0f38cdbedb87bbca/spec/readme.md), the `when` field includes the current delay. The `delay` field, if present, expresses how much the former differs from the schedule.
You may pass the `tripId` field into [`trip(id, lineName, [opt])`](trip.md) to get details on the vehicle's trip. You may pass a departure's `tripId` into [`trip(id, lineName, [opt])`](trip.md) to get details on the whole trip.
As an example, we're going to use the [VBB profile](../p/vbb): As an example, we're going to use the [VBB profile](../p/vbb):
@ -66,10 +66,15 @@ const vbbProfile = require('hafas-client/p/vbb')
const client = createClient(vbbProfile, 'my-awesome-program') const client = createClient(vbbProfile, 'my-awesome-program')
// S Charlottenburg // S Charlottenburg
await client.departures('900000024101', {duration: 3}) const {
departures,
realtimeDataUpdatedAt,
} = await client.departures('900000024101', {duration: 3})
``` ```
The result may look like this: `realtimeDataUpdatedAt` is a UNIX timestamp reflecting the latest moment when (at least some) of the response's realtime data have been updated.
`departures` may look like this:
```js ```js
[ { [ {

View file

@ -38,7 +38,7 @@ const createClient = (profile, userAgent, opt = {}) => {
throw new TypeError('userAgent must be a string'); throw new TypeError('userAgent must be a string');
} }
const _stationBoard = async (station, type, parse, opt = {}) => { const _stationBoard = async (station, type, resultsField, parse, opt = {}) => {
if (isObj(station)) station = profile.formatStation(station.id) if (isObj(station)) station = profile.formatStation(station.id)
else if ('string' === typeof station) station = profile.formatStation(station) else if ('string' === typeof station) station = profile.formatStation(station)
else throw new TypeError('station must be an object or a string.') else throw new TypeError('station must be an object or a string.')
@ -75,19 +75,25 @@ const createClient = (profile, userAgent, opt = {}) => {
const req = profile.formatStationBoardReq({profile, opt}, station, type) const req = profile.formatStationBoardReq({profile, opt}, station, type)
const {res, common} = await profile.request({profile, opt}, userAgent, req) const {res, common} = await profile.request({profile, opt}, userAgent, req)
if (!Array.isArray(res.jnyL)) return []
const ctx = {profile, opt, common, res} const ctx = {profile, opt, common, res}
// todo [breaking]: return object with realtimeDataUpdatedAt const jnyL = Array.isArray(res.jnyL) ? res.jnyL : []
return res.jnyL.map(res => parse(ctx, res)) const results = jnyL.map(res => parse(ctx, res))
.sort((a, b) => new Date(a.when) - new Date(b.when)) // todo .sort((a, b) => new Date(a.when) - new Date(b.when)) // todo
return {
[resultsField]: results,
realtimeDataUpdatedAt: res.planrtTS && res.planrtTS !== '0'
? parseInt(res.planrtTS)
: null,
}
} }
const departures = async (station, opt = {}) => { const departures = async (station, opt = {}) => {
return await _stationBoard(station, 'DEP', profile.parseDeparture, opt) return await _stationBoard(station, 'DEP', 'departures', profile.parseDeparture, opt)
} }
const arrivals = async (station, opt = {}) => { const arrivals = async (station, opt = {}) => {
return await _stationBoard(station, 'ARR', profile.parseArrival, opt) return await _stationBoard(station, 'ARR', 'arrivals', profile.parseArrival, opt)
} }
const journeys = async (from, to, opt = {}) => { const journeys = async (from, to, opt = {}) => {

View file

@ -299,13 +299,13 @@ tap.test('journeys: via works with detour', async (t) => {
// todo: without detour test // todo: without detour test
tap.test('departures', async (t) => { tap.test('departures', async (t) => {
const departures = await client.departures(spichernstr, { const res = await client.departures(spichernstr, {
duration: 5, when duration: 5, when
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: spichernstr id: spichernstr
}) })
@ -313,7 +313,7 @@ tap.test('departures', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: spichernstr, id: spichernstr,
name: 'U Spichernstr', name: 'U Spichernstr',
@ -324,7 +324,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -349,13 +349,13 @@ tap.test('departures at 7-digit station', async (t) => {
}) })
tap.test('arrivals', async (t) => { tap.test('arrivals', async (t) => {
const arrivals = await client.arrivals(spichernstr, { const res = await client.arrivals(spichernstr, {
duration: 5, when duration: 5, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: spichernstr id: spichernstr
}) })

View file

@ -183,13 +183,13 @@ tap.test('trip', async (t) => {
}) })
tap.test('departures at Ettelbruck.', async (t) => { tap.test('departures at Ettelbruck.', async (t) => {
const departures = await client.departures(ettelbruck, { const res = await client.departures(ettelbruck, {
duration: 20, when duration: 20, when
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: ettelbruck id: ettelbruck
}) })
@ -197,13 +197,13 @@ tap.test('departures at Ettelbruck.', async (t) => {
}) })
tap.test('arrivals at Ettelbruck.', async (t) => { tap.test('arrivals at Ettelbruck.', async (t) => {
const arrivals = await client.arrivals(ettelbruck, { const res = await client.arrivals(ettelbruck, {
duration: 20, when duration: 20, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: ettelbruck id: ettelbruck
}) })
@ -211,7 +211,7 @@ tap.test('arrivals at Ettelbruck.', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: ettelbruck, id: ettelbruck,
name: 'Ettelbruck', name: 'Ettelbruck',
@ -222,7 +222,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })

View file

@ -162,13 +162,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures at Broadie Oaks', async (t) => { tap.test('departures at Broadie Oaks', async (t) => {
const departures = await client.departures(broadieOaks, { const res = await client.departures(broadieOaks, {
duration: 10, when, duration: 10, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: broadieOaks id: broadieOaks
}) })
@ -176,7 +176,7 @@ tap.test('departures at Broadie Oaks', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: broadieOaks, id: broadieOaks,
name: 'Magdeburg Hbf', name: 'Magdeburg Hbf',
@ -187,18 +187,18 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
tap.test('arrivals at Broadie Oaks', async (t) => { tap.test('arrivals at Broadie Oaks', async (t) => {
const arrivals = await client.arrivals(broadieOaks, { const res = await client.arrivals(broadieOaks, {
duration: 10, when duration: 10, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: broadieOaks id: broadieOaks
}) })

View file

@ -34,13 +34,13 @@ const bielefeldHbf = '8000036'
const hagenVorhalle = '8000977' const hagenVorhalle = '8000977'
tap.test('departures at Hagen Bauhaus', async (t) => { tap.test('departures at Hagen Bauhaus', async (t) => {
const departures = await client.departures(hagenBauhaus, { const res = await client.departures(hagenBauhaus, {
duration: 120, when, duration: 120, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: hagenBauhaus id: hagenBauhaus
}) })
@ -48,11 +48,11 @@ tap.test('departures at Hagen Bauhaus', async (t) => {
}) })
tap.test('trip details', async (t) => { tap.test('trip details', async (t) => {
const deps = await client.departures(hagenBauhaus, { const res = await client.departures(hagenBauhaus, {
results: 1, duration: 120, when results: 1, duration: 120, when
}) })
const p = deps[0] || {} const p = res.departures[0] || {}
t.ok(p.tripId, 'precondition failed') t.ok(p.tripId, 'precondition failed')
t.ok(p.line.name, 'precondition failed') t.ok(p.line.name, 'precondition failed')
const trip = await client.trip(p.tripId, p.line.name, {when}) const trip = await client.trip(p.tripId, p.line.name, {when})
@ -62,7 +62,7 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: hagenBauhaus, id: hagenBauhaus,
name: 'Hagen(Westf) Bauhaus', name: 'Hagen(Westf) Bauhaus',
@ -73,20 +73,20 @@ tap.test('departures with station object', async (t) => {
} }
}, {when, duration: 120}) }, {when, duration: 120})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
// todo: departures at hagenBauhaus in direction of … // todo: departures at hagenBauhaus in direction of …
tap.test('arrivals at Hagen Bauhaus', async (t) => { tap.test('arrivals at Hagen Bauhaus', async (t) => {
const arrivals = await client.arrivals(hagenBauhaus, { const res = await client.arrivals(hagenBauhaus, {
duration: 120, when duration: 120, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: hagenBauhaus id: hagenBauhaus
}) })

View file

@ -330,13 +330,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures at Berlin Schwedter Str.', async (t) => { tap.test('departures at Berlin Schwedter Str.', async (t) => {
const departures = await client.departures(blnSchwedterStr, { const res = await client.departures(blnSchwedterStr, {
duration: 5, when, duration: 5, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: blnSchwedterStr id: blnSchwedterStr
}) })
@ -344,7 +344,7 @@ tap.test('departures at Berlin Schwedter Str.', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: jungfernheide, id: jungfernheide,
name: 'Berlin Jungfernheide', name: 'Berlin Jungfernheide',
@ -355,7 +355,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -373,13 +373,13 @@ tap.test('departures at Berlin Hbf in direction of Berlin Ostbahnhof', async (t)
}) })
tap.test('arrivals at Berlin Schwedter Str.', async (t) => { tap.test('arrivals at Berlin Schwedter Str.', async (t) => {
const arrivals = await client.arrivals(blnSchwedterStr, { const res = await client.arrivals(blnSchwedterStr, {
duration: 5, when, duration: 5, when,
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: blnSchwedterStr id: blnSchwedterStr
}) })
@ -434,7 +434,7 @@ tap.test('stop', async (t) => {
}) })
tap.test('line with additionalName', async (t) => { tap.test('line with additionalName', async (t) => {
const departures = await client.departures(potsdamHbf, { const {departures} = await client.departures(potsdamHbf, {
when, when,
duration: 12 * 60, // 12 minutes duration: 12 * 60, // 12 minutes
products: {bus: false, suburban: false, tram: false} products: {bus: false, suburban: false, tram: false}

View file

@ -151,13 +151,13 @@ tap.skip('trip details', async (t) => {
}) })
tap.skip('departures at Hamburg Barmbek', async (t) => { tap.skip('departures at Hamburg Barmbek', async (t) => {
const departures = await client.departures(barmbek, { const res = await client.departures(barmbek, {
duration: 5, when, duration: 5, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: barmbek id: barmbek
}) })
@ -165,7 +165,7 @@ tap.skip('departures at Hamburg Barmbek', async (t) => {
}) })
tap.skip('departures with station object', async (t) => { tap.skip('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: tiefstack, id: tiefstack,
name: 'Hamburg Tiefstack', name: 'Hamburg Tiefstack',
@ -176,7 +176,7 @@ tap.skip('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -194,13 +194,13 @@ tap.skip('departures at Barmbek in direction of Altona', async (t) => {
}) })
tap.skip('arrivals at Hamburg Barmbek', async (t) => { tap.skip('arrivals at Hamburg Barmbek', async (t) => {
const arrivals = await client.arrivals(barmbek, { const res = await client.arrivals(barmbek, {
duration: 5, when duration: 5, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: barmbek id: barmbek
}) })

View file

@ -189,13 +189,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures at Magdeburg Universität', async (t) => { tap.test('departures at Magdeburg Universität', async (t) => {
const departures = await client.departures(universitaet, { const res = await client.departures(universitaet, {
duration: 30, when, duration: 30, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: universitaet id: universitaet
}) })
@ -203,7 +203,7 @@ tap.test('departures at Magdeburg Universität', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'stop', type: 'stop',
id: universitaet, id: universitaet,
name: 'Universität', name: 'Universität',
@ -216,7 +216,7 @@ tap.test('departures with station object', async (t) => {
duration: 30, when, duration: 30, when,
}) })
validate(t, deps, 'departures', 'deps') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -235,13 +235,13 @@ tap.test('departures at Universität in direction of Spielhagenstr.', async (t)
}) })
tap.test('arrivals at Magdeburg Universität', async (t) => { tap.test('arrivals at Magdeburg Universität', async (t) => {
const arrivals = await client.arrivals(universitaet, { const res = await client.arrivals(universitaet, {
duration: 30, when duration: 30, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: universitaet id: universitaet
}) })

View file

@ -181,13 +181,13 @@ tap.test('departures at Ingolstadt Hbf', async (t) => {
'80303', // stop "Ingolstadt, Hauptbahnhof Stadtauswärts" '80303', // stop "Ingolstadt, Hauptbahnhof Stadtauswärts"
] ]
const deps = await client.departures(ingolstadtHbf, { const res = await client.departures(ingolstadtHbf, {
duration: 10, when duration: 10, when
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures: deps, res,
validate, validate,
ids, ids,
}) })
@ -195,7 +195,7 @@ tap.test('departures at Ingolstadt Hbf', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: ingolstadtHbf, id: ingolstadtHbf,
name: 'Ingolstadt Hbf', name: 'Ingolstadt Hbf',
@ -206,7 +206,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -217,13 +217,13 @@ tap.test('arrivals at Ingolstadt Hbf', async (t) => {
'80302' // stop "Ingolstadt, Hauptbahnhof Stadteinwärts" '80302' // stop "Ingolstadt, Hauptbahnhof Stadteinwärts"
] ]
const arrs = await client.arrivals(ingolstadtHbf, { const res = await client.arrivals(ingolstadtHbf, {
duration: 10, when duration: 10, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals: arrs, res,
validate, validate,
ids, ids,
}) })

View file

@ -1,14 +1,15 @@
'use strict' 'use strict'
const testArrivals = async (cfg) => { const testArrivals = async (cfg) => {
const {test: t, arrivals: arrs, validate} = cfg const {test: t, res, validate} = cfg
const ids = cfg.ids || (cfg.id ? [cfg.id] : []) const ids = cfg.ids || (cfg.id ? [cfg.id] : [])
const {arrivals: arrs} = res
validate(t, res, 'arrivalsResponse', 'res')
validate(t, arrs, 'arrivals', 'arrivals')
t.ok(arrs.length > 0, 'must be >0 arrivals')
for (let i = 0; i < arrs.length; i++) { for (let i = 0; i < arrs.length; i++) {
let stop = arrs[i].stop let stop = arrs[i].stop
let name = `arrs[${i}].stop` let name = `res.arrivals[${i}].stop`
if (stop.station) { if (stop.station) {
stop = stop.station stop = stop.station
name += '.station' name += '.station'
@ -22,7 +23,7 @@ const testArrivals = async (cfg) => {
} }
// todo: move into arrivals validator // todo: move into arrivals validator
t.same(arrs, arrs.sort((a, b) => t.when > b.when), 'arrivals must be sorted by .when') t.same(arrs, arrs.sort((a, b) => t.when > b.when), 'res.arrivals must be sorted by .when')
} }
module.exports = testArrivals module.exports = testArrivals

View file

@ -11,12 +11,13 @@ const testDeparturesInDirection = async (cfg) => {
validate validate
} = cfg } = cfg
const deps = await fetchDepartures(id, { const res = await fetchDepartures(id, {
direction: directionIds[0], direction: directionIds[0],
when when
}) })
validate(t, deps, 'departures', 'departures') const {departures: deps} = res
t.ok(deps.length > 0, 'must be >0 departures')
validate(t, res, 'departuresResponse', 'res')
for (let i = 0; i < deps.length; i++) { for (let i = 0; i < deps.length; i++) {
const dep = deps[i] const dep = deps[i]

View file

@ -1,14 +1,15 @@
'use strict' 'use strict'
const testDepartures = async (cfg) => { const testDepartures = async (cfg) => {
const {test: t, departures: deps, validate} = cfg const {test: t, res, validate} = cfg
const ids = cfg.ids || (cfg.id ? [cfg.id] : []) const ids = cfg.ids || (cfg.id ? [cfg.id] : [])
const {departures: deps} = res
validate(t, res, 'departuresResponse', 'res')
validate(t, deps, 'departures', 'departures')
t.ok(deps.length > 0, 'must be >0 departures')
for (let i = 0; i < deps.length; i++) { for (let i = 0; i < deps.length; i++) {
let stop = deps[i].stop let stop = deps[i].stop
let name = `deps[${i}].stop` let name = `res.departures[${i}].stop`
if (stop.station) { if (stop.station) {
stop = stop.station stop = stop.station
name += '.station' name += '.station'
@ -22,7 +23,7 @@ const testDepartures = async (cfg) => {
} }
// todo: move into deps validator // todo: move into deps validator
t.same(deps, deps.sort((a, b) => t.when > b.when), 'departures must be sorted by .when') t.same(deps, deps.sort((a, b) => t.when > b.when), 'res.departures must be sorted by .when')
} }
module.exports = testDepartures module.exports = testDepartures

View file

@ -23,11 +23,10 @@ const createWhen = (timezone, locale, tMock) => {
}).startOf('week').plus({weeks: 1, hours: 10}).toJSDate() }).startOf('week').plus({weeks: 1, hours: 10}).toJSDate()
} }
const assertValidWhen = (actual, expected, name) => { const assertValidWhen = (actual, expected, name, delta = day + 6 * hour) => {
const ts = +new Date(actual) const ts = +new Date(actual)
a.ok(!Number.isNaN(ts), name + ' is not parsable by Date') a.ok(!Number.isNaN(ts), name + ' is not parsable by Date')
// the timestamps might be from long-distance trains // the timestamps might be from long-distance trains
const delta = day + 6 * hour
if (!isRoughlyEqual(delta, +expected, ts)) { if (!isRoughlyEqual(delta, +expected, ts)) {
throw new AssertionError({ throw new AssertionError({
message: name + ' is out of range', message: name + ' is out of range',

View file

@ -6,9 +6,18 @@ const anyOf = require('validate-fptf/lib/any-of')
const {assertValidWhen} = require('./util') const {assertValidWhen} = require('./util')
const DAY = 24 * 60 * 60 * 1000
const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o) const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o)
const is = val => val !== null && val !== undefined const is = val => val !== null && val !== undefined
const createValidateRealtimeDataUpdatedAt = (cfg) => {
const validateRealtimeDataUpdatedAt = (val, rtDataUpdatedAt, name = 'realtimeDataUpdatedAt') => {
assertValidWhen(rtDataUpdatedAt * 1000, cfg.when, name, 100 * DAY)
}
return validateRealtimeDataUpdatedAt
}
const createValidateProducts = (cfg) => { const createValidateProducts = (cfg) => {
const validateProducts = (val, p, name = 'products') => { const validateProducts = (val, p, name = 'products') => {
a.ok(isObj(p), name + ' must be an object') a.ok(isObj(p), name + ' must be an object')
@ -518,6 +527,24 @@ const createValidateDepartures = (cfg) => {
return _createValidateStationBoardResults(cfg, 'departure') return _createValidateStationBoardResults(cfg, 'departure')
} }
const _createValidateStationBoardResponse = (cfg, validatorsKey, arrsOrDepsKey) => {
const _validateStationBoardResponse = (val, res, name) => {
a.ok(isObj(res), name + ' must be an object')
val.realtimeDataUpdatedAt(val, res.realtimeDataUpdatedAt, name + '.realtimeDataUpdatedAt')
const arrsOrDeps = res[arrsOrDepsKey]
val[validatorsKey](val, arrsOrDeps, `${name}.${arrsOrDepsKey}`)
}
return _validateStationBoardResponse
}
const createValidateArrivalsResponse = (cfg) => {
return _createValidateStationBoardResponse(cfg, 'arrivals', 'arrivals')
}
const createValidateDeparturesResponse = (cfg) => {
return _createValidateStationBoardResponse(cfg, 'departures', 'departures')
}
const createValidateMovement = (cfg) => { const createValidateMovement = (cfg) => {
const { maxLatitude, minLatitude, maxLongitude, minLongitude } = cfg const { maxLatitude, minLatitude, maxLongitude, minLongitude } = cfg
const validateMovement = (val, m, name = 'movement') => { const validateMovement = (val, m, name = 'movement') => {
@ -576,6 +603,7 @@ const validateMovements = (val, ms, name = 'movements') => {
} }
module.exports = { module.exports = {
realtimeDataUpdatedAt: createValidateRealtimeDataUpdatedAt,
products: createValidateProducts, products: createValidateProducts,
station: createValidateStation, station: createValidateStation,
stop: () => validateStop, stop: () => validateStop,
@ -596,6 +624,8 @@ module.exports = {
departure: createValidateDeparture, departure: createValidateDeparture,
arrivals: createValidateArrivals, arrivals: createValidateArrivals,
departures: createValidateDepartures, departures: createValidateDepartures,
arrivalsResponse: createValidateArrivalsResponse,
departuresResponse: createValidateDeparturesResponse,
movement: createValidateMovement, movement: createValidateMovement,
movements: () => validateMovements movements: () => validateMovements
} }

View file

@ -156,13 +156,13 @@ tap.test('departures at Soest', async (t) => {
'902737', // Bahnhof E, Soest '902737', // Bahnhof E, Soest
] ]
const departures = await client.departures(soest, { const res = await client.departures(soest, {
duration: 10, when, duration: 10, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
ids, ids,
}) })
@ -170,7 +170,7 @@ tap.test('departures at Soest', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: soest, id: soest,
name: 'Magdeburg Hbf', name: 'Magdeburg Hbf',
@ -181,7 +181,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -193,13 +193,13 @@ tap.test('arrivals at Soest', async (t) => {
'902737', // Bahnhof E, Soest '902737', // Bahnhof E, Soest
] ]
const arrivals = await client.arrivals(soest, { const res = await client.arrivals(soest, {
duration: 10, when, duration: 10, when,
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
ids, ids,
}) })

View file

@ -187,13 +187,13 @@ tap.test('trip', async (t) => {
}) })
tap.test('departures at Ettelbruck.', async (t) => { tap.test('departures at Ettelbruck.', async (t) => {
const departures = await client.departures(ettelbruck, { const res = await client.departures(ettelbruck, {
duration: 20, when duration: 20, when
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: ettelbruck id: ettelbruck
}) })
@ -201,13 +201,13 @@ tap.test('departures at Ettelbruck.', async (t) => {
}) })
tap.test('arrivals at Ettelbruck.', async (t) => { tap.test('arrivals at Ettelbruck.', async (t) => {
const arrivals = await client.arrivals(ettelbruck, { const res = await client.arrivals(ettelbruck, {
duration: 20, when duration: 20, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: ettelbruck id: ettelbruck
}) })
@ -215,7 +215,7 @@ tap.test('arrivals at Ettelbruck.', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: ettelbruck, id: ettelbruck,
name: 'Ettelbruck', name: 'Ettelbruck',
@ -226,7 +226,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })

View file

@ -224,13 +224,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures at Kiel Räucherei', async (t) => { tap.test('departures at Kiel Räucherei', async (t) => {
const departures = await client.departures(kielRaeucherei, { const res = await client.departures(kielRaeucherei, {
duration: 30, when, duration: 30, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: kielRaeucherei id: kielRaeucherei
}) })
@ -238,7 +238,7 @@ tap.test('departures at Kiel Räucherei', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: kielHbf, id: kielHbf,
name: 'Kiel Hbf', name: 'Kiel Hbf',
@ -249,7 +249,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -267,13 +267,13 @@ tap.test('departures at Berlin Hbf in direction of Berlin Ostbahnhof', async (t)
}) })
tap.test('arrivals at Kiel Räucherei', async (t) => { tap.test('arrivals at Kiel Räucherei', async (t) => {
const arrivals = await client.arrivals(kielRaeucherei, { const res = await client.arrivals(kielRaeucherei, {
duration: 30, when duration: 30, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: kielRaeucherei id: kielRaeucherei
}) })

View file

@ -171,13 +171,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures at Kassel Auestadion.', async (t) => { tap.test('departures at Kassel Auestadion.', async (t) => {
const departures = await client.departures(auestadion, { const res = await client.departures(auestadion, {
duration: 11, when, duration: 11, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: auestadion id: auestadion
}) })
@ -185,7 +185,7 @@ tap.test('departures at Kassel Auestadion.', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: auestadion, id: auestadion,
name: 'Kassel Auestadion', name: 'Kassel Auestadion',
@ -196,7 +196,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -214,13 +214,13 @@ tap.test('departures at Auestadion in direction of Friedrichsplatz', async (t) =
}) })
tap.test('arrivals at Kassel Weigelstr.', async (t) => { tap.test('arrivals at Kassel Weigelstr.', async (t) => {
const arrivals = await client.arrivals(weigelstr, { const res = await client.arrivals(weigelstr, {
duration: 5, when duration: 5, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: weigelstr, id: weigelstr,
}) })

View file

@ -251,13 +251,13 @@ tap.test('departures at Wien Leibenfrostgasse', async (t) => {
'904030' // stop "Wien Leibenfrostgasse (Ziegelofengasse)" '904030' // stop "Wien Leibenfrostgasse (Ziegelofengasse)"
] ]
const deps = await client.departures(wienLeibenfrostgasse, { const res = await client.departures(wienLeibenfrostgasse, {
duration: 15, when, duration: 15, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures: deps, res,
validate, validate,
ids, ids,
}) })
@ -265,7 +265,7 @@ tap.test('departures at Wien Leibenfrostgasse', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: salzburgHbf, id: salzburgHbf,
name: 'Salzburg Hbf', name: 'Salzburg Hbf',
@ -276,7 +276,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })

View file

@ -118,13 +118,13 @@ tap.test('trip', async (t) => {
}) })
tap.test('departures at Næstved.', async (t) => { tap.test('departures at Næstved.', async (t) => {
const departures = await client.departures(næstved, { const res = await client.departures(næstved, {
duration: 20, when, duration: 20, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
ids: [ ids: [
næstved, næstved,
@ -136,13 +136,13 @@ tap.test('departures at Næstved.', async (t) => {
}) })
tap.test('arrivals at Næstved.', async (t) => { tap.test('arrivals at Næstved.', async (t) => {
const arrivals = await client.arrivals(næstved, { const res = await client.arrivals(næstved, {
duration: 20, when duration: 20, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
ids: [ ids: [
næstved, næstved,

View file

@ -66,13 +66,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('arrivals at Wiesbaden Hbf', async (t) => { tap.test('arrivals at Wiesbaden Hbf', async (t) => {
const arrivals = await client.arrivals(wiesbadenHbf, { const res = await client.arrivals(wiesbadenHbf, {
duration: 10, when duration: 10, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: wiesbadenHbf, id: wiesbadenHbf,
}) })

View file

@ -81,13 +81,13 @@ tap.test('refreshJourney', async (t) => {
}) })
tap.test('arrivals at Platz der Jugend', async (t) => { tap.test('arrivals at Platz der Jugend', async (t) => {
const arrivals = await client.arrivals(sternwarte, { const res = await client.arrivals(sternwarte, {
duration: 30, when duration: 30, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
ids: [ ids: [
sternwarte, sternwarte,

View file

@ -172,13 +172,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures', async (t) => { tap.test('departures', async (t) => {
const departures = await client.departures(saarbrueckenUhlandstr, { const res = await client.departures(saarbrueckenUhlandstr, {
duration: 5, when duration: 5, when
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: saarbrueckenUhlandstr, id: saarbrueckenUhlandstr,
}) })
@ -186,9 +186,9 @@ tap.test('departures', async (t) => {
}) })
tap.test('departures with stop object', async (t) => { tap.test('departures with stop object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'stop', type: 'stop',
id: '8000323', id: saarbrueckenHbf,
name: 'Saarbrücken Hbf', name: 'Saarbrücken Hbf',
location: { location: {
type: 'location', type: 'location',
@ -197,7 +197,7 @@ tap.test('departures with stop object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })

View file

@ -178,13 +178,13 @@ tap.test('trip details', async (t) => {
tap.test('departures at Dietlindenstraße', async (t) => { tap.test('departures at Dietlindenstraße', async (t) => {
const dietlindenstr = '624391' const dietlindenstr = '624391'
const departures = await client.departures(dietlindenstr, { const res = await client.departures(dietlindenstr, {
duration: 10, when, duration: 10, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: dietlindenstr id: dietlindenstr
}) })
@ -192,7 +192,7 @@ tap.test('departures at Dietlindenstraße', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: mittersendling, id: mittersendling,
name: 'Mittersendling', name: 'Mittersendling',
@ -203,18 +203,18 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
tap.test('arrivals at Karl-Theodor-Straße', async (t) => { tap.test('arrivals at Karl-Theodor-Straße', async (t) => {
const arrivals = await client.arrivals(karlTheodorStr, { const res = await client.arrivals(karlTheodorStr, {
duration: 10, when, duration: 10, when,
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: karlTheodorStr id: karlTheodorStr
}) })

View file

@ -71,13 +71,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('arrivals at Bruxelles Midi', async (t) => { tap.test('arrivals at Bruxelles Midi', async (t) => {
const arrivals = await client.arrivals(bruxellesMidi, { const res = await client.arrivals(bruxellesMidi, {
duration: 10, when duration: 10, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: bruxellesMidi, id: bruxellesMidi,
}) })

View file

@ -73,13 +73,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('arrivals at Volksgarten', async (t) => { tap.test('arrivals at Volksgarten', async (t) => {
const arrivals = await client.arrivals(volksgarten, { const res = await client.arrivals(volksgarten, {
duration: 10, when duration: 10, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: volksgarten, id: volksgarten,
}) })

View file

@ -285,13 +285,13 @@ tap.test('journeys: via works with detour', async (t) => {
// todo: without detour test // todo: without detour test
tap.test('departures', async (t) => { tap.test('departures', async (t) => {
const departures = await client.departures(spichernstr, { const res = await client.departures(spichernstr, {
duration: 5, when, duration: 5, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: spichernstr id: spichernstr
}) })
@ -299,7 +299,7 @@ tap.test('departures', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: spichernstr, id: spichernstr,
name: 'U Spichernstr', name: 'U Spichernstr',
@ -310,7 +310,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })
@ -335,13 +335,13 @@ tap.test('departures at 7-digit station', async (t) => {
}) })
tap.test('arrivals', async (t) => { tap.test('arrivals', async (t) => {
const arrivals = await client.arrivals(spichernstr, { const res = await client.arrivals(spichernstr, {
duration: 5, when, duration: 5, when,
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: spichernstr id: spichernstr
}) })

View file

@ -66,13 +66,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('arrivals at Bremen Humboldtstr.', async (t) => { tap.test('arrivals at Bremen Humboldtstr.', async (t) => {
const arrivals = await client.arrivals(bremenHumboldtstr, { const res = await client.arrivals(bremenHumboldtstr, {
duration: 10, when duration: 10, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: bremenHumboldtstr, id: bremenHumboldtstr,
}) })

View file

@ -145,13 +145,13 @@ tap.test('trip details', async (t) => {
}) })
tap.test('departures at Meckesheim', async (t) => { tap.test('departures at Meckesheim', async (t) => {
const departures = await client.departures(meckesheim, { const res = await client.departures(meckesheim, {
duration: 3 * 60, when, duration: 3 * 60, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: meckesheim id: meckesheim
}) })
@ -173,13 +173,13 @@ tap.test('departures at Meckesheim in direction of Reilsheim', async (t) => {
}) })
tap.test('arrivals at Meckesheim', async (t) => { tap.test('arrivals at Meckesheim', async (t) => {
const arrivals = await client.arrivals(meckesheim, { const res = await client.arrivals(meckesheim, {
duration: 3 * 60, when duration: 3 * 60, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: meckesheim id: meckesheim
}) })

View file

@ -101,13 +101,13 @@ tap.test('trip', async (t) => {
}) })
tap.test('departures at Kornmarkt.', async (t) => { tap.test('departures at Kornmarkt.', async (t) => {
const departures = await client.departures(kornmarkt, { const res = await client.departures(kornmarkt, {
duration: 20, when duration: 20, when
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
id: kornmarkt id: kornmarkt
}) })
@ -115,13 +115,13 @@ tap.test('departures at Kornmarkt.', async (t) => {
}) })
tap.test('arrivals at Kornmarkt.', async (t) => { tap.test('arrivals at Kornmarkt.', async (t) => {
const arrivals = await client.arrivals(kornmarkt, { const res = await client.arrivals(kornmarkt, {
duration: 20, when duration: 20, when
}) })
await testArrivals({ await testArrivals({
test: t, test: t,
arrivals, res,
validate, validate,
id: kornmarkt id: kornmarkt
}) })
@ -129,7 +129,7 @@ tap.test('arrivals at Kornmarkt.', async (t) => {
}) })
tap.test('departures with station object', async (t) => { tap.test('departures with station object', async (t) => {
const deps = await client.departures({ const res = await client.departures({
type: 'station', type: 'station',
id: kornmarkt, id: kornmarkt,
name: 'Kornmarkt', name: 'Kornmarkt',
@ -140,7 +140,7 @@ tap.test('departures with station object', async (t) => {
} }
}, {when}) }, {when})
validate(t, deps, 'departures', 'departures') validate(t, res, 'departuresResponse', 'res')
t.end() t.end()
}) })

View file

@ -79,13 +79,13 @@ tap.test('trip details', async (t) => {
tap.test('departures at ETH/Universitätsspital', async (t) => { // todo tap.test('departures at ETH/Universitätsspital', async (t) => { // todo
const polyterrasseETH = '8503500' const polyterrasseETH = '8503500'
const departures = await client.departures(ethUniversitätsspital, { const res = await client.departures(ethUniversitätsspital, {
duration: 5, when, duration: 5, when,
}) })
await testDepartures({ await testDepartures({
test: t, test: t,
departures, res,
validate, validate,
ids: [ethUniversitätsspital, polyterrasseETH], ids: [ethUniversitätsspital, polyterrasseETH],
}) })

View file

@ -42,9 +42,16 @@ tap.test('withRetrying works', (t) => {
}) })
const client = createClient(profile, userAgent) const client = createClient(profile, userAgent)
t.plan(1 + 4) t.plan(2 + 4)
client.departures(spichernstr, {duration: 1}) client.departures(spichernstr, {duration: 1})
.then(deps => t.same(deps, [], 'resolved with invalid value')) .then((res) => {
const {
departures: deps,
realtimeDataUpdatedAt,
} = res
t.same(deps, [], 'resolved with invalid value')
t.equal(realtimeDataUpdatedAt, null, 'resolved with invalid value')
})
.catch(t.ifError) .catch(t.ifError)
setTimeout(() => t.equal(calls, 1), 50) // buffer setTimeout(() => t.equal(calls, 1), 50) // buffer