From aa2d0e70caf512dd4719e55243b11f7de40adfdf Mon Sep 17 00:00:00 2001
From: Juan Cruz Viotti <juanchiviotti@gmail.com>
Date: Fri, 21 Nov 2014 11:22:26 -0400
Subject: [PATCH] Implement log module

---
 lib/log/log.coffee      | 22 ++++++++++
 lib/log/log.spec.coffee | 93 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 lib/log/log.coffee
 create mode 100644 lib/log/log.spec.coffee

diff --git a/lib/log/log.coffee b/lib/log/log.coffee
new file mode 100644
index 00000000..0d700a30
--- /dev/null
+++ b/lib/log/log.coffee
@@ -0,0 +1,22 @@
+isQuiet = false
+
+exports.setQuiet = (quiet) ->
+	isQuiet = !!quiet
+
+exports.isQuiet = ->
+	return isQuiet
+
+# stderr
+exports.error = (args...) ->
+	console.error.apply(null, args)
+
+exports.warning = (args...) ->
+	console.warn.apply(null, args)
+
+# stdout
+exports.info = (args...) ->
+	return if exports.isQuiet()
+	console.info.apply(null, args)
+
+exports.out = (args...) ->
+	console.log.apply(null, args)
diff --git a/lib/log/log.spec.coffee b/lib/log/log.spec.coffee
new file mode 100644
index 00000000..46e2fad0
--- /dev/null
+++ b/lib/log/log.spec.coffee
@@ -0,0 +1,93 @@
+_ = require('lodash')
+chai = require('chai')
+chai.use(require('sinon-chai'))
+expect = chai.expect
+sinon = require('sinon')
+log = require('./log')
+
+MESSAGE =
+	foobar: 'Foo Bar'
+
+	# Very handy to check that the real console functions
+	# were called without printing anything, and preventing
+	# us from having to mock console, which is used by Mocha
+	empty: ''
+
+describe 'Log:', ->
+
+	testConsoleFunction = (logName, consoleName, message, assertions) ->
+		spy = sinon.spy(console, consoleName)
+		log[logName](message)
+		assertions(spy)
+		console[consoleName].restore()
+
+	testConsoleFunctionBeingCalled = (logName, consoleName, message) ->
+		testConsoleFunction logName, consoleName, message, (spy) ->
+			expect(spy).to.have.been.calledOnce
+			expect(spy).to.have.been.calledWith(message)
+
+	testConsoleFunctionNotBeingCalled = (logName, consoleName, message) ->
+		testConsoleFunction logName, consoleName, message, (spy) ->
+			expect(spy).to.not.have.been.called
+
+	describe 'if quiet is false', ->
+
+		beforeEach ->
+			log.setQuiet(false)
+
+		describe '#error()', ->
+
+			it 'should output to console.error', ->
+				testConsoleFunctionBeingCalled('error', 'error', MESSAGE.empty)
+
+		describe '#warning()', ->
+
+			it 'should output to console.warn', ->
+				testConsoleFunctionBeingCalled('warning', 'warn', MESSAGE.empty)
+
+		describe '#info()', ->
+
+			it 'should output to console.info', ->
+				testConsoleFunctionBeingCalled('info', 'info', MESSAGE.empty)
+
+		describe '#out()', ->
+
+			it 'should output to console.log', ->
+				testConsoleFunctionBeingCalled('out', 'log', MESSAGE.empty)
+
+		describe '#setQuiet()', ->
+
+			it 'should set the quietness', ->
+				expect(log.isQuiet()).to.be.false
+				log.setQuiet(true)
+				expect(log.isQuiet()).to.be.true
+
+		describe '#isQuiet()', ->
+
+			it 'should return false by default', ->
+				expect(log.isQuiet()).to.be.false
+
+	describe 'if quiet is true', ->
+
+		beforeEach ->
+			log.setQuiet(true)
+
+		describe '#error()', ->
+
+			it 'should still output to console.error', ->
+				testConsoleFunctionBeingCalled('error', 'error', MESSAGE.empty)
+
+		describe '#warning()', ->
+
+			it 'should still output to console.warn', ->
+				testConsoleFunctionBeingCalled('warning', 'warn', MESSAGE.empty)
+
+		describe '#info()', ->
+
+			it 'should not call console.info', ->
+				testConsoleFunctionNotBeingCalled('info', 'info', MESSAGE.empty)
+
+		describe '#out()', ->
+
+			it 'should not call console.log', ->
+				testConsoleFunctionBeingCalled('out', 'log', MESSAGE.empty)