Feat: code refactoring and jest tests
chore: More refactoring chore: More tests and refactors fix: Fixed age not getting calculated properly chore: Implemented mocking in jest chore: More mock tests chore: checkStuckScreen tests
This commit is contained in:
parent
65165b943b
commit
04fd82454d
12 changed files with 1047 additions and 66 deletions
28
lib/notifier/test/email.test.js
Normal file
28
lib/notifier/test/email.test.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
const email = require('../email')
|
||||
|
||||
const alertRec = {
|
||||
devices: {
|
||||
f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05: {
|
||||
balanceAlerts: [],
|
||||
deviceAlerts: [
|
||||
{ code: 'PING', age: 602784301.446, machineName: 'Abc123' }
|
||||
]
|
||||
}
|
||||
},
|
||||
deviceNames: {
|
||||
f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05: 'Abc123'
|
||||
},
|
||||
general: []
|
||||
}
|
||||
|
||||
const printEmailMsg = `Errors were reported by your Lamassu Machines.
|
||||
|
||||
Errors for Abc123:
|
||||
Machine down for ~6 days
|
||||
`
|
||||
|
||||
test('Print Email Alers', () => {
|
||||
expect(email.printEmailAlerts(alertRec, { active: true, errors: true })).toBe(
|
||||
printEmailMsg
|
||||
)
|
||||
})
|
||||
234
lib/notifier/test/notifier.test.js
Normal file
234
lib/notifier/test/notifier.test.js
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
const notifier = require('..')
|
||||
|
||||
// mock plugins object with mock data to test functions
|
||||
const plugins = {
|
||||
sendMessage: rec => {
|
||||
return rec
|
||||
},
|
||||
getNotificationConfig: () => ({
|
||||
email_active: false,
|
||||
sms_active: true,
|
||||
email_errors: false,
|
||||
sms_errors: true,
|
||||
sms: { active: true, errors: true },
|
||||
email: { active: false, errors: false }
|
||||
}),
|
||||
getMachineNames: () => [
|
||||
{
|
||||
deviceId:
|
||||
'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
cashbox: 0,
|
||||
cassette1: 444,
|
||||
cassette2: 222,
|
||||
version: '7.5.0-beta.0',
|
||||
model: 'unknown',
|
||||
pairedAt: '2020-11-13T16:20:31.624Z',
|
||||
lastPing: '2020-11-16T13:11:03.169Z',
|
||||
name: 'Abc123',
|
||||
paired: true,
|
||||
cashOut: true,
|
||||
statuses: [{ label: 'Unresponsive', type: 'error' }]
|
||||
}
|
||||
],
|
||||
checkBalances: () => []
|
||||
}
|
||||
|
||||
const devices = [
|
||||
{
|
||||
deviceId:
|
||||
'7e531a2666987aa27b9917ca17df7998f72771c57fdb21c90bc033999edd17e4',
|
||||
lastPing: '2020-11-16T13:11:03.169Z',
|
||||
name: 'Abc123'
|
||||
},
|
||||
{
|
||||
deviceId:
|
||||
'9871e58aa2643ff9445cbc299b50397430ada75157d6c29b4c93548fff0f48f7',
|
||||
lastPing: '2020-11-16T16:21:35.948Z',
|
||||
name: 'Machine 2'
|
||||
},
|
||||
{
|
||||
deviceId:
|
||||
'5ae0d02dedeb77b6521bd5eb7c9159bdc025873fa0bcb6f87aaddfbda0c50913',
|
||||
lastPing: '2020-11-19T15:07:57.089Z',
|
||||
name: 'Machine 3'
|
||||
},
|
||||
{
|
||||
deviceId:
|
||||
'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
lastPing: '2020-11-23T19:34:41.031Z',
|
||||
name: 'New Machine 4 '
|
||||
}
|
||||
]
|
||||
|
||||
test('Exits checkNotifications with Promise.resolve() if SMS and Email are disabled', async () => {
|
||||
expect.assertions(1)
|
||||
await expect(
|
||||
notifier.checkNotification({
|
||||
getNotificationConfig: () => ({
|
||||
sms: { active: false, errors: false },
|
||||
email: { active: false, errors: false }
|
||||
})
|
||||
})
|
||||
).resolves.toBe(undefined)
|
||||
})
|
||||
|
||||
test('Exits checkNotifications with Promise.resolve() if SMS and Email are disabled even if errors or balance are defined to something', async () => {
|
||||
expect.assertions(1)
|
||||
await expect(
|
||||
notifier.checkNotification({
|
||||
getNotificationConfig: () => ({
|
||||
sms: { active: false, errors: true, balance: true },
|
||||
email: { active: false, errors: true, balance: true }
|
||||
})
|
||||
})
|
||||
).resolves.toBe(undefined)
|
||||
})
|
||||
|
||||
test("Check Pings should return code PING for devices that haven't been pinged recently", () => {
|
||||
expect(
|
||||
notifier.checkPings([
|
||||
{
|
||||
deviceId:
|
||||
'7e531a2666987aa27b9917ca17df7998f72771c57fdb21c90bc033999edd17e4',
|
||||
lastPing: '2020-11-16T13:11:03.169Z',
|
||||
name: 'Abc123'
|
||||
}
|
||||
])
|
||||
).toMatchObject({
|
||||
'7e531a2666987aa27b9917ca17df7998f72771c57fdb21c90bc033999edd17e4': [
|
||||
{ code: 'PING', machineName: 'Abc123' }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('Checkpings returns empty array as the value for the id prop, if the lastPing is more recent than 60 seconds', () => {
|
||||
expect(
|
||||
notifier.checkPings([
|
||||
{
|
||||
deviceId:
|
||||
'7a531a2666987aa27b9917ca17df7998f72771c57fdb21c90bc033999edd17e4',
|
||||
lastPing: new Date(),
|
||||
name: 'Abc123'
|
||||
}
|
||||
])
|
||||
).toMatchObject({
|
||||
'7a531a2666987aa27b9917ca17df7998f72771c57fdb21c90bc033999edd17e4': []
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
// https://stackoverflow.com/questions/58151010/difference-between-resetallmocks-resetmodules-resetmoduleregistry-restoreallm
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
const utils = require('../utils')
|
||||
|
||||
test('Check notification resolves to undefined if shouldNotAlert is called and is true', async () => {
|
||||
const mockShouldNotAlert = jest.spyOn(utils, 'shouldNotAlert')
|
||||
mockShouldNotAlert.mockReturnValue(true)
|
||||
|
||||
const result = await notifier.checkNotification(plugins)
|
||||
expect(mockShouldNotAlert).toHaveBeenCalledTimes(1)
|
||||
expect(result).toBe(undefined)
|
||||
})
|
||||
|
||||
test('Sendmessage is called if shouldNotAlert is called and is false', async () => {
|
||||
const mockShouldNotAlert = jest.spyOn(utils, 'shouldNotAlert')
|
||||
const mockSendMessage = jest.spyOn(plugins, 'sendMessage')
|
||||
|
||||
mockShouldNotAlert.mockReturnValue(false)
|
||||
const result = await notifier.checkNotification(plugins)
|
||||
|
||||
expect(mockShouldNotAlert).toHaveBeenCalledTimes(1)
|
||||
expect(mockSendMessage).toHaveBeenCalledTimes(1)
|
||||
expect(result).toBe(undefined)
|
||||
})
|
||||
|
||||
test('If no alert fingerprint and inAlert is true, exits on call to sendNoAlerts', async () => {
|
||||
// mock utils.buildAlertFingerprint to return null
|
||||
// mock utils.getAlertFingerprint to be true which will make inAlert true
|
||||
|
||||
const buildFp = jest.spyOn(utils, 'buildAlertFingerprint')
|
||||
const mockGetFp = jest.spyOn(utils, 'getAlertFingerprint')
|
||||
const mockSendNoAlerts = jest.spyOn(utils, 'sendNoAlerts')
|
||||
|
||||
buildFp.mockReturnValue(null)
|
||||
mockGetFp.mockReturnValue(true)
|
||||
await notifier.checkNotification(plugins)
|
||||
|
||||
expect(mockGetFp).toHaveBeenCalledTimes(1)
|
||||
expect(mockSendNoAlerts).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
|
||||
// vvv tests for checkstuckscreen...
|
||||
test('checkStuckScreen returns [] when no events are found', () => {
|
||||
expect(notifier.checkStuckScreen([], 'Abc123')).toEqual([])
|
||||
})
|
||||
|
||||
test('checkStuckScreen returns [] if most recent event is idle', () => {
|
||||
// device_time is what matters for the sorting of the events by recency
|
||||
expect(notifier.checkStuckScreen([{
|
||||
id: '48ae51c6-c5b4-485e-b81d-aa337fc025e2',
|
||||
device_id: 'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
event_type: 'stateChange',
|
||||
note: '{"state":"chooseCoin","isIdle":false}',
|
||||
created: "2020-11-23T19:30:29.209Z",
|
||||
device_time: "1999-11-23T19:30:29.177Z",
|
||||
age: 157352628.123
|
||||
}, {
|
||||
id: '48ae51c6-c5b4-485e-b81d-aa337fc025e2',
|
||||
device_id: 'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
event_type: 'stateChange',
|
||||
note: '{"state":"chooseCoin","isIdle":true}',
|
||||
created: "2020-11-23T19:30:29.209Z",
|
||||
device_time: "2020-11-23T19:30:29.177Z",
|
||||
age: 157352628.123
|
||||
}])).toEqual([])
|
||||
})
|
||||
|
||||
test('checkStuckScreen returns object array of length 1 with prop code: "STALE" if age > STALE_STATE', () => {
|
||||
// there is an age 0 and an isIdle true in the first object but it will be below the second one in the sorting order and thus ignored
|
||||
const result = notifier.checkStuckScreen([{
|
||||
id: '48ae51c6-c5b4-485e-b81d-aa337fc025e2',
|
||||
device_id: 'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
event_type: 'stateChange',
|
||||
note: '{"state":"chooseCoin","isIdle":true}',
|
||||
created: "2020-11-23T19:30:29.209Z",
|
||||
device_time: "1999-11-23T19:30:29.177Z",
|
||||
age: 0
|
||||
}, {
|
||||
id: '48ae51c6-c5b4-485e-b81d-aa337fc025e2',
|
||||
device_id: 'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
event_type: 'stateChange',
|
||||
note: '{"state":"chooseCoin","isIdle":false}',
|
||||
created: "2020-11-23T19:30:29.209Z",
|
||||
device_time: "2020-11-23T19:30:29.177Z",
|
||||
age: 157352628.123
|
||||
}])
|
||||
expect(result[0]).toMatchObject({code: "STALE"})
|
||||
})
|
||||
|
||||
test('checkStuckScreen returns empty array if age < STALE_STATE', () => {
|
||||
const STALE_STATE = require("../codes").STALE_STATE
|
||||
const result1 = notifier.checkStuckScreen([{
|
||||
id: '48ae51c6-c5b4-485e-b81d-aa337fc025e2',
|
||||
device_id: 'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
event_type: 'stateChange',
|
||||
note: '{"state":"chooseCoin","isIdle":false}',
|
||||
created: "2020-11-23T19:30:29.209Z",
|
||||
device_time: "2020-11-23T19:30:29.177Z",
|
||||
age: 0
|
||||
}])
|
||||
const result2 = notifier.checkStuckScreen([{
|
||||
id: '48ae51c6-c5b4-485e-b81d-aa337fc025e2',
|
||||
device_id: 'f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05',
|
||||
event_type: 'stateChange',
|
||||
note: '{"state":"chooseCoin","isIdle":false}',
|
||||
created: "2020-11-23T19:30:29.209Z",
|
||||
device_time: "2020-11-23T19:30:29.177Z",
|
||||
age: STALE_STATE
|
||||
}])
|
||||
expect(result1).toEqual([])
|
||||
expect(result2).toEqual([])
|
||||
})
|
||||
22
lib/notifier/test/sms.test.js
Normal file
22
lib/notifier/test/sms.test.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
const sms = require('../sms')
|
||||
|
||||
const alertRec = {
|
||||
devices: {
|
||||
f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05: {
|
||||
balanceAlerts: [],
|
||||
deviceAlerts: [
|
||||
{ code: 'PING', age: 602784301.446, machineName: 'Abc123' }
|
||||
]
|
||||
}
|
||||
},
|
||||
deviceNames: {
|
||||
f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05: 'Abc123'
|
||||
},
|
||||
general: []
|
||||
}
|
||||
|
||||
test('Print SMS alerts', () => {
|
||||
expect(sms.printSmsAlerts(alertRec, { active: true, errors: true })).toBe(
|
||||
'[Lamassu] Errors reported: Machine Down (Abc123)'
|
||||
)
|
||||
})
|
||||
100
lib/notifier/test/utils.test.js
Normal file
100
lib/notifier/test/utils.test.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
const utils = require('../utils')
|
||||
|
||||
const plugins = {
|
||||
sendMessage: rec => {
|
||||
return rec
|
||||
}
|
||||
}
|
||||
|
||||
const alertRec = {
|
||||
devices: {
|
||||
f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05: {
|
||||
balanceAlerts: [],
|
||||
deviceAlerts: [
|
||||
{ code: 'PING', age: 1605532263169, machineName: 'Abc123' }
|
||||
]
|
||||
}
|
||||
},
|
||||
deviceNames: {
|
||||
f02af604ca9010bd9ae04c427a24da90130da10d355f0a9b235886a89008fc05: 'Abc123'
|
||||
},
|
||||
general: []
|
||||
}
|
||||
|
||||
const notifications = {
|
||||
sms: { active: true, errors: true },
|
||||
email: { active: false, errors: false }
|
||||
}
|
||||
|
||||
test('Build alert fingerprint returns null if no sms or email alerts', () => {
|
||||
expect(
|
||||
utils.buildAlertFingerprint(
|
||||
{
|
||||
devices: {},
|
||||
deviceNames: {},
|
||||
general: []
|
||||
},
|
||||
notifications
|
||||
)
|
||||
).toBe(null)
|
||||
})
|
||||
|
||||
test('Build alert fingerprint returns null if sms and email are disabled', () => {
|
||||
expect(
|
||||
utils.buildAlertFingerprint(alertRec, {
|
||||
sms: { active: false, errors: true },
|
||||
email: { active: false, errors: false }
|
||||
})
|
||||
).toBe(null)
|
||||
})
|
||||
|
||||
test('Build alert fingerprint returns hash if email or [sms] are enabled and there are alerts in alertrec', () => {
|
||||
expect(
|
||||
typeof utils.buildAlertFingerprint(alertRec, {
|
||||
sms: { active: true, errors: true },
|
||||
email: { active: false, errors: false }
|
||||
})
|
||||
).toBe('string')
|
||||
})
|
||||
|
||||
test('Build alert fingerprint returns hash if [email] or sms are enabled and there are alerts in alertrec', () => {
|
||||
expect(
|
||||
typeof utils.buildAlertFingerprint(alertRec, {
|
||||
sms: { active: false, errors: false },
|
||||
email: { active: true, errors: true }
|
||||
})
|
||||
).toBe('string')
|
||||
})
|
||||
|
||||
test('Send no alerts returns empty object with sms and email disabled', () => {
|
||||
expect(utils.sendNoAlerts(plugins, false, false)).toEqual({})
|
||||
})
|
||||
|
||||
test('Send no alerts returns object with sms prop with sms only enabled', () => {
|
||||
expect(utils.sendNoAlerts(plugins, true, false)).toEqual({
|
||||
sms: {
|
||||
body: '[Lamassu] All clear'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('Send no alerts returns object with sms and email prop with both enabled', () => {
|
||||
expect(utils.sendNoAlerts(plugins, true, true)).toEqual({
|
||||
email: {
|
||||
body: 'No errors are reported for your machines.',
|
||||
subject: '[Lamassu] All clear'
|
||||
},
|
||||
sms: {
|
||||
body: '[Lamassu] All clear'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('Send no alerts returns object with email prop if only email is enabled', () => {
|
||||
expect(utils.sendNoAlerts(plugins, false, true)).toEqual({
|
||||
email: {
|
||||
body: 'No errors are reported for your machines.',
|
||||
subject: '[Lamassu] All clear'
|
||||
}
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue