diff --git a/colorize.js b/colorize.js index 0186c6e..a053b39 100644 --- a/colorize.js +++ b/colorize.js @@ -65,6 +65,10 @@ class Colorizer { message = level; } + if (this.isColorDisabledByEnvVar()) { + return message; + } + // // If the color for the level is just a string // then attempt to colorize the message with it. @@ -104,6 +108,21 @@ class Colorizer { return info; } + + isColorDisabledByEnvVar() { + // eslint-disable-next-line no-process-env + const NO_COLOR = process.env.NO_COLOR; + /** + * If the environment variable NO_COLOR is truthy, the style of the output + * is automatically disabled. + */ + const COLOR_DISABLED = NO_COLOR && + NO_COLOR !== '0' && + NO_COLOR !== 'false' && + NO_COLOR !== 'undefined'; + + return COLOR_DISABLED; + } } /* diff --git a/test/cli.test.js b/test/cli.test.js index 734d892..ce6b1d7 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -14,6 +14,11 @@ const { LEVEL, MESSAGE } = require('triple-beam'); describe('cli', () => { before(setupLevels); + beforeEach(() => { + // eslint-disable-next-line no-process-env + process.env.NO_COLOR = undefined; + }); + it('cli() (default) sets info[MESSAGE]', assumeFormatted( cli(), infoify({ level: 'info', message: 'whatever' }), diff --git a/test/colorize.test.js b/test/colorize.test.js index 7cd046b..1874a89 100644 --- a/test/colorize.test.js +++ b/test/colorize.test.js @@ -1,3 +1,4 @@ +/* eslint-disable no-process-env */ 'use strict'; const assume = require('assume'); @@ -12,9 +13,14 @@ const { setupLevels } = require('./helpers'); +// eslint-disable-next-line max-statements describe('colorize', () => { before(setupLevels); + beforeEach(() => { + process.env.NO_COLOR = undefined; + }); + it('colorize() (default)', assumeFormatted( colorize(), infoify({ level: 'info', message: 'whatever' }), @@ -26,6 +32,20 @@ describe('colorize', () => { } )); + it('colorize() (default) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + colorize(), + infoify({ level: 'info', message: 'whatever' }), + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + } + ); + }); + it('colorize({ level: true })', assumeFormatted( colorize({ level: true }), infoify({ level: 'info', message: 'whatever' }), @@ -37,6 +57,20 @@ describe('colorize', () => { } )); + it('colorize({ level: true }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + colorize({ level: true }), + infoify({ level: 'info', message: 'whatever' }), + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + } + ); + }); + it('colorize{ message: true })', assumeFormatted( colorize({ message: true }), infoify({ level: 'info', message: 'whatever' }), @@ -48,6 +82,20 @@ describe('colorize', () => { } )); + it('colorize{ message: true }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + colorize({ message: true }), + infoify({ level: 'info', message: 'whatever' }), + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + } + ); + }); + it('colorize({ level: true, message: true })', assumeFormatted( colorize({ level: true, message: true }), infoify({ level: 'info', message: 'whatever' }), @@ -59,6 +107,20 @@ describe('colorize', () => { } )); + it('colorize({ level: true, message: true }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + colorize({ level: true, message: true }), + infoify({ level: 'info', message: 'whatever' }), + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + } + ); + }); + it('colorize({ all: true })', assumeFormatted( colorize({ all: true }), infoify({ level: 'info', message: 'whatever' }), @@ -70,6 +132,20 @@ describe('colorize', () => { } )); + it('colorize({ all: true }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + colorize({ all: true }), + infoify({ level: 'info', message: 'whatever' }), + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + } + ); + }); + it('colorize({ all: true }) [custom message]', assumeFormatted( colorize({ all: true }), { @@ -88,6 +164,27 @@ describe('colorize', () => { } )); + it('colorize({ all: true }) [custom message] when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + colorize({ all: true }), + { + level: 'info', + [LEVEL]: 'info', + message: 'whatever', + [MESSAGE]: '[info] whatever custom' + }, + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info[LEVEL]).equals('info'); + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + assume(info[MESSAGE]).equals('[info] whatever custom'); + } + ); + }); + it('colorizes when LEVEL !== level', assumeFormatted( colorize(), { [LEVEL]: 'info', level: 'INFO', message: 'whatever' }, @@ -97,6 +194,20 @@ describe('colorize', () => { assume(info.level).equals(colors.green('INFO')); } )); + + it('colorizes when LEVEL !== level when NO_COLOR is enabled', () => { + process.env.NO_COLOR = 'true'; + + assumeFormatted( + colorize(), + { [LEVEL]: 'info', level: 'INFO', message: 'whatever' }, + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + assume(info.level).equals('INFO'); + } + ); + }); }); describe('Colorizer', () => { @@ -117,19 +228,46 @@ describe('Colorizer', () => { ); }); + it('Colorizer.addColors({ string: string }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + Colorizer.addColors({ weird: 'cyan' }); + + assume(Colorizer.allColors).deep.equals( + Object.assign({}, expected, { weird: 'cyan' }) + ); + }); + it('Colorizer.addColors({ string: [Array] })', () => { Colorizer.addColors({ multiple: ['red', 'bold'] }); assume(Colorizer.allColors.multiple).is.an('array'); assume(Colorizer.allColors.multiple).deep.equals(['red', 'bold']); }); + it('Colorizer.addColors({ string: [Array] }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + Colorizer.addColors({ multiple: ['red', 'bold'] }); + assume(Colorizer.allColors.multiple).is.an('array'); + assume(Colorizer.allColors.multiple).deep.equals(['red', 'bold']); + }); + // eslint-disable-next-line no-useless-escape it('Colorizer.addColors({ string: "(\w+)/s(\w+)" })', () => { Colorizer.addColors({ delimited: 'blue underline' }); assume(Colorizer.allColors.delimited).deep.equals(['blue', 'underline']); }); + // eslint-disable-next-line no-useless-escape + it('Colorizer.addColors({ string: "(\w+)/s(\w+)" }) when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + Colorizer.addColors({ delimited: 'blue underline' }); + assume(Colorizer.allColors.delimited).deep.equals(['blue', 'underline']); + }); + describe('#colorize(LEVEL, level, message)', () => { + beforeEach(() => { + process.env.NO_COLOR = undefined; + }); + const instance = new Colorizer(); it('colorize(level) [single color]', () => { @@ -152,4 +290,32 @@ describe('Colorizer', () => { ); }); }); + + describe('#colorize(LEVEL, level, message) when NO_COLOR env var is enabled', () => { + beforeEach(() => { + process.env.NO_COLOR = 'true'; + }); + + const instance = new Colorizer(); + + it('colorize(level) [single color]', () => { + assume(instance.colorize('weird', 'weird')).equals('weird'); + }); + + it('colorize(level) [multiple colors]', () => { + assume(instance.colorize('multiple', 'multiple')).equals( + 'multiple' + ); + }); + + it('colorize(level, message) [single color]', () => { + assume(instance.colorize('weird', 'weird', 'message')).equals('message'); + }); + + it('colorize(level, message) [multiple colors]', () => { + assume(instance.colorize('multiple', 'multiple', 'message')).equals( + 'message' + ); + }); + }); }); diff --git a/test/uncolorize.test.js b/test/uncolorize.test.js index 52da897..206b33f 100644 --- a/test/uncolorize.test.js +++ b/test/uncolorize.test.js @@ -1,3 +1,4 @@ +/* eslint-disable no-process-env */ 'use strict'; const assume = require('assume'); @@ -42,6 +43,10 @@ function addAndRemoveColors(opts = {}) { describe('uncolorize', () => { before(setupLevels); + beforeEach(() => { + process.env.NO_COLOR = undefined; + }); + it('uncolorize() (default) removes all colors', assumeFormatted( addAndRemoveColors(), infoify({ level: 'info', message: 'whatever' }), @@ -83,6 +88,29 @@ describe('uncolorize', () => { } )); + it('same uncolorize() (default) preserves mutable level formatting when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + + assumeFormatted( + combine( + format(info => { + info.level = info.level.toUpperCase(); + return info; + })(), + colorize(), + uncolorize() + ), + { [LEVEL]: 'info', level: 'info', message: 'whatever' }, + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + + assume(info.level).equals('INFO'); + assume(info.message).equals('whatever'); + } + ); + }); + it('uncolorize() not crashing with Symbol()', assumeFormatted( combine( format(info => { @@ -115,6 +143,23 @@ describe('uncolorize', () => { } )); + it( + 'same uncolorize({ level: false }) removes color from { message, [MESSAGE] } when NO_COLOR env var is enabled', () => { + process.env.NO_COLOR = 'true'; + assumeFormatted( + addAndRemoveColors({ level: false }, true), + infoify({ level: 'info', message: 'whatever' }), + info => { + assume(info.level).is.a('string'); + assume(info.message).is.a('string'); + + assume(info.level).equals('info'); + assume(info.message).equals('whatever'); + assume(info[MESSAGE]).equals('info: whatever'); + } + ); + }); + it('uncolorize({ message: false }) removes color from { level, [MESSAGE] }', assumeFormatted( addAndRemoveColors({ message: false }), infoify({ level: 'info', message: 'whatever' }), @@ -147,7 +192,6 @@ describe('uncolorize', () => { info => { assume(info.level).is.a('string'); assume(info.message).is.a('string'); - assume(info.level).equals(colors.green('info')); assume(info.message).equals(colors.green('whatever')); assume(info[MESSAGE]).equals('info: whatever');