1 /* jshint maxparams:7 */
3 var vows = require('vows')
4 , assert = require('assert')
5 , util = require('util')
6 , EE = require('events').EventEmitter
7 , levels = require('../lib/levels');
9 function MockLogger() {
14 this.log = function(level, message, exception) {
15 that.messages.push({ level: level, message: message });
18 this.isLevelEnabled = function(level) {
19 return level.isGreaterThanOrEqualTo(that.level);
22 this.level = levels.TRACE;
26 function MockRequest(remoteAddr, method, originalUrl, headers) {
28 this.socket = { remoteAddress: remoteAddr };
29 this.originalUrl = originalUrl;
31 this.httpVersionMajor = '5';
32 this.httpVersionMinor = '0';
33 this.headers = headers || {};
36 Object.keys(this.headers).forEach(function(key) {
37 self.headers[key.toLowerCase()] = self.headers[key];
41 function MockResponse() {
43 this.end = function(chunk, encoding) {
47 this.writeHead = function(code, headers) {
48 this.statusCode = code;
49 this._headers = headers;
53 util.inherits(MockResponse, EE);
55 function request(cl, method, url, code, reqHeaders, resHeaders) {
56 var req = new MockRequest('my.remote.addr', method, url, reqHeaders);
57 var res = new MockResponse();
58 cl(req, res, function() {});
59 res.writeHead(code, resHeaders);
60 res.end('chunk','encoding');
63 vows.describe('log4js connect logger').addBatch({
64 'getConnectLoggerModule': {
66 var clm = require('../lib/connect-logger');
70 'should return a "connect logger" factory' : function(clm) {
74 'take a log4js logger and return a "connect logger"' : {
75 topic: function(clm) {
76 var ml = new MockLogger();
77 var cl = clm.connectLogger(ml);
81 'should return a "connect logger"': function(cl) {
82 assert.isFunction(cl);
87 topic: function(clm) {
88 var ml = new MockLogger();
89 var cl = clm.connectLogger(ml);
90 var cb = this.callback;
91 request(cl, 'GET', 'http://url', 200);
92 setTimeout(function() {
93 cb(null, ml.messages);
97 'check message': function(messages) {
98 assert.isArray(messages);
99 assert.equal(messages.length, 1);
100 assert.ok(levels.INFO.isEqualTo(messages[0].level));
101 assert.include(messages[0].message, 'GET');
102 assert.include(messages[0].message, 'http://url');
103 assert.include(messages[0].message, 'my.remote.addr');
104 assert.include(messages[0].message, '200');
108 'log events with level below logging level' : {
109 topic: function(clm) {
110 var ml = new MockLogger();
111 ml.level = levels.FATAL;
112 var cl = clm.connectLogger(ml);
113 request(cl, 'GET', 'http://url', 200);
117 'check message': function(messages) {
118 assert.isArray(messages);
119 assert.isEmpty(messages);
123 'log events with non-default level and custom format' : {
124 topic: function(clm) {
125 var ml = new MockLogger();
126 var cb = this.callback;
127 ml.level = levels.INFO;
128 var cl = clm.connectLogger(ml, { level: levels.INFO, format: ':method :url' } );
129 request(cl, 'GET', 'http://url', 200);
130 setTimeout(function() {
131 cb(null, ml.messages);
134 'check message': function(messages) {
135 assert.isArray(messages);
136 assert.equal(messages.length, 1);
137 assert.ok(levels.INFO.isEqualTo(messages[0].level));
138 assert.equal(messages[0].message, 'GET http://url');
142 'logger with options as string': {
143 topic: function(clm) {
144 var ml = new MockLogger();
145 var cb = this.callback;
146 ml.level = levels.INFO;
147 var cl = clm.connectLogger(ml, ':method :url');
148 request(cl, 'POST', 'http://meh', 200);
149 setTimeout(function() {
150 cb(null, ml.messages);
153 'should use the passed in format': function(messages) {
154 assert.equal(messages[0].message, 'POST http://meh');
159 topic: function(clm) {
160 var ml = new MockLogger();
161 var cb = this.callback;
162 ml.level = levels.INFO;
163 var cl = clm.connectLogger(ml, { level: 'auto', format: ':method :url' });
164 request(cl, 'GET', 'http://meh', 200);
165 request(cl, 'GET', 'http://meh', 201);
166 request(cl, 'GET', 'http://meh', 302);
167 request(cl, 'GET', 'http://meh', 404);
168 request(cl, 'GET', 'http://meh', 500);
169 setTimeout(function() {
170 cb(null, ml.messages);
174 'should use INFO for 2xx': function(messages) {
175 assert.ok(levels.INFO.isEqualTo(messages[0].level));
176 assert.ok(levels.INFO.isEqualTo(messages[1].level));
179 'should use WARN for 3xx': function(messages) {
180 assert.ok(levels.WARN.isEqualTo(messages[2].level));
183 'should use ERROR for 4xx': function(messages) {
184 assert.ok(levels.ERROR.isEqualTo(messages[3].level));
187 'should use ERROR for 5xx': function(messages) {
188 assert.ok(levels.ERROR.isEqualTo(messages[4].level));
192 'format using a function': {
193 topic: function(clm) {
194 var ml = new MockLogger();
195 var cb = this.callback;
196 ml.level = levels.INFO;
197 var cl = clm.connectLogger(ml, function(req, res, formatFn) { return "I was called"; });
198 request(cl, 'GET', 'http://blah', 200);
199 setTimeout(function() {
200 cb(null, ml.messages);
204 'should call the format function': function(messages) {
205 assert.equal(messages[0].message, 'I was called');
209 'format that includes request headers': {
210 topic: function(clm) {
211 var ml = new MockLogger();
212 var cb = this.callback;
213 ml.level = levels.INFO;
214 var cl = clm.connectLogger(ml, ':req[Content-Type]');
217 'GET', 'http://blah', 200,
218 { 'Content-Type': 'application/json' }
220 setTimeout(function() {
221 cb(null, ml.messages);
224 'should output the request header': function(messages) {
225 assert.equal(messages[0].message, 'application/json');
229 'format that includes response headers': {
230 topic: function(clm) {
231 var ml = new MockLogger();
232 var cb = this.callback;
233 ml.level = levels.INFO;
234 var cl = clm.connectLogger(ml, ':res[Content-Type]');
237 'GET', 'http://blah', 200,
239 { 'Content-Type': 'application/cheese' }
241 setTimeout(function() {
242 cb(null, ml.messages);
246 'should output the response header': function(messages) {
247 assert.equal(messages[0].message, 'application/cheese');
251 'log events with custom token' : {
252 topic: function(clm) {
253 var ml = new MockLogger();
254 var cb = this.callback;
255 ml.level = levels.INFO;
256 var cl = clm.connectLogger(ml, {
258 format: ':method :url :custom_string',
260 token: ':custom_string', replacement: 'fooBAR'
263 request(cl, 'GET', 'http://url', 200);
264 setTimeout(function() {
265 cb(null, ml.messages);
269 'check message': function(messages) {
270 assert.isArray(messages);
271 assert.equal(messages.length, 1);
272 assert.ok(levels.INFO.isEqualTo(messages[0].level));
273 assert.equal(messages[0].message, 'GET http://url fooBAR');
277 'log events with custom override token' : {
278 topic: function(clm) {
279 var ml = new MockLogger();
280 var cb = this.callback;
281 ml.level = levels.INFO;
282 var cl = clm.connectLogger(ml, {
284 format: ':method :url :date',
286 token: ':date', replacement: "20150310"
289 request(cl, 'GET', 'http://url', 200);
290 setTimeout(function() {
291 cb(null, ml.messages);
295 'check message': function(messages) {
296 assert.isArray(messages);
297 assert.equal(messages.length, 1);
298 assert.ok(levels.INFO.isEqualTo(messages[0].level));
299 assert.equal(messages[0].message, 'GET http://url 20150310');