'use strict' const validateFptf = require('validate-fptf') const isRoughlyEqual = require('is-roughly-equal') const {DateTime} = require('luxon') const isValidWGS84 = require('is-coordinates') const validateFptfWith = (t, item, allowedTypes, name) => { try { validateFptf.recurse(allowedTypes, item, name) } catch (err) { t.ifError(err) } } const assertValidStation = (t, s, coordsOptional = false) => { validateFptfWith(t, s, ['station'], 'station') if (!coordsOptional || (s.location !== null && s.location !== undefined)) { t.ok(s.location) assertValidLocation(t, s.location, coordsOptional) } } const assertValidPoi = (t, p) => { assertValidLocation(t, p, true) t.equal(typeof p.id, 'string') t.equal(typeof p.name, 'string') if (p.address !== null && p.address !== undefined) { t.equal(typeof p.address, 'string') t.ok(p.address) } } const assertValidAddress = (t, a) => { assertValidLocation(t, a, true) t.equal(typeof a.address, 'string') } const assertValidLocation = (t, l, coordsOptional = false) => { t.equal(l.type, 'location') if (l.name !== null && l.name !== undefined) { t.equal(typeof l.name, 'string') t.ok(l.name) } if (l.address !== null && l.address !== undefined) { t.equal(typeof l.address, 'string') t.ok(l.address) } const hasLatitude = l.latitude !== null && l.latitude !== undefined const hasLongitude = l.longitude !== null && l.longitude !== undefined if (!coordsOptional && hasLatitude) t.equal(typeof l.latitude, 'number') if (!coordsOptional && hasLongitude) t.equal(typeof l.longitude, 'number') if ((hasLongitude && !hasLatitude) || (hasLatitude && !hasLongitude)) { t.fail('should have both .latitude and .longitude') } if (hasLatitude && hasLongitude) isValidWGS84([l.longitude, l.latitude]) if (!coordsOptional && l.altitude !== null && l.altitude !== undefined) { t.equal(typeof l.altitude, 'number') } } const validLineModes = [ 'train', 'bus', 'watercraft', 'taxi', 'gondola', 'aircraft', 'car', 'bicycle', 'walking' ] const assertValidLine = (t, l) => { validateFptfWith(t, l, ['line'], 'line') } const isValidDateTime = (w) => { return !Number.isNaN(+new Date(w)) } const assertValidStopover = (t, s, coordsOptional = false) => { if ('arrival' in s) t.ok(isValidDateTime(s.arrival)) if ('departure' in s) t.ok(isValidDateTime(s.departure)) if (s.arrivalDelay !== null && s.arrivalDelay !== undefined) { t.equal(typeof s.arrivalDelay, 'number') } if (s.departureDelay !== null && s.departureDelay !== undefined) { t.equal(typeof s.departureDelay, 'number') } if (!('arrival' in s) && !('departure' in s)) { t.fail('stopover doesn\'t contain arrival or departure') } t.ok(s.station) assertValidStation(t, s.station, coordsOptional) } const hour = 60 * 60 * 1000 const week = 7 * 24 * hour // next Monday 10 am const createWhen = (timezone, locale) => { return DateTime.fromMillis(Date.now(), { zone: timezone, locale, }).startOf('week').plus({weeks: 1, hours: 10}).toJSDate() } const isValidWhen = (actual, expected) => { const ts = +new Date(actual) if (Number.isNaN(ts)) return false return isRoughlyEqual(12 * hour, +expected, ts) } const assertValidWhen = (t, actual, expected) => { t.ok(isValidWhen(actual, expected), 'invalid when') } const assertValidTicket = (t, ti) => { t.strictEqual(typeof ti.name, 'string') t.ok(ti.name.length > 0) if (ti.price !== null) { t.strictEqual(typeof ti.price, 'number') t.ok(ti.price > 0) } if (ti.amount !== null) { t.strictEqual(typeof ti.amount, 'number') t.ok(ti.amount > 0) } if ('bike' in ti) t.strictEqual(typeof ti.bike, 'boolean') if ('shortTrip' in ti) t.strictEqual(typeof ti.shortTrip, 'boolean') if ('group' in ti) t.strictEqual(typeof ti.group, 'boolean') if ('fullDay' in ti) t.strictEqual(typeof ti.fullDay, 'boolean') if (ti.tariff !== null) { t.strictEqual(typeof ti.tariff, 'string') t.ok(ti.tariff.length > 0) } if (ti.coverage !== null) { t.strictEqual(typeof ti.coverage, 'string') t.ok(ti.coverage.length > 0) } if (ti.variant !== null) { t.strictEqual(typeof ti.variant, 'string') t.ok(ti.variant.length > 0) } } module.exports = { assertValidStation, assertValidPoi, assertValidAddress, assertValidLocation, assertValidLine, isValidDateTime, assertValidStopover, hour, createWhen, isValidWhen, assertValidWhen, assertValidTicket }