3v324v23's picture
Add PNG files and track with Git LFS
befd7da
'use strict';
const expect = require('chai').expect;
const rewire = require('rewire');
let logger = require('../index');
const { init } = require('../index');
const SensitiveDataStream = require('../streams/sensitive-data');
const PrettyStream = require('bunyan-prettystream');
const SentryStream = require('bunyan-sentry-stream').SentryStream;
describe('index.js', () => {
let oldStdoutWrite;
describe('Log functions', () => {
const logs = [];
before(() => {
oldStdoutWrite = process.stdout.write;
process.stdout.write = function stubStdout(string) {
try {
string = JSON.parse(string);
logs.push(string);
} catch (e) {
oldStdoutWrite.apply(process.stdout, [string]);
}
};
const oldEnv = process.env;
process.env = {
LOGGER_NAME: 'Test logger name',
LOGGER_LEVEL: 'debug',
SENTRY_DSN: 'https://a:b@fake.com/12345',
};
logger = rewire('../index');
process.env = oldEnv;
});
after(() => {
process.stdout.write = oldStdoutWrite;
});
it('should output the fatal level message', () => {
logger.fatal('hello');
let message = logs.shift();
expect(message.name).to.be.eql('Test logger name');
expect(message.msg).to.be.eql('hello');
expect(message.level).to.be.eql(60);
// Should keep the object safe:
logger.fatal(
{
a: 1,
},
'hello'
);
message = logs.shift();
expect(message.a).to.be.eql(1);
// Should use the Error object for the stack:
logger.fatal(new Error('Fatal error'), 'hello');
message = logs.shift();
expect(message.err)
.to.be.an('object')
.with.property('stack');
expect(message.err.stack.substr(0, 18)).to.be.eql('Error: Fatal error');
});
it('should output the error level message', () => {
logger.error('hello');
let message = logs.shift();
expect(message.level).to.be.eql(50);
// Should keep the object safe:
logger.error(
{
a: 1,
},
'hello'
);
message = logs.shift();
expect(message.a).to.be.eql(1);
// Should use the Error object for the stack:
logger.error(new Error('Fatal error'), 'hello');
message = logs.shift();
expect(message.err).to.be.an('object');
expect(message.err.stack.substr(0, 18)).to.be.eql('Error: Fatal error');
});
it('should output the warn level message', () => {
logger.warn('hello');
const message = logs.shift();
expect(message).to.have.property('level', 40);
expect(message).to.not.have.property('stack');
});
it('should output the info level message', () => {
logger.info('hello');
const message = logs.shift();
expect(message).to.have.property('level', 30);
});
it('should output the debug level message', () => {
logger.debug('hello');
const message = logs.shift();
expect(message).to.have.property('level', 20);
});
it('should not output the trace level message (level set to debug)', () => {
logger.trace('hello');
expect(logs).to.have.lengthOf(0);
});
it('should format message correctly', () => {
logger.info('hello %s', 20);
const message = logs.shift();
expect(message.msg).to.be.eql('hello 20');
});
it('should keep objects safe', () => {
logger.info(
{
a: 1,
b: {
c: 1,
},
},
'hello'
);
const message = logs.shift();
expect(message.a).to.be.eql(1);
expect(message.b).to.be.eql({
c: 1,
});
expect(message.msg).to.be.eql('hello');
});
describe('sensitive data', () => {
it('must replace sensitive data with __SENSITIVE_DATA__ in logs', () => {
logger.info(
{
password: 'My personal password',
headers: {
'accept-language': 'fr-FR', // unchanged
authorization: 'Bearer token',
},
req: {
token: 'My personal token',
},
},
'Logging amazingly sensitive data!'
);
const message = logs.shift();
expect(message.password).to.equal('__SENSITIVE_DATA__');
expect(message.headers['accept-language']).to.equal('fr-FR');
expect(message.headers.authorization).to.equal('__SENSITIVE_DATA__');
expect(message.req.token).to.equal('__SENSITIVE_DATA__');
});
});
});
describe('Streams configuration', () => {
it('should use the sensitive data stream if no config is set', () => {
const newLogger = init();
expect(newLogger.streams).to.have.lengthOf(1);
expect(newLogger.streams[0]).to.have.property('stream');
expect(newLogger.streams[0].stream).to.be.instanceOf(SensitiveDataStream);
expect(newLogger.streams[0].stream.fragments).to.equal(
'(mdp|password|authorization|token|pwd|auth)'
);
});
it('should use the sensitive data stream with specific pattern fragments if set', () => {
const newLogger = init({
logger: { sensitiveDataPattern: '(password)' },
});
expect(newLogger.streams).to.have.lengthOf(1);
expect(newLogger.streams[0]).to.have.property('stream');
expect(newLogger.streams[0].stream).to.be.instanceOf(SensitiveDataStream);
expect(newLogger.streams[0].stream.fragments).to.equal('(password)');
});
it('should use only the default stdout stream if LOGGER_USE_SENSITIVE_DATA_STREAM is false', () => {
const newLogger = init({
logger: { hideSensitiveData: false },
});
expect(newLogger.streams).to.have.lengthOf(1);
expect(newLogger.streams[0]).to.have.property('stream', process.stdout);
});
it('should use the pretty stream formatter with USE_BUNYAN_PRETTY_STREAM set to true', () => {
const newLogger = init({
logger: { pretty: true },
});
expect(newLogger.streams).to.have.lengthOf(1);
expect(newLogger.streams[0]).to.have.property('type', 'raw');
expect(newLogger.streams[0]).to.have.property('level', 30);
expect(newLogger.streams[0].stream).to.be.instanceOf(PrettyStream);
});
it('should have sentry stream with SENTRY_DSN set', () => {
const newLogger = init({
sentry: {
dsn: 'https://a:b@fake.com/12345',
release: 'some_release',
environment: 'some_env',
},
});
expect(newLogger.streams).to.have.lengthOf(2);
expect(newLogger.streams[1].stream).to.be.instanceOf(SentryStream);
expect(newLogger.streams[1].stream).to.have.deep.property(
'client.environment',
'some_env'
);
expect(newLogger.streams[1].stream).to.have.deep.property(
'client.release',
'some_release'
);
});
});
});