From cc74f6a85bd68752ffea141c889de3cdba73f61c Mon Sep 17 00:00:00 2001 From: Jannis R Date: Tue, 3 Sep 2019 15:35:12 +0200 Subject: [PATCH] tests for parse/* :white_check_mark: --- .travis.yml | 6 +++ package.json | 4 +- test/e2e/common.js | 36 -------------- test/index.js | 2 + test/parse/date-time.js | 50 ++++++++++++++++++++ test/parse/hint.js | 56 ++++++++++++++++++++++ test/parse/icon.js | 66 ++++++++++++++++++++++++++ test/parse/index.js | 10 ++++ test/parse/line.js | 54 +++++++++++++++++++++ test/parse/location.js | 101 ++++++++++++++++++++++++++++++++++++++++ test/parse/operator.js | 21 +++++++++ test/parse/warning.js | 63 +++++++++++++++++++++++++ test/parse/when.js | 38 +++++++++++++++ 13 files changed, 469 insertions(+), 38 deletions(-) create mode 100644 test/parse/date-time.js create mode 100644 test/parse/hint.js create mode 100644 test/parse/icon.js create mode 100644 test/parse/index.js create mode 100644 test/parse/line.js create mode 100644 test/parse/location.js create mode 100644 test/parse/operator.js create mode 100644 test/parse/warning.js create mode 100644 test/parse/when.js diff --git a/.travis.yml b/.travis.yml index 594a7057..917b8c66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,3 +5,9 @@ node_js: - 'lts/*' - '8' cache: npm +script: npm test +jobs: + include: + - name: e2e-test + script: npm run e2e-test + node_js: '8' diff --git a/package.json b/package.json index d605150a..d174e730 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ }, "scripts": { "e2e-test": "env NODE_ENV=dev node test/e2e/index.js | tap-spec", - "test": "npm run e2e-test", - "prepublishOnly": "npm test" + "test": "env NODE_ENV=dev node test/index.js | tap-spec", + "prepublishOnly": "npm test && npm run e2e-test" } } diff --git a/test/e2e/common.js b/test/e2e/common.js index 8af5243f..ca28371c 100644 --- a/test/e2e/common.js +++ b/test/e2e/common.js @@ -4,9 +4,7 @@ const test = require('tape') const createClient = require('../..') const vbbProfile = require('../../p/vbb') -const parseDateTime = require('../../parse/date-time') -// todo: use a mock profile const client = createClient(vbbProfile, 'public-transport/hafas-client:test') test('exposes the profile', (t) => { @@ -14,37 +12,3 @@ test('exposes the profile', (t) => { t.equal(client.profile.endpoint, vbbProfile.endpoint) t.end() }) - -test('parseDateTime: works', (t) => { - const profile = {timezone: 'Europe/Berlin', locale: 'de-DE'} - const whenStr = '2019-03-18T13:19:10+01:00' - const when = +new Date(whenStr) - - const assert = (args, expected) => { - const name = args.join(', ') - const actual = parseDateTime(profile, ...args) - t.equal(typeof actual, typeof expected, name) - t.equal(actual, expected, name) - } - - assert(['20190318', '131910', null, false], whenStr) - assert(['20190318', '131910', null, true], when) - - // manual timezone offset - assert(['20190318', '131910', 60, false], whenStr) - assert(['20190318', '131910', 60, true], when) - assert(['20190318', '131910', 120, false], '2019-03-18T13:19:10+02:00') - assert(['20190318', '131910', 120, true], +new Date('2019-03-18T13:19:10+02:00')) - - // day offset - assert(['20190318', '2131910', null, false], '2019-03-20T13:19:10+01:00') - assert(['20190318', '2131910', null, true], +new Date('2019-03-20T13:19:10+01:00')) - assert(['20190318', '02131910', null, false], '2019-03-20T13:19:10+01:00') - assert(['20190318', '02131910', null, true], +new Date('2019-03-20T13:19:10+01:00')) - - // manual timezone offset day offset - assert(['20190318', '02131910', 150, false], '2019-03-20T13:19:10+02:30') - assert(['20190318', '02131910', 150, true], +new Date('2019-03-20T13:19:10+02:30')) - - t.end() -}) diff --git a/test/index.js b/test/index.js index e480eedc..59e53375 100644 --- a/test/index.js +++ b/test/index.js @@ -1,5 +1,7 @@ 'use strict' +require('./parse') + require('./bvg-journey') require('./vbb-departures') require('./bvg-radar') diff --git a/test/parse/date-time.js b/test/parse/date-time.js new file mode 100644 index 00000000..e5fa181a --- /dev/null +++ b/test/parse/date-time.js @@ -0,0 +1,50 @@ +'use strict' + +const test = require('tape') +const parse = require('../../parse/date-time') + +const profile = { + timezone: 'Europe/Berlin', + locale: 'de-DE' +} + +test('date & time parsing uses profile.timezone', (t) => { + const iso = parse({ + ...profile, timezone: 'Europe/Moscow' + }, '20190819', '203000', undefined, false) + t.equal(iso, '2019-08-19T20:30:00+03:00') + t.end() +}) + +test('date & time parsing returns a timestamp', (t) => { + const iso = parse(profile, '20190819', '203000', undefined, false) + const ts = parse(profile, '20190819', '203000', undefined, true) + t.equal(ts, +new Date(iso)) + t.equal(ts, 1566239400 * 1000) + t.end() +}) + +test('date & time parsing uses tzOffset', (t) => { + const iso = parse(profile, '20190819', '203000', -120, false) + t.equal(iso, '2019-08-19T20:30:00-02:00') + t.end() +}) + +test('date & time parsing works with day "overflow"', (t) => { + const iso = parse(profile, '20190819', '02203000', undefined, false) + t.equal(iso, '2019-08-21T20:30:00+02:00') + t.end() +}) + +// #106 +test('date & time parsing works with day "overflow" & tzOffset', (t) => { + const iso = parse(profile, '20190819', '02203000', -120, false) + t.equal(iso, '2019-08-21T20:30:00-02:00') + t.end() +}) + +test('date & time parsing works with summer & winter time', (t) => { + const iso = parse(profile, '20190219', '203000', undefined, false) + t.equal(iso, '2019-02-19T20:30:00+01:00') + t.end() +}) diff --git a/test/parse/hint.js b/test/parse/hint.js new file mode 100644 index 00000000..3dff77c8 --- /dev/null +++ b/test/parse/hint.js @@ -0,0 +1,56 @@ +'use strict' + +const test = require('tape') +const parse = require('../../parse/hint') + +const profile = {} + +test('parses hints correctly', (t) => { + const input = { + type: 'A', + code: 'bf', + prio: 123, + txtN: 'some text' + } + const expected = { + type: 'hint', + code: 'bf', + text: 'some text' + } + + t.deepEqual(parse(profile, input), expected) + t.deepEqual(parse(profile, { + ...input, type: 'I' + }), expected) + + // alternative trip + t.deepEqual(parse(profile, { + ...input, type: 'L', jid: 'trip id' + }), { + ...expected, type: 'status', code: 'alternative-trip', tripId: 'trip id' + }) + + // type: M + t.deepEqual(parse(profile, { + ...input, type: 'M', txtS: 'some summary' + }), { + ...expected, type: 'status', summary: 'some summary' + }) + + // type: D + for (const type of ['D', 'U', 'R', 'N', 'Y']) { + t.deepEqual(parse(profile, {...input, type}), { + ...expected, type: 'status' + }) + } + + // .code via .icon + t.deepEqual(parse(profile, { + ...input, code: null, icon: {type: 'cancel'} + }), {...expected, code: 'cancelled'}) + + // invalid + t.equal(parse(profile, {...input, type: 'X'}), null) + + t.end() +}) diff --git a/test/parse/icon.js b/test/parse/icon.js new file mode 100644 index 00000000..940b2f97 --- /dev/null +++ b/test/parse/icon.js @@ -0,0 +1,66 @@ +'use strict' + +const test = require('tape') +const parse = require('../../parse/icon') + +test('parses icons correctly', (t) => { + const profile = {} + + const text = { + "res": "BVG", + "text": "Berliner Verkehrsbetriebe" + } + t.deepEqual(parse(profile, text), { + type: 'BVG', + title: 'Berliner Verkehrsbetriebe' + }) + + const txtS = { + "res": "PROD_BUS", + "txtS": "18" + } + t.deepEqual(parse(profile, txtS), { + type: 'PROD_BUS', + title: '18' + }) + + const txt = { + "res": "RBB", + "txt": "Regionalbus Braunschweig GmbH" + } + t.deepEqual(parse(profile, txt), { + type: 'RBB', + title: 'Regionalbus Braunschweig GmbH' + }) + + const noText = { + "res": "attr_bike_r" + } + t.deepEqual(parse(profile, noText), { + type: 'attr_bike_r', + title: null + }) + + const withColor = { + "res": "prod_sub_t", + "fg": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bg": { + "r": 0, + "g": 51, + "b": 153, + "a": 255 + } + } + t.deepEqual(parse(profile, withColor), { + type: 'prod_sub_t', + title: null, + fgColor: {r: 255, g: 255, b: 255, a: 255}, + bgColor: {r: 0, g: 51, b: 153, a: 255} + }) + t.end() +}) diff --git a/test/parse/index.js b/test/parse/index.js new file mode 100644 index 00000000..9bbf7e2a --- /dev/null +++ b/test/parse/index.js @@ -0,0 +1,10 @@ +'use strict' + +require('./date-time') +require('./icon') +require('./operator') +require('./location') +require('./when') +require('./line') +require('./hint') +require('./warning') diff --git a/test/parse/line.js b/test/parse/line.js new file mode 100644 index 00000000..1dcbe88c --- /dev/null +++ b/test/parse/line.js @@ -0,0 +1,54 @@ +'use strict' + +const test = require('tape') +const parser = require('../../parse/line') + +const profile = { + products: [ + {id: 'train', bitmasks: [1]}, + {id: 'ferry', bitmasks: [2]}, + {id: 'bus', bitmasks: [4, 8]} + ] +} +const opt = {} +const parse = parser(profile, opt, {}) + +test('parses lines correctly', (t) => { + const input = { + line: 'foo line', + prodCtx: { + lineId: 'Foo ', + num: 123 + } + } + const expected = { + type: 'line', + id: 'foo', + fahrtNr: 123, + name: 'foo line', + public: true + } + + t.deepEqual(parse(input), expected) + + t.deepEqual(parse({ + ...input, line: null, addName: input.line + }), expected) + t.deepEqual(parse({ + ...input, line: null, name: input.line + }), expected) + + // no prodCtx.lineId + t.deepEqual(parse({ + ...input, prodCtx: {...input.prodCtx, lineId: null} + }), { + ...expected, id: 'foo-line' + }) + // no prodCtx + t.deepEqual(parse({ + ...input, prodCtx: undefined + }), { + ...expected, id: 'foo-line', fahrtNr: null + }) + t.end() +}) diff --git a/test/parse/location.js b/test/parse/location.js new file mode 100644 index 00000000..8e9fa0af --- /dev/null +++ b/test/parse/location.js @@ -0,0 +1,101 @@ +'use strict' + +const test = require('tape') +const omit = require('lodash/omit') +const parse = require('../../parse/location') + +const profile = { + parseStationName: name => name.toLowerCase(), + parseProducts: bitmask => [bitmask] +} +const opt = { + linesOfStops: false +} + +test('parses an address correctly', (t) => { + const input = { + type: 'A', + name: 'Foo street 3', + lid: 'a=b@L=some%20id', + crd: {x: 13418027, y: 52515503} + } + + const address = parse(profile, opt, null, input) + t.deepEqual(address, { + type: 'location', + id: 'some id', + address: 'Foo street 3', + latitude: 52.515503, + longitude: 13.418027 + }) + + t.end() +}) + +test('parses a POI correctly', (t) => { + const input = { + type: 'P', + name: 'some POI', + lid: 'a=b@L=some%20id', + crd: {x: 13418027, y: 52515503} + } + + const poi = parse(profile, opt, null, input) + t.deepEqual(poi, { + type: 'location', + poi: true, + id: 'some id', + name: 'some POI', + latitude: 52.515503, + longitude: 13.418027 + }) + + const withExtId = parse(profile, opt, null, {...input, extId: 'some ext id'}) + t.equal(withExtId.id, 'some ext id') + + const withLeadingZero = parse(profile, opt, null, {...input, extId: '00some ext id'}) + t.equal(withLeadingZero.id, 'some ext id') + + t.end() +}) + +test('parses a stop correctly', (t) => { + const input = { + type: 'S', + name: 'Foo bus stop', + lid: 'a=b@L=foo%20stop', + crd: {x: 13418027, y: 52515503}, + pCls: 123 + } + + const stop = parse(profile, opt, null, input) + t.deepEqual(stop, { + type: 'stop', + id: 'foo stop', + name: 'foo bus stop', // lower-cased! + location: { + type: 'location', + id: 'foo stop', + latitude: 52.515503, + longitude: 13.418027 + }, + products: [123] + }) + + const withoutLoc = parse(profile, opt, null, omit(input, ['crd'])) + t.equal(withoutLoc.location, null) + + const mainMast = parse(profile, opt, null, {...input, isMainMast: true}) + t.equal(mainMast.type, 'station') + + const meta = parse(profile, opt, null, {...input, meta: 1}) + t.equal(meta.isMeta, true) + + const lineA = {id: 'a'} + const withLines = parse(profile, {...opt, linesOfStops: true}, null, { + ...input, lines: [lineA] + }) + t.deepEqual(withLines.lines, [lineA]) + + t.end() +}) diff --git a/test/parse/operator.js b/test/parse/operator.js new file mode 100644 index 00000000..6f73f329 --- /dev/null +++ b/test/parse/operator.js @@ -0,0 +1,21 @@ +'use strict' + +const test = require('tape') +const parse = require('../../parse/operator') + +test('parses an operator correctly', (t) => { + const profile = {} + + const op = { + "name": "Berliner Verkehrsbetriebe", + "icoX": 1, + "id": "Berliner Verkehrsbetriebe" + } + + t.deepEqual(parse(profile, op), { + type: 'operator', + id: 'berliner-verkehrsbetriebe', + name: 'Berliner Verkehrsbetriebe' + }) + t.end() +}) diff --git a/test/parse/warning.js b/test/parse/warning.js new file mode 100644 index 00000000..4bce1b16 --- /dev/null +++ b/test/parse/warning.js @@ -0,0 +1,63 @@ +'use strict' + +const test = require('tape') +const parse = require('../../parse/warning') + +const profile = { + parseProducts: bitmask => [bitmask], + parseDateTime: (_, date, time) => date + ':' + time +} + +test('parses warnings correctly', (t) => { + const input = { + hid: 'some warning ID', // todo: null + head: 'some
summary', // todo: null + text: 'some long
text

body', // todo: null + icon: {type: 'HimWarn'}, // todo: null + prio: 123, + cat: 1 + } + const expected = { + id: 'some warning ID', + type: 'status', + summary: 'some\nsummary', + text: 'some long\ntext\n\nbody', + icon: {type: 'HimWarn'}, + priority: 123, + category: 1 + } + + t.deepEqual(parse(profile, input), expected) + + // without basic fields + t.deepEqual(parse(profile, {...input, hid: null}), {...expected, id: null}) + t.deepEqual(parse(profile, {...input, head: null}), {...expected, summary: null}) + t.deepEqual(parse(profile, {...input, text: null}), {...expected, text: null}) + t.deepEqual(parse(profile, {...input, cat: null}), {...expected, category: null}) + + // without icon + t.deepEqual(parse(profile, {...input, icon: null}), { + ...expected, type: 'warning', icon: null + }) + + // with products + t.deepEqual(parse(profile, {...input, prod: 123}), { + ...expected, products: [123] + }) + + // validFrom, validUntil, modified + t.deepEqual(parse(profile, { + ...input, + sDate: '20190101', sTime: '094020', + eDate: '20190101', eTime: '114020', + lModDate: '20190101', lModTime: '084020', + }), { + ...expected, + validFrom: '20190101:094020', + validUntil: '20190101:114020', + modified: '20190101:084020' + }) + + // todo: .edges, .events + t.end() +}) diff --git a/test/parse/when.js b/test/parse/when.js new file mode 100644 index 00000000..c5160d9a --- /dev/null +++ b/test/parse/when.js @@ -0,0 +1,38 @@ +'use strict' + +const test = require('tape') +const parse = require('../../parse/when') + +const profile = { + parseDateTime: (profile, date, time, tzOffset, timestamp = false) => { + if (timestamp) return ((date + '' + time) - tzOffset * 60) * 1000 + return date + ':' + time + } +} + +test('parseWhen works correctly', (t) => { + const date = '20190606' + const timeS = '163000' + const timeR = '163130' + const tzOffset = 120 + const expected = { + when: '20190606:163130', + plannedWhen: '20190606:163000', + delay: 130 // seconds + } + + t.deepEqual(parse(profile, date, timeS, timeR, tzOffset), expected) + + // no realtime data + t.deepEqual(parse(profile, date, timeS, null, tzOffset), { + ...expected, when: expected.plannedWhen, delay: null + }) + + // cancelled + t.deepEqual(parse(profile, date, timeS, timeR, tzOffset, true), { + ...expected, + when: null, + prognosedWhen: expected.when + }) + t.end() +})