bridge-node-server/node_server/utils/test/logging.spec.js
Martin Donnelly 57bd6c8e6a init
2018-06-24 21:15:03 +01:00

175 lines
4.4 KiB
JavaScript

/**
* @fileOverview Test the logging libraries
*/
'use strict';
const Transport = require('winston-transport');
const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
const _ = require('lodash');
const logging = require('../logging');
const expect = chai.expect;
const sandbox = sinon.createSandbox();
chai.use(sinonChai);
const FILENAME = '/some/file/name.js';
const ID = 'test:logging';
const INFO_LOG_STRING = 'String sent to log.info';
const ERROR_LOG_STRING = 'String sent to log.error';
const EXTRA_INFO = {
extra1: 1,
extra2: '2'
};
const FAKE_IP = '127.0.0.2';
const REQUEST_ID = 1234;
const USER_ID = '05afcaac4b73658acc79a26d981246978135edadf1';
const FAKE_REQ = {
ip: FAKE_IP,
bridgeUniqueId: REQUEST_ID,
session: {
data: {
user: USER_ID
}
}
};
/**
* Expected results
*/
const EXPECTED_BASIC_LOG = {
meta: {
ip: FAKE_IP,
file: FILENAME,
logId: ID,
reqId: REQUEST_ID,
userId: USER_ID
}
};
const EXPECTED_EXTENDED_LOG = _.defaults({},
EXPECTED_BASIC_LOG,
{
meta: {
_extra1: 1,
_extra2: '2'
}
}
);
const EXPECTED_INFO_LEVEL = {
level: 'info',
message: INFO_LOG_STRING
};
const EXPECTED_ERROR_LEVEL = {
level: 'error',
message: ERROR_LOG_STRING
};
/**
* Make a fake log transport with a spy
*/
class SpyTransport extends Transport {
// eslint-disable-next-line class-methods-use-this
log(info, callback) {
// Null transport doesn't do anything
callback();
}
}
const spyTransport = new SpyTransport();
sandbox.spy(spyTransport, 'log');
/**
* Function to expect that the correct values were called based on the values
* collected by the spy.
*
* @param {Object} expected - the values we expect to be logged
*
* @returns {Promise} - promise for the result of the expectation
*/
function expectLoggedValues(expected) {
return expect(spyTransport.log).to.be
.calledOnce
.calledWith(sinon.match(expected));
}
/**
* The tests
*/
describe('Initialised log', () => {
let log;
let fakeTimer;
before(() => {
/**
* Use fake timers so we can control the timing of the logged timestamp.
*/
fakeTimer = sinon.useFakeTimers();
const logger = logging._test.getLogger();
logger.add(spyTransport);
log = logging(FILENAME, ID);
});
after(() => {
/**
* Put real timers back after all the tests are complete.
*/
fakeTimer.restore();
});
beforeEach(() => {
/**
* Create the log anew, and reset any sandbox history for each test.
*/
log = logging(FILENAME, ID);
sandbox.resetHistory();
});
it('has an info() function', () => {
return expect(log)
.to.have.property('info')
.to.be.instanceOf(Function);
});
it('has an error() function', () => {
return expect(log)
.to.have.property('error')
.to.be.instanceOf(Function);
});
describe('calling info function', () => {
it('with a `req` and a message logs all basic details at info level', () => {
log.info(FAKE_REQ, INFO_LOG_STRING);
const expected = _.defaults({}, EXPECTED_BASIC_LOG, EXPECTED_INFO_LEVEL);
return expectLoggedValues(expected);
});
it('with a `req`, a message, & more data, merges the extra props prefixed with `_` at info level', () => {
log.info(FAKE_REQ, INFO_LOG_STRING, EXTRA_INFO);
const expected = _.defaults({}, EXPECTED_EXTENDED_LOG, EXPECTED_INFO_LEVEL);
return expectLoggedValues(expected);
});
});
describe('calling error function', () => {
it('with a `req` and a message logs all basic details at error level', () => {
log.error(FAKE_REQ, ERROR_LOG_STRING);
const expected = _.defaults({}, EXPECTED_BASIC_LOG, EXPECTED_ERROR_LEVEL);
return expectLoggedValues(expected);
});
it('with a `req`, a message, & more data, merges the extra props prefixed with `_` at error level', () => {
log.error(FAKE_REQ, ERROR_LOG_STRING, EXTRA_INFO);
const expected = _.defaults({}, EXPECTED_EXTENDED_LOG, EXPECTED_ERROR_LEVEL);
return expectLoggedValues(expected);
});
});
});