202 lines
4.9 KiB
JavaScript
202 lines
4.9 KiB
JavaScript
|
'use strict'
|
||
|
|
||
|
const tap = require('tap')
|
||
|
const messageTrackerFactory = require('../../../../lib/client/message-tracker/')
|
||
|
|
||
|
tap.test('options', t => {
|
||
|
t.test('requires an options object', async t => {
|
||
|
try {
|
||
|
messageTrackerFactory()
|
||
|
} catch (error) {
|
||
|
t.match(error, /options object is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory([])
|
||
|
} catch (error) {
|
||
|
t.match(error, /options object is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory('')
|
||
|
} catch (error) {
|
||
|
t.match(error, /options object is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory(42)
|
||
|
} catch (error) {
|
||
|
t.match(error, /options object is required/)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.test('requires id to be a string', async t => {
|
||
|
try {
|
||
|
messageTrackerFactory({ id: {} })
|
||
|
} catch (error) {
|
||
|
t.match(error, /options\.id string is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory({ id: [] })
|
||
|
} catch (error) {
|
||
|
t.match(error, /options\.id string is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory({ id: 42 })
|
||
|
} catch (error) {
|
||
|
t.match(error, /options\.id string is required/)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.test('requires parser to be an object', async t => {
|
||
|
try {
|
||
|
messageTrackerFactory({ id: 'foo', parser: 'bar' })
|
||
|
} catch (error) {
|
||
|
t.match(error, /options\.parser object is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory({ id: 'foo', parser: 42 })
|
||
|
} catch (error) {
|
||
|
t.match(error, /options\.parser object is required/)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
messageTrackerFactory({ id: 'foo', parser: [] })
|
||
|
} catch (error) {
|
||
|
t.match(error, /options\.parser object is required/)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|
||
|
|
||
|
tap.test('.pending', t => {
|
||
|
t.test('returns 0 for no messages', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
t.is(tracker.pending, 0)
|
||
|
})
|
||
|
|
||
|
t.test('returns 1 for 1 message', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, () => {})
|
||
|
t.is(tracker.pending, 1)
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|
||
|
|
||
|
tap.test('#abandon', t => {
|
||
|
t.test('returns false if message does not exist', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
const result = tracker.abandon(1)
|
||
|
t.is(result, false)
|
||
|
})
|
||
|
|
||
|
t.test('returns true if message is abandoned', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, {})
|
||
|
const result = tracker.abandon(1)
|
||
|
t.is(result, true)
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|
||
|
|
||
|
tap.test('#fetch', t => {
|
||
|
t.test('returns handler for fetched message', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, handler)
|
||
|
const fetched = tracker.fetch(1)
|
||
|
t.is(fetched, handler)
|
||
|
|
||
|
function handler () {}
|
||
|
})
|
||
|
|
||
|
t.test('returns handler for fetched abandoned message', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, handler)
|
||
|
tracker.track({ abandon: 'message' }, () => {})
|
||
|
tracker.abandon(1)
|
||
|
const fetched = tracker.fetch(1)
|
||
|
t.is(fetched, handler)
|
||
|
|
||
|
function handler () {}
|
||
|
})
|
||
|
|
||
|
t.test('returns null when message does not exist', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
const fetched = tracker.fetch(1)
|
||
|
t.is(fetched, null)
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|
||
|
|
||
|
tap.test('#purge', t => {
|
||
|
t.test('invokes cb for each tracked message', async t => {
|
||
|
t.plan(4)
|
||
|
let count = 0
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, handler1)
|
||
|
tracker.track({}, handler2)
|
||
|
tracker.purge(cb)
|
||
|
|
||
|
function cb (msgID, handler) {
|
||
|
if (count === 0) {
|
||
|
t.is(msgID, 1)
|
||
|
t.is(handler, handler1)
|
||
|
count += 1
|
||
|
return
|
||
|
}
|
||
|
t.is(msgID, 2)
|
||
|
t.is(handler, handler2)
|
||
|
}
|
||
|
|
||
|
function handler1 () {}
|
||
|
function handler2 () {}
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|
||
|
|
||
|
tap.test('#remove', t => {
|
||
|
t.test('removes from the current track', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, () => {})
|
||
|
tracker.remove(1)
|
||
|
t.is(tracker.pending, 0)
|
||
|
})
|
||
|
|
||
|
// Not a great test. It exercises the desired code path, but we probably
|
||
|
// should expose some insight into the abandoned track.
|
||
|
t.test('removes from the abandoned track', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
tracker.track({}, () => {})
|
||
|
tracker.track({ abandon: 'message' }, () => {})
|
||
|
tracker.abandon(1)
|
||
|
tracker.remove(1)
|
||
|
t.is(tracker.pending, 1)
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|
||
|
|
||
|
tap.test('#track', t => {
|
||
|
t.test('add messageID and tracks message', async t => {
|
||
|
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||
|
const msg = {}
|
||
|
tracker.track(msg, handler)
|
||
|
|
||
|
t.deepEqual(msg, { messageID: 1 })
|
||
|
const cb = tracker.fetch(1)
|
||
|
t.is(cb, handler)
|
||
|
|
||
|
function handler () {}
|
||
|
})
|
||
|
|
||
|
t.end()
|
||
|
})
|