Permalink
Browse files

[test] Added missing test for ignoring files

  • Loading branch information...
1 parent d417e27 commit c4f57ee4f2b983580937311a161c33e0d7dfb599 @3rd-Eden 3rd-Eden committed Dec 16, 2012
Showing with 205 additions and 65 deletions.
  1. +70 −65 lib/logger.js
  2. +135 −0 test/logger.test.js
View
@@ -100,20 +100,23 @@ var methods = {
var Logger = module.exports = function devnull(options) {
options = options || {};
- // default options
+ // Default options.
this.env = atty ? 'development' : 'production';
this.levels = levels;
this.level = options.level || Object.keys(this.levels).length;
this.notification = this.levels.warning;
this.namespacing = this.levels.debug;
- // output related options
+ // Output related options.
this.timestamp = true;
this.base = true;
this.pattern = '{FullYear}-{Month:2}-{Date:2} {toLocaleTimeString}';
- // override the defaults, but not the methods and they should also be the
- // exact same type
+ // Set the correct prefx.
+ this.prefix = methods[this.env];
+
+ // Override the defaults, but not the methods and they should also be the
+ // exact same type.
for (var key in options) {
if (key in this
&& type(this[key]) !== 'function'
@@ -123,8 +126,6 @@ var Logger = module.exports = function devnull(options) {
}
}
- // set the correct prefx
- this.prefix = methods[this.env];
this.transports = [];
this.calls = 0;
this.silence = {};
@@ -133,6 +134,34 @@ var Logger = module.exports = function devnull(options) {
if (this.base) {
this.use(require('../transports/stream'));
}
+
+ // Generate logging methods based on the allowed levels. This allows us to use
+ // a more readable syntax like: logger.info('hello world'); We are generating
+ // a new Function here so we reduce scope lookups and get a better call stack
+ // report. This should be done inside the constructor so we can also generate
+ // custom logging methods on the fly
+ Object.keys(this.levels).forEach(function levelr(level) {
+ var index = this.levels[level]
+ , capture = [
+ 'var stack, err, original;'
+ , 'if ('+ index +' > this.level) return this;'
+ , 'if ('+ index +' <= this.namespacing) {'
+ , ' original = Error.prepareStackTrace;'
+ , ' Error.prepareStackTrace = function (idontgiveafuck, trace) { return trace; };'
+ , ' err = new Error();'
+ , ' Error.captureStackTrace(err, arguments.callee);'
+ , ' stack = err.stack;'
+ , ' Error.prepareStackTrace = original;'
+ , '}'
+ , 'return this.write.apply(this, ['
+ , ' "'+ level +'"'
+ , ' , '+ index
+ , ' , stack'
+ , '].concat(Array.prototype.slice.call(arguments)));'
+ ];
+
+ this[level] = new Function(capture.join(''));
+ }.bind(this));
};
Logger.prototype.__proto__ = EventEmitter.prototype;
@@ -244,19 +273,19 @@ Logger.prototype.ignore = function ignore(file) {
* @api public
*/
Logger.prototype.unignore = function unignore(file) {
- if (file in this.silence) delete this.silence[file];
+ if (this.ignoring(file)) delete this.silence[file];
return this;
};
/**
- * Returns a list currently ignored files.
+ * Checks if the given file is ignored.
*
- * @returns {Array}
+ * @returns {Boolean}
* @api public
*/
-Logger.prototype.ignoring = function ignoring() {
- return Object.keys(this.silence);
+Logger.prototype.ignoring = function ignoring(file) {
+ return file in this.silence;
};
/**
@@ -268,7 +297,7 @@ Logger.prototype.ignoring = function ignoring() {
* @api public
*/
Logger.prototype.use = function use(Transport, options) {
- // prevent duplicates
+ // Prevent duplicates.
if (type(Transport) !== 'function') return this;
this.transports.push(new Transport(this, options || {}));
@@ -309,13 +338,13 @@ Logger.prototype.remove = function remove(Transport) {
var transport = this.has(Transport)
, i = this.transports.length;
- // cancel if we don't have a transport
+ // Cancel if we don't have a transport.
if (!transport) return this;
- // shutdown the transport
+ // Shutdown the transport.
transport.close();
- // and remove it
+ // And remove it.
while (i--) {
if (this.transports[i] === transport) {
this.transports.splice(i, 1);
@@ -331,7 +360,7 @@ Logger.prototype.remove = function remove(Transport) {
* @param {String} type log type
* @param {Number} level log level
* @returns {Logger}
- * @api public
+ * @api private
*/
Logger.prototype.write = function write(type, level, stack) {
var args = Array.prototype.slice.call(arguments).slice(3)
@@ -344,20 +373,26 @@ Logger.prototype.write = function write(type, level, stack) {
path = stack[0].getFileName();
filename = path.slice(path.lastIndexOf('/') + 1);
- // silence, silence! ssht!
- if (this.silence[filename]) return this;
+ // Silence, silence! ssht!.
+ if (this.silence[filename] || this.silence[path]) return this;
}
for (; i < length; i++) {
- this.transports[i].write(type, this.namespace(stack, args, filename), args);
+ this.transports[i].write(
+ type
+ , this.namespace(stack, args, filename)
+ , args
+ , filename
+ , stack
+ );
}
- // do we need to emit a event
+ // Do we need to emit a event
if (level <= this.notification && this.listeners(type).length) {
this.emit(type, args, stack);
}
- // increase our calls
+ // Increase our calls
++this.calls;
return this;
@@ -379,11 +414,11 @@ Logger.prototype.stamp = function stamp(date) {
return this.pattern.replace(
/\{(.+?)(?::(.*?))?\}/g
, function replace(res, method, padding) {
- for (res = now[method in now ? method : 'get' + method]() // exec the getter
- + (/h/.test(method) || '') // increment month by 1
- + ''; // cast to string
- res.length < padding; // while we need padding
- res = 0 + res // padd with zeros
+ for (res = now[method in now ? method : 'get' + method]() // Exec the getter
+ + (/h/.test(method) || '') // Increment month by 1
+ + ''; // Cast to string
+ res.length < padding; // While we need padding
+ res = 0 + res // Pad with zeros
);
return res;
@@ -463,17 +498,17 @@ Logger.prototype.namespace = function namespace(trace, args, filename) {
, one, two
, path = [filename];
- // try to detect if we received a user defined namespace argument or
- if (args.length > 1 // we should have multiple arguments
- && typeof arg === 'string' // first should be string
- && !~arg.indexOf(' ') // but not a sentance
- && !~arg.indexOf('%') // and not a formatting option
+ // Try to detect if we received a user defined namespace argument or
+ if (args.length > 1 // We should have multiple arguments
+ && typeof arg === 'string' // First should be string
+ && !~arg.indexOf(' ') // But not a sentance
+ && !~arg.indexOf('%') // And not a formatting option.
) {
path.push(args.shift());
return path;
}
- // generate a namespace from the called functions
+ // Generate a namespace from the called functions.
one = trace[0].getFunctionName() || trace[0].getMethodName();
if (one) {
@@ -485,41 +520,9 @@ Logger.prototype.namespace = function namespace(trace, args, filename) {
}
}
- // return the code path
return path;
};
-/**
- * Generate logging methods based on the allowed levels. This allows us to use
- * a more readable syntax like: logger.info('hello world'); We are generating
- * a new Function here so we reduce scope lookups and get a better call stack
- * report.
- *
- * @api private
- */
-Object.keys(levels).forEach(function levelr(level) {
- var index = levels[level]
- , capture = [
- 'var stack, err, original;'
- , 'if ('+ index +' > this.level) return this;'
- , 'if ('+ index +' <= this.namespacing) {'
- , ' original = Error.prepareStackTrace;'
- , ' Error.prepareStackTrace = function (idontgiveafuck, trace) { return trace; };'
- , ' err = new Error;'
- , ' Error.captureStackTrace(err, arguments.callee);'
- , ' stack = err.stack;'
- , ' Error.prepareStackTrace = original;'
- , '}'
- , 'return this.write.apply(this, ['
- , ' "'+ level +'"'
- , ' , '+ index
- , ' , stack'
- , '].concat(Array.prototype.slice.call(arguments)));'
- ];
-
- Logger.prototype[level] = new Function(capture.join(''));
-});
-
/**
* Start exporting some additional information like log levels etc. Most of the
* details is already exposed but we might as well, expose all the things.
@@ -531,7 +534,9 @@ Object.keys(levels).forEach(function levelr(level) {
* @type {String}
* @api public
*/
-Logger.version = '0.0.7';
+Logger.version = Logger.prototype.version = JSON.parse(
+ require('fs').readFileSync(__dirname + '/../package.json')
+).version;
/**
* Export the logging methods which are used to prefix the output.
View
@@ -584,4 +584,139 @@ describe('dev/null, logger', function () {
expect(logger.enabled('timestamp')).to.eql(false);
});
});
+
+ describe('#disabled', function () {
+ it('should be not be disabled', function () {
+ var logger = new Logger;
+
+ expect(logger.disabled('base')).to.eql(false);
+ expect(logger.disabled('timestamp')).to.eql(false);
+ });
+
+ it('should be disabled', function () {
+ var logger = new Logger;
+
+ logger.set('timestamp', false);
+ logger.set('base', false);
+
+ expect(logger.disabled('base')).to.eql(true);
+ expect(logger.disabled('timestamp')).to.eql(true);
+ });
+ });
+
+ describe('#ignore', function () {
+ it('should be chainable', function () {
+ var logger = new Logger;
+
+ expect(logger.ignore(__filename)).to.equal(logger);
+ });
+
+ it('should ignore the current file', function () {
+ var logger = new Logger({ notification: 10 })
+ , emits = 0;
+
+ logger.on('info', function () {
+ emits++;
+ });
+
+ // ensure that normal logs work
+ logger.info('foo');
+ expect(emits).to.equal(1);
+
+ logger.ignore(__filename);
+ logger.info('foo');
+
+ // should not increase as this log should be ignored
+ expect(emits).to.equal(1);
+ });
+ });
+
+ describe('#unignore', function () {
+ it('should be chainable', function () {
+ var logger = new Logger;
+
+ expect(logger.unignore(__filename)).to.equal(logger);
+ });
+
+ it('should unignore the current file', function () {
+ var logger = new Logger({ notification: 10 })
+ , emits = 0;
+
+ logger.on('info', function () {
+ emits++;
+ });
+
+ // ensure that normal logs work
+ logger.info('foo');
+ expect(emits).to.equal(1);
+
+ logger.ignore(__filename);
+ logger.info('foo');
+ expect(emits).to.equal(1);
+
+ // unignore, and it should increase the emit's again
+ logger.unignore(__filename);
+ logger.info('foo');
+ expect(emits).to.equal(2);
+ });
+ });
+
+ describe('#ignoring', function () {
+ it('should not be ignoring a random file', function () {
+ var logger = new Logger;
+
+ expect(logger.ignoring('adfaslfkjasd;lfjslf')).to.equal(false);
+ });
+
+ it('should be ignoring the current file', function () {
+ var logger = new Logger;
+
+ logger.ignore(__filename);
+ expect(logger.ignoring(__filename)).to.equal(true);
+ });
+
+ it('should not be ignoring the current file', function () {
+ var logger = new Logger;
+
+ logger.ignore(__filename);
+ expect(logger.ignoring(__filename)).to.equal(true);
+ logger.unignore(__filename);
+ expect(logger.ignoring(__filename)).to.equal(false);
+ });
+ });
+
+ describe('#format', function () {
+ it('should format strings', function () {
+ var logger = new Logger;
+
+ expect(logger.format('foo %s', 'bar')).to.equal('foo bar');
+ expect(logger.format('foo %s baz %s', 'bar', 'lol')).to.equal('foo bar baz lol');
+ expect(logger.format('foo %s', 1)).to.equal('foo 1');
+ });
+
+ it('should format json', function () {
+ var logger = new Logger;
+
+ var arr = [1, 2]
+ , obj = { foo: 'bar' }
+ , nest = { arr: arr };
+
+ expect(logger.format('hi %j', arr)).to.equal('hi ' + JSON.stringify(arr));
+ expect(logger.format('hi %j', obj)).to.equal('hi ' + JSON.stringify(obj));
+ expect(logger.format('hi %j', nest)).to.equal('hi ' + JSON.stringify(nest));
+ });
+
+ it('should format digits', function () {
+ var logger = new Logger;
+
+ expect(logger.format('%d + %d = %d', 1,2,3)).to.equal('1 + 2 = 3');
+ });
+
+ it('should escape %', function () {
+ var logger = new Logger;
+
+ expect(logger.format('wassup %')).to.equal('wassup %');
+ expect(logger.format('wassup %%')).to.equal('wassup %%');
+ });
+ });
});

0 comments on commit c4f57ee

Please sign in to comment.