Files
elasticsearch-js/test/unit/specs/log.js
Julian Simioni 9dfcc20bd9 Use JSON.stringify to log objects
There are two major advantages to JSON.stringify over util.inspect:

1.) JSON.stringify defaults to recursively printing deeply nested
objects.

2.) JSON.stringify output is JSON, meaning it can be taken directly from
the output and used wherever JSON is accepted. util.inspect output is
JSON-like, but also includes other annotation such as the types of
various values, as well as functions on objects.
2016-03-31 14:08:27 -04:00

260 lines
8.0 KiB
JavaScript

var Log = require('../../../src/lib/log');
var _ = require('lodash');
var expect = require('expect.js');
describe('Log class', function () {
describe('::parseLevels', function () {
it('accepts a string and returns it and the other levels below it', function () {
expect(Log.parseLevels('trace')).to.eql([
'error',
'warning',
'info',
'debug',
'trace'
]);
});
it('accepts and validates an array of levels', function () {
expect(Log.parseLevels(['warning', 'info'])).to.eql(['warning', 'info']);
});
it('throws an error when an invalid string is supplied', function () {
expect(function () {
Log.parseLevels('INVALID');
}).to.throwError(/invalid logging level/);
});
it('throws an error when an invalid string is supplied in side an array', function () {
expect(function () {
Log.parseLevels(['error', 'INVALID']);
}).to.throwError(/invalid logging level/);
});
});
describe('#addOutput', function () {
var log;
Log.loggers.stub = function (log, config) {
this.config = config;
};
beforeEach(function () {
log = new Log();
});
it('returns the newly created logger', function () {
expect(log.addOutput({ type: 'stub' })).to.be.a(Log.loggers.stub);
});
it('Accepts a config object with `level: "{{level}}"`', function () {
var logger = log.addOutput({
type: 'stub',
level: 'warning'
});
expect(logger.config.levels).to.eql([
'error', 'warning'
]);
});
it('Accepts a config object with `level: ["{{level}}"]`', function () {
var logger = log.addOutput({
type: 'stub',
level: ['warning']
});
expect(logger.config.levels).to.eql([
'warning'
]);
});
it('Accepts a config object with `levels: "{{level}}"`', function () {
var logger = log.addOutput({
type: 'stub',
levels: 'warning'
});
expect(logger.config.levels).to.eql([
'error', 'warning'
]);
});
it('Accepts a config object with `levels: ["{{level}}"]`', function () {
var logger = log.addOutput({
type: 'stub',
level: ['warning']
});
expect(logger.config.levels).to.eql([
'warning'
]);
});
});
describe('#join', function () {
it('joins strings together with spaces', function () {
expect(Log.join(['foo', 'bar'])).to.eql('foo bar');
});
it('stringifies objects', function () {
expect(Log.join([{ foo: 'bar' }])).to.eql('{\n "foo": "bar"\n}\n');
});
it('fully stringifies deeply nested objects', function() {
var object = { foo: { bar: { baz: 'value' } } };
var expected = '{\n "bar": {\n "baz": "value"\n }\n}\n';
expect(Log.join(object)).to.eql(expected);
});
});
describe('instance without any outputs', function () {
var log;
beforeEach(function () {
log = new Log();
});
it('should not emit any events', function () {
log.emit = function () {
throw new Error('Emit should not be called');
};
log.error();
log.info();
log.warning();
log.debug();
log.trace();
});
});
describe('instance without one output listening to all events', function () {
var log, call;
beforeEach(function () {
call = void 0;
log = new Log({
log: [
{
type: function (log, config) {
log.on('error', _.noop);
log.on('warning', _.noop);
log.on('info', _.noop);
log.on('debug', _.noop);
log.on('trace', _.noop);
}
}
]
});
log.emit = function (eventName) {
call = {
event : eventName,
args: Array.prototype.slice.call(arguments, 1)
};
};
});
it('should emit an "error" event with an Error object arg', function () {
var err = new Error('error');
log.error(err);
expect(call.event).to.eql('error');
expect(call.args[0]).to.be(err);
call = void 0;
log.error('error');
expect(call.event).to.eql('error');
expect(call.args[0]).to.be.a(Error);
expect(call.args[0].message).to.eql('error');
});
it('should emit a "warning" event with a single message arg for #warning calls', function () {
log.warning('shit!');
expect(call.event).to.eql('warning');
expect(call.args.length).to.be(1);
expect(call.args[0]).to.eql('shit!');
});
it('should emit a "info" event with a single message arg for #info calls', function () {
log.info('look out!');
expect(call.event).to.eql('info');
expect(call.args.length).to.be(1);
expect(call.args[0]).to.eql('look out!');
});
it('should emit a "debug" event with a single message arg for #debug calls', function () {
log.debug('here');
expect(call.event).to.eql('debug');
expect(call.args.length).to.be(1);
expect(call.args[0]).to.eql('here');
});
it('should emit a trace event for trace events, with normalized request details arg', function () {
log.trace('GET', 'http://localhost:9200/_cluster/nodes', '', '', 200);
expect(call.event).to.eql('trace');
expect(call.args.length).to.be(1);
expect(call.args[0]).to.have.property('method', 'GET');
expect(call.args[0]).to.have.property('url', 'http://localhost:9200/_cluster/nodes');
expect(call.args[0]).to.have.property('status', 200);
});
});
describe('constructor', function () {
it('looks for output config options at config.log', function () {
var log = new Log({ log: { type: process.browser ? 'console' : 'stdio', level: 'error' } });
expect(log.listenerCount('error')).to.eql(1);
expect(log.listenerCount('warning')).to.eql(0);
expect(log.listenerCount('info')).to.eql(0);
expect(log.listenerCount('debug')).to.eql(0);
expect(log.listenerCount('trace')).to.eql(0);
});
it('accepts a string and treat it as a log level', function () {
var log = new Log({ log: 'error' });
expect(log.listenerCount('error')).to.eql(1);
expect(log.listenerCount('warning')).to.eql(0);
expect(log.listenerCount('info')).to.eql(0);
expect(log.listenerCount('debug')).to.eql(0);
expect(log.listenerCount('trace')).to.eql(0);
});
it('accepts an array of strings and treat it as a log level config', function () {
var log = new Log({ log: ['error', 'trace'] });
expect(log.listenerCount('error')).to.eql(1);
expect(log.listenerCount('warning')).to.eql(0);
expect(log.listenerCount('info')).to.eql(0);
expect(log.listenerCount('debug')).to.eql(0);
expect(log.listenerCount('trace')).to.eql(1);
});
it('accepts an array of output config objects', function () {
var log = new Log({ log: [{ level: 'error' }, { level: 'trace'}] });
expect(log.listenerCount('error')).to.eql(2);
expect(log.listenerCount('warning')).to.eql(1);
expect(log.listenerCount('info')).to.eql(1);
expect(log.listenerCount('debug')).to.eql(1);
expect(log.listenerCount('trace')).to.eql(1);
});
it('rejects numbers and other truthy data-types', function () {
expect(function () {
var log = new Log({ log: 1515 });
}).to.throwError(/invalid logging output config/i);
expect(function () {
var log = new Log({ log: /regexp/ });
}).to.throwError(/invalid logging output config/i);
expect(function () {
var log = new Log({ log: new Date() });
}).to.throwError(/invalid logging output config/i);
expect(function () {
var log = new Log({ log: [1515] });
}).to.throwError(/invalid logging output config/i);
expect(function () {
var log = new Log({ log: [/regexp/] });
}).to.throwError(/invalid logging output config/i);
expect(function () {
var log = new Log({ log: [new Date()] });
}).to.throwError(/invalid logging output config/i);
});
});
});