diff --git a/lib/validate-profile.js b/lib/validate-profile.js index cfa8a840..19465c3f 100644 --- a/lib/validate-profile.js +++ b/lib/validate-profile.js @@ -7,7 +7,7 @@ const types = { transformReqBody: 'function', transformJourneysQuery: 'function', - products: 'object', + products: 'array', parseDateTime: 'function', parseDeparture: 'function', @@ -36,7 +36,11 @@ const types = { const validateProfile = (profile) => { for (let key of Object.keys(types)) { const type = types[key] - if (type !== typeof profile[key]) { + if (type === 'array') { + if (!Array.isArray(profile[key])) { + throw new Error(`profile.${key} must be an array.`) + } + } else if (type !== typeof profile[key]) { throw new Error(`profile.${key} must be a ${type}.`) } if (type === 'object' && profile[key] === null) { diff --git a/p/db/index.js b/p/db/index.js index a5973581..d8cc5e6f 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -112,7 +112,8 @@ const defaultProducts = { national: true, nationalExp: true, regional: true, - regionalExp: true + regionalExp: true, + taxi: false } const formatProducts = (products) => { products = Object.assign(Object.create(null), defaultProducts, products) @@ -140,7 +141,7 @@ const dbProfile = { // todo: parseLocation parseLine: createParseLine, - parseProducts: createParseBitmask(modes.bitmasks), + parseProducts: createParseBitmask(modes.allProducts, defaultProducts), parseJourney: createParseJourney, formatStation, diff --git a/p/insa/example.js b/p/insa/example.js new file mode 100644 index 00000000..054ae1f3 --- /dev/null +++ b/p/insa/example.js @@ -0,0 +1,29 @@ +'use strict' + +const createClient = require('../..') +const insaProfile = require('.') + +const client = createClient(insaProfile) + +// from Magdeburg-Neustadt to Magdeburg-Buckau +client.journeys('008010226', '008013456', {results: 1}) +// client.departures('008010226', { duration: 5 }) +// client.locations('Magdeburg Hbf', {results: 2}) +// client.locations('Kunstmuseum Kloster Unser Lieben Frauen Magdeburg', {results: 2}) +// client.location('008010226') // Magdeburg-Neustadt +// client.nearby({ +// type: 'location', +// latitude: 52.148842, +// longitude: 11.641705 +// }, {distance: 200}) +// client.radar(52.148364, 11.600826, 52.108486, 11.651451, {results: 10}) + +// .then(([journey]) => { +// const leg = journey.legs[0] +// return client.journeyLeg(leg.id, leg.line.name) +// }) + +.then(data => { + console.log(require('util').inspect(data, { depth: null })) +}) +.catch(console.error) diff --git a/p/insa/index.js b/p/insa/index.js new file mode 100644 index 00000000..8b7bea1b --- /dev/null +++ b/p/insa/index.js @@ -0,0 +1,82 @@ +'use strict' + +const _createParseLine = require('../../parse/line') +const products = require('./products') +const createParseBitmask = require('../../parse/products-bitmask') +const createFormatBitmask = require('../../format/products-bitmask') + +const defaultProducts = { + nationalExp: true, + national: true, + regional: true, + suburban: true, + bus: true, + tram: true, + tourismTrain: true, +} + + +const transformReqBody = (body) => { + body.client = { + type: 'IPH', + id: 'NASA', + v: '4000200', + name: 'nasaPROD', + os: 'iPhone OS 11.2.5' + } + body.ver = '1.11' + body.auth = {aid: "nasa-apps"} + body.lang = 'en' // todo: `de`? + + return body +} + +const createParseLine = (profile, operators) => { + const parseLine = _createParseLine(profile, operators) + + const parseLineWithMode = (l) => { + const res = parseLine(l) + + res.mode = res.product = null + if ('class' in res) { + const data = products.bitmasks[parseInt(res.class)] + if (data) { + res.mode = data.mode + res.product = data.product + } + } + + return res + } + return parseLineWithMode +} + +const formatProducts = (products) => { + products = Object.assign(Object.create(null), defaultProducts, products) + return { + type: 'PROD', + mode: 'INC', + value: formatBitmask(products) + '' + } +} + +const formatBitmask = createFormatBitmask(products) + + +const insaProfile = { + locale: 'de-DE', + timezone: 'Europe/Berlin', + endpoint: 'http://reiseauskunft.insa.de/bin/mgate.exe', + transformReqBody, + + products: products.allProducts, + parseProducts: createParseBitmask(products.allProducts, defaultProducts), + formatProducts, + + parseLine: createParseLine, + + journeyLeg: true, + radar: true +} + +module.exports = insaProfile; diff --git a/p/insa/products.js b/p/insa/products.js new file mode 100644 index 00000000..d6b343e5 --- /dev/null +++ b/p/insa/products.js @@ -0,0 +1,82 @@ +'use strict' + +// TODO Jannis R.: DRY +const p = { + nationalExp: { + bitmask: 1, + name: 'InterCityExpress', + short: 'ICE', + mode: 'train', + product: 'nationalExp' + }, + national: { + bitmask: 2, + name: 'InterCity & EuroCity', + short: 'IC/EC', + mode: 'train', + product: 'national' + }, + regional: { + bitmask: 8, + name: 'RegionalExpress & RegionalBahn', + short: 'RE/RB', + mode: 'train', + product: 'regional' + }, + suburban: { + bitmask: 16, + name: 'S-Bahn', + short: 'S', + mode: 'train', + product: 'suburban' + }, + tram: { + bitmask: 32, + name: 'Tram', + short: 'T', + mode: 'train', + product: 'tram' + }, + bus: { + bitmask: 64+128, + name: 'Bus', + short: 'B', + mode: 'bus', + product: 'bus' + }, + tourismTrain: { + bitmask: 256, + name: 'Tourism Train', + short: 'TT', + mode: 'train', + product: 'tourismTrain' + }, + unknown: { + bitmask: 0, + name: 'unknown', + short: '?', + product: 'unknown' + } +} + +p.bitmasks = [] +p.bitmasks[1] = p.nationalExp +p.bitmasks[2] = p.national +p.bitmasks[8] = p.regional +p.bitmasks[16] = p.suburban +p.bitmasks[32] = p.tram +p.bitmasks[64] = p.bus +p.bitmasks[128] = p.bus +p.bitmasks[256] = p.tourismTrain + +p.allProducts = [ + p.nationalExp, + p.national, + p.regional, + p.suburban, + p.tram, + p.bus, + p.tourismTrain +] + +module.exports = p diff --git a/p/insa/readme.md b/p/insa/readme.md new file mode 100644 index 00000000..4918b2b4 --- /dev/null +++ b/p/insa/readme.md @@ -0,0 +1,18 @@ +# INSA profile for `hafas-client` + +The [Nahverkehr Sachsen-Anhalt (NASA)](https://de.wikipedia.org/wiki/Nahverkehrsservice_Sachsen-Anhalt) offers [Informationssystem Nahverkehr Sachsen-Anhalt (INSA)](https://insa.de) to distribute their public transport data. + +## Usage + +```js +const createClient = require('hafas-client') +const insaProfile = require('hafas-client/p/insa') + +// create a client with INSA profile +const client = createClient(insaProfile) +``` + + +## Customisations + +- parses *INSA*-specific products (such as *Tourism Train*) diff --git a/p/oebb/index.js b/p/oebb/index.js index 13a61284..5196ab49 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -113,7 +113,7 @@ const oebbProfile = { products: products.allProducts, - parseProducts: createParseBitmask(products.bitmasks), + parseProducts: createParseBitmask(products.allProducts, defaultProducts), parseLine: createParseLine, parseLocation, parseMovement: createParseMovement, diff --git a/p/vbb/index.js b/p/vbb/index.js index 307ba0f4..3f9f9ecd 100644 --- a/p/vbb/index.js +++ b/p/vbb/index.js @@ -181,7 +181,7 @@ const vbbProfile = { parseStationName: shorten, parseLocation, parseLine: createParseLine, - parseProducts: createParseBitmask(modes.bitmasks), + parseProducts: createParseBitmask(modes.allProducts, defaultProducts), parseJourney: createParseJourney, parseDeparture: createParseDeparture, parseStopover: createParseStopover, diff --git a/parse/location.js b/parse/location.js index c0de893d..e6689e6b 100644 --- a/parse/location.js +++ b/parse/location.js @@ -20,7 +20,7 @@ const parseLocation = (profile, l, lines) => { type: 'station', id: l.extId, name: l.name, - location: res + location: 'number' === typeof res.latitude ? res : null } if ('pCls' in l) station.products = profile.parseProducts(l.pCls) diff --git a/parse/products-bitmask.js b/parse/products-bitmask.js index 04f9b89a..5dc5e8bc 100644 --- a/parse/products-bitmask.js +++ b/parse/products-bitmask.js @@ -1,14 +1,29 @@ 'use strict' -const createParseBitmask = (bitmasks) => { +const createParseBitmask = (allProducts, defaultProducts) => { + allProducts = allProducts.sort((p1, p2) => p2.bitmask - p1.bitmask) // desc + if (allProducts.length === 0) throw new Error('allProducts is empty.') + for (let product of allProducts) { + if ('string' !== typeof product.product) { + throw new Error('allProducts[].product must be a string.') + } + if ('number' !== typeof product.bitmask) { + throw new Error(product.product + '.bitmask must be a number.') + } + } + const parseBitmask = (bitmask) => { - const products = {} - let i = 1 - do { - products[bitmasks[i].product] = products[bitmasks[i].product] || !!(bitmask & i) - i *= 2 - } while (bitmasks[i] && bitmasks[i].product) - return products + const res = Object.assign({}, defaultProducts) + + for (let product of allProducts) { + if (bitmask === 0) break + if ((product.bitmask & bitmask) > 0) { + res[product.product] = true + bitmask -= product.bitmask + } + } + + return res } return parseBitmask } diff --git a/readme.md b/readme.md index a0f71162..09eab5fe 100644 --- a/readme.md +++ b/readme.md @@ -7,6 +7,7 @@ HAFAS endpoint | wrapper library? | docs | example code | source code [Deutsche Bahn](https://en.wikipedia.org/wiki/Deutsche_Bahn) | [`db-hafas`](https://github.com/derhuerst/db-hafas), which has additional features | [docs](p/db/readme.md) | [example code](p/db/example.js) | [src](p/db/index.js) [Berlin & Brandenburg public transport](https://en.wikipedia.org/wiki/Verkehrsverbund_Berlin-Brandenburg) | [`vbb-hafas`](https://github.com/derhuerst/vbb-hafas), which has additional features | [docs](p/vbb/readme.md) | [example code](p/vbb/example.js) | [src](p/vbb/index.js) [Österreichische Bundesbahnen (ÖBB)](https://en.wikipedia.org/wiki/Austrian_Federal_Railways) | – | [docs](p/oebb/readme.md) | [example code](p/oebb/example.js) | [src](p/oebb/index.js) +[Nahverkehr Sachsen-Anhalt (NASA)](https://de.wikipedia.org/wiki/Nahverkehrsservice_Sachsen-Anhalt)/[INSA](https://insa.de) | – | [docs](p/insa/readme.md) | [example code](p/insa/example.js) | [src](p/insa/index.js) [![npm version](https://img.shields.io/npm/v/hafas-client.svg)](https://www.npmjs.com/package/hafas-client) [![build status](https://img.shields.io/travis/derhuerst/hafas-client.svg)](https://travis-ci.org/derhuerst/hafas-client) diff --git a/test/db.js b/test/db.js index f38d2ddd..ffaca334 100644 --- a/test/db.js +++ b/test/db.js @@ -8,7 +8,7 @@ const isRoughlyEqual = require('is-roughly-equal') const co = require('./co') const createClient = require('..') const dbProfile = require('../p/db') -const modes = require('../p/db/modes') +const {allProducts} = require('../p/db/modes') const { assertValidStation, assertValidPoi, @@ -69,11 +69,12 @@ const assertIsJungfernheide = (t, s) => { t.ok(isRoughlyEqual(s.location.longitude, 13.299424, .0005)) } -// todo: this doesnt seem to work // todo: DRY with assertValidStationProducts +// todo: DRY with other tests const assertValidProducts = (t, p) => { - for (let k of Object.keys(modes)) { - t.ok('boolean', typeof modes[k], 'mode ' + k + ' must be a boolean') + for (let product of allProducts) { + product = product.product // wat + t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean') } } diff --git a/test/index.js b/test/index.js index b278e8d2..8fbdc852 100644 --- a/test/index.js +++ b/test/index.js @@ -3,4 +3,5 @@ require('./db') require('./vbb') require('./oebb') +require('./insa') require('./throttle') diff --git a/test/insa.js b/test/insa.js new file mode 100644 index 00000000..f22581d6 --- /dev/null +++ b/test/insa.js @@ -0,0 +1,365 @@ +'use strict' + +const tapePromise = require('tape-promise').default +const tape = require('tape') +const isRoughlyEqual = require('is-roughly-equal') +const validateFptf = require('validate-fptf') + +const co = require('./co') +const createClient = require('..') +const insaProfile = require('../p/insa') +const {allProducts} = require('../p/insa/products') +const { + assertValidStation, + assertValidPoi, + assertValidAddress, + assertValidLocation, + assertValidLine, + assertValidStopover, + hour, + createWhen, + assertValidWhen +} = require('./util.js') + +const when = createWhen('Europe/Berlin', 'de-DE') + +const assertValidStationProducts = (t, p) => { + t.ok(p) + t.equal(typeof p.nationalExp, 'boolean') + t.equal(typeof p.national, 'boolean') + t.equal(typeof p.regional, 'boolean') + t.equal(typeof p.suburban, 'boolean') + t.equal(typeof p.tram, 'boolean') + t.equal(typeof p.bus, 'boolean') + t.equal(typeof p.tourismTrain, 'boolean') +} + +const isMagdeburgHbf = s => { + return ( + s.type === 'station' && + (s.id === '8010224' || s.id === '008010224') && + s.name === 'Magdeburg Hbf' && + s.location && + isRoughlyEqual(s.location.latitude, 52.130352, 0.001) && + isRoughlyEqual(s.location.longitude, 11.626891, 0.001) + ) +} + +const assertIsMagdeburgHbf = (t, s) => { + t.equal(s.type, 'station') + t.ok(s.id === '8010224' || s.id === '008010224', 'id should be 8010224') + t.equal(s.name, 'Magdeburg Hbf') + t.ok(s.location) + t.ok(isRoughlyEqual(s.location.latitude, 52.130352, 0.001)) + t.ok(isRoughlyEqual(s.location.longitude, 11.626891, 0.001)) +} + +// todo: DRY with assertValidStationProducts +// todo: DRY with other tests +const assertValidProducts = (t, p) => { + for (let product of allProducts) { + product = product.product // wat + t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean') + } +} + +const test = tapePromise(tape) +const client = createClient(insaProfile) + +test('Magdeburg Hbf to Magdeburg-Buckau', co(function*(t) { + const magdeburgHbf = '8010224' + const magdeburgBuckau = '8013456' + const journeys = yield client.journeys(magdeburgHbf, magdeburgBuckau, { + when, + passedStations: true + }) + + t.ok(Array.isArray(journeys)) + t.ok(journeys.length > 0, 'no journeys') + for (let journey of journeys) { + assertValidStation(t, journey.origin) + assertValidStationProducts(t, journey.origin.products) + if (journey.origin.products) { + assertValidProducts(t, journey.origin.products) + } + assertValidWhen(t, journey.departure, when) + + assertValidStation(t, journey.destination) + assertValidStationProducts(t, journey.origin.products) + if (journey.destination.products) { + assertValidProducts(t, journey.destination.products) + } + assertValidWhen(t, journey.arrival, when) + + t.ok(Array.isArray(journey.legs)) + t.ok(journey.legs.length > 0, 'no legs') + const leg = journey.legs[0] + + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + assertValidWhen(t, leg.departure, when) + t.equal(typeof leg.departurePlatform, 'string') + + assertValidStation(t, leg.destination) + assertValidStationProducts(t, leg.origin.products) + assertValidWhen(t, leg.arrival, when) + t.equal(typeof leg.arrivalPlatform, 'string') + + assertValidLine(t, leg.line) + + t.ok(Array.isArray(leg.passed)) + for (let stopover of leg.passed) assertValidStopover(t, stopover) + } + + t.end() +})) + +test('Magdeburg Hbf to 39104 Magdeburg, Sternstr. 10', co(function*(t) { + const magdeburgHbf = '8010224' + const sternStr = { + type: 'location', + latitude: 52.118414, + longitude: 11.422332, + address: 'Magdeburg - Altenstadt, Sternstraße 10' + } + + const journeys = yield client.journeys(magdeburgHbf, sternStr, { + when + }) + + t.ok(Array.isArray(journeys)) + t.ok(journeys.length >= 1, 'no journeys') + const journey = journeys[0] + const firstLeg = journey.legs[0] + const lastLeg = journey.legs[journey.legs.length - 1] + + assertValidStation(t, firstLeg.origin) + assertValidStationProducts(t, firstLeg.origin.products) + if (firstLeg.origin.products) + assertValidProducts(t, firstLeg.origin.products) + assertValidWhen(t, firstLeg.departure, when) + assertValidWhen(t, firstLeg.arrival, when) + assertValidWhen(t, lastLeg.departure, when) + assertValidWhen(t, lastLeg.arrival, when) + + const d = lastLeg.destination + assertValidAddress(t, d) + t.equal(d.address, 'Magdeburg - Altenstadt, Sternstraße 10') + t.ok(isRoughlyEqual(0.0001, d.latitude, 52.118414)) + t.ok(isRoughlyEqual(0.0001, d.longitude, 11.422332)) + + t.end() +})) + +test('Kloster Unser Lieben Frauen to Magdeburg Hbf', co(function*(t) { + const kloster = { + type: 'location', + latitude: 52.127601, + longitude: 11.636437, + name: 'Magdeburg, Kloster Unser Lieben Frauen (Denkmal)', + id: '970012223' + } + const magdeburgHbf = '8010224' + const journeys = yield client.journeys(kloster, magdeburgHbf, { + when + }) + + t.ok(Array.isArray(journeys)) + t.ok(journeys.length >= 1, 'no journeys') + const journey = journeys[0] + const firstLeg = journey.legs[0] + const lastLeg = journey.legs[journey.legs.length - 1] + + const o = firstLeg.origin + assertValidPoi(t, o) + t.equal(o.name, 'Magdeburg, Kloster Unser Lieben Frauen (Denkmal)') + t.ok(isRoughlyEqual(0.0001, o.latitude, 52.127601)) + t.ok(isRoughlyEqual(0.0001, o.longitude, 11.636437)) + + assertValidWhen(t, firstLeg.departure, when) + assertValidWhen(t, firstLeg.arrival, when) + assertValidWhen(t, lastLeg.departure, when) + assertValidWhen(t, lastLeg.arrival, when) + + assertValidStation(t, lastLeg.destination) + assertValidStationProducts(t, lastLeg.destination.products) + if (lastLeg.destination.products) + assertValidProducts(t, lastLeg.destination.products) + + t.end() +})) + +test('Magdeburg-Buckau to Magdeburg-Neustadt with stopover at Magdeburg Hbf', co(function*(t) { + const magdeburgBuckau = '8013456' + const magdeburgNeustadt = '8010226' + const magdeburgHbf = '8010224' + const [journey] = yield client.journeys(magdeburgBuckau, magdeburgNeustadt, { + via: magdeburgHbf, + results: 1, + when + }) + + const i1 = journey.legs.findIndex(leg => leg.destination.id === magdeburgHbf) + t.ok(i1 >= 0, 'no leg with Magdeburg Hbf as destination') + + const i2 = journey.legs.findIndex(leg => leg.origin.id === magdeburgHbf) + t.ok(i2 >= 0, 'no leg with Magdeburg Hbf as origin') + t.ok(i2 > i1, 'leg with Magdeburg Hbf as origin must be after leg to it') + + t.end() +})) + +test('departures at Magdeburg Hbf', co(function*(t) { + const magdeburgHbf = '8010224' + const deps = yield client.departures(magdeburgHbf, { + duration: 5, + when + }) + + t.ok(Array.isArray(deps)) + for (let dep of deps) { + assertValidStation(t, dep.station) + assertValidStationProducts(t, dep.station.products) + if (dep.station.products) { + assertValidProducts(t, dep.station.products) + } + assertValidWhen(t, dep.when, when) + } + + t.end() +})) + +test('nearby Magdeburg Hbf', co(function*(t) { + const magdeburgHbfPosition = { + type: 'location', + latitude: 52.130352, + longitude: 11.626891 + } + const nearby = yield client.nearby(magdeburgHbfPosition, { + results: 2, + distance: 400 + }) + + t.ok(Array.isArray(nearby)) + t.equal(nearby.length, 2) + + assertIsMagdeburgHbf(t, nearby[0]) + t.ok(nearby[0].distance >= 0) + t.ok(nearby[0].distance <= 100) + + for (let n of nearby) { + if (n.type === 'station') assertValidStation(t, n) + else assertValidLocation(t, n) + } + + t.end() +})) + +test('journey leg details', co(function* (t) { + const magdeburgHbf = '8010224' + const magdeburgBuckau = '8013456' + const [journey] = yield client.journeys(magdeburgHbf, magdeburgBuckau, { + results: 1, when + }) + + const p = journey.legs[0] + t.ok(p, 'missing legs[0]') + t.ok(p.id, 'missing legs[0].id') + t.ok(p.line, 'missing legs[0].line') + t.ok(p.line.name, 'missing legs[0].line.name') + const leg = yield client.journeyLeg(p.id, p.line.name, {when}) + + t.equal(typeof leg.id, 'string') + t.ok(leg.id) + + assertValidLine(t, leg.line) + + t.equal(typeof leg.direction, 'string') + t.ok(leg.direction) + + t.ok(Array.isArray(leg.passed)) + for (let passed of leg.passed) assertValidStopover(t, passed) + + t.end() +})) + +test('locations named Magdeburg', co(function*(t) { + const locations = yield client.locations('Magdeburg', { + results: 10 + }) + + t.ok(Array.isArray(locations)) + t.ok(locations.length > 0) + t.ok(locations.length <= 10) + + for (let l of locations) { + if (l.type === 'station') assertValidStation(t, l) + else assertValidLocation(t, l) + } + t.ok(locations.some(isMagdeburgHbf)) + + t.end() +})) + +test('location', co(function*(t) { + const magdeburgBuckau = '8013456' + const loc = yield client.location(magdeburgBuckau) + + assertValidStation(t, loc) + t.equal(loc.id, magdeburgBuckau) + + t.end() +})) + +test('radar', co(function* (t) { + const north = 52.148364 + const west = 11.600826 + const south = 52.108486 + const east = 11.651451 + const vehicles = yield client.radar(north, west, south, east, { + duration: 5 * 60, when, results: 10 + }) + + t.ok(Array.isArray(vehicles)) + t.ok(vehicles.length > 0) + for (let v of vehicles) { + assertValidLine(t, v.line) + + t.equal(typeof v.location.latitude, 'number') + t.ok(v.location.latitude <= 57, 'vehicle is too far away') + t.ok(v.location.latitude >= 47, 'vehicle is too far away') + t.equal(typeof v.location.longitude, 'number') + t.ok(v.location.longitude >= 8, 'vehicle is too far away') + t.ok(v.location.longitude <= 14, 'vehicle is too far away') + + t.ok(Array.isArray(v.nextStops)) + for (let st of v.nextStops) { + assertValidStopover(t, st, true) + + if (st.arrival) { + t.equal(typeof st.arrival, 'string') + const arr = +new Date(st.arrival) + // note that this can be an ICE train + t.ok(isRoughlyEqual(14 * hour, +when, arr)) + } + if (st.departure) { + t.equal(typeof st.departure, 'string') + const dep = +new Date(st.departure) + // note that this can be an ICE train + t.ok(isRoughlyEqual(14 * hour, +when, dep)) + } + } + + t.ok(Array.isArray(v.frames)) + for (let f of v.frames) { + // see #28 + // todo: check if this works by now + assertValidStation(t, f.origin, true) + assertValidStationProducts(t, f.origin.products) + assertValidStation(t, f.destination, true) + assertValidStationProducts(t, f.destination.products) + t.equal(typeof f.t, 'number') + } + } + t.end() +})) diff --git a/test/oebb.js b/test/oebb.js index 178c58db..73d8c685 100644 --- a/test/oebb.js +++ b/test/oebb.js @@ -12,7 +12,7 @@ const validateLineWithoutMode = require('./validate-line-without-mode') const co = require('./co') const createClient = require('..') const oebbProfile = require('../p/oebb') -const products = require('../p/oebb/products') +const {allProducts} = require('../p/oebb/products') const { assertValidStation, assertValidPoi, @@ -73,11 +73,12 @@ const assertIsSalzburgHbf = (t, s) => { t.ok(isRoughlyEqual(s.location.longitude, 13.045604, .0005)) } -// todo: this doesnt seem to work // todo: DRY with assertValidStationProducts +// todo: DRY with other tests const assertValidProducts = (t, p) => { - for (let k of Object.keys(products)) { - t.ok('boolean', typeof products[k], 'mode ' + k + ' must be a boolean') + for (let product of allProducts) { + product = product.product // wat + t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean') } }