tests for parse/*

This commit is contained in:
Jannis R 2019-09-03 15:35:12 +02:00
parent 5ea22f7a59
commit cc74f6a85b
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
13 changed files with 469 additions and 38 deletions

View file

@ -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'

View file

@ -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"
}
}

View file

@ -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()
})

View file

@ -1,5 +1,7 @@
'use strict'
require('./parse')
require('./bvg-journey')
require('./vbb-departures')
require('./bvg-radar')

50
test/parse/date-time.js Normal file
View file

@ -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()
})

56
test/parse/hint.js Normal file
View file

@ -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()
})

66
test/parse/icon.js Normal file
View file

@ -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()
})

10
test/parse/index.js Normal file
View file

@ -0,0 +1,10 @@
'use strict'
require('./date-time')
require('./icon')
require('./operator')
require('./location')
require('./when')
require('./line')
require('./hint')
require('./warning')

54
test/parse/line.js Normal file
View file

@ -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()
})

101
test/parse/location.js Normal file
View file

@ -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()
})

21
test/parse/operator.js Normal file
View file

@ -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()
})

63
test/parse/warning.js Normal file
View file

@ -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<br>summary', // todo: null
text: 'some long<br>text<br><br />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()
})

38
test/parse/when.js Normal file
View file

@ -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()
})