winston-middleware 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/test/test.js CHANGED
@@ -1,384 +1,660 @@
1
- var vows = require('vows');
2
- var assert = require('assert');
3
- var winston = require('winston');
4
- var expressWinston = require('../index');
1
+ var should = require('should');
5
2
  var util = require('util');
6
- var events = require('events');
3
+ var _ = require('underscore');
4
+
5
+ var mocks = require('node-mocks-http');
6
+ var winston = require('winston');
7
+
8
+ var expressWinston = require('../index.js');
9
+
10
+ expressWinston.ignoredRoutes.push('/ignored');
11
+ expressWinston.responseWhitelist.push('body');
12
+
13
+ expressWinston.bodyBlacklist.push('potato');
14
+
15
+ var MockTransport = function (test, options) {
16
+ test.transportInvoked = false;
7
17
 
8
- var MockTransport = function(options) {
9
- winston.Transport.call(this, options);
18
+ winston.Transport.call(this, options || {});
19
+
20
+ this.log = function (level, msg, meta, cb) {
21
+ test.transportInvoked = true;
22
+ test.log.level = level;
23
+ test.log.msg = msg;
24
+ test.log.meta = meta;
25
+ this.emit('logged');
26
+ return cb();
27
+ };
10
28
  };
11
29
  util.inherits(MockTransport, winston.Transport);
12
30
 
13
- vows.describe("exports").addBatch({
14
- "When I check the exported properties": {
15
- topic: function() {
16
- return expressWinston;
17
- },
18
- "an array with all the properties whitelisted in the req object": function(exports) {
19
- assert.isArray(exports.requestWhitelist);
20
- },
21
- "an array with all the properties whitelisted in the res object": function(exports) {
22
- assert.isArray(exports.responseWhitelist);
23
- },
24
- "an array with all the properties whitelisted in the body object": function(exports) {
25
- assert.isArray(exports.bodyWhitelist);
26
- },
27
- "and the factory should contain a default request filter function": function(exports) {
28
- assert.isFunction(exports.defaultRequestFilter);
31
+ var req = {};
32
+ var res = {};
33
+
34
+ var setUp = function (options) {
35
+ options = options || {};
36
+
37
+ var reqSpec = {
38
+ method: 'GET',
39
+ url: '/hello',
40
+ headers: {
41
+ 'header-1': 'value 1'
29
42
  },
30
- "and the factory should contain a default response filter function": function(exports) {
31
- assert.isFunction(exports.defaultResponseFilter);
43
+ query: {
44
+ val: '1'
32
45
  },
33
- "it should export a function for the creation of error loggers middlewares": function(exports) {
34
- assert.isFunction(exports.errorLogger);
46
+ params: {
47
+ id: 20
35
48
  },
36
- "it should export a function for the creation of request logger middlewares": function(exports) {
37
- assert.isFunction(exports.logger);
49
+ };
50
+
51
+ if (options.body) reqSpec.body = options.body;
52
+
53
+ if (options.ignoreRoute) reqSpec.url = '/ignored';
54
+ if (options.url) reqSpec.url = options.url;
55
+
56
+ req = mocks.createRequest(reqSpec);
57
+
58
+ req.route = {
59
+ path: reqSpec.url,
60
+ methods: {
61
+ get: true
38
62
  }
39
- }
40
- }).export(module);
63
+ };
41
64
 
42
- vows.describe("errorLogger").addBatch({
43
- "when I run the middleware factory": {
44
- topic: function() {
45
- return expressWinston.errorLogger;
46
- },
47
- "without options": {
48
- "an error should be raised": function(factory) {
49
- assert.throws(function() {
50
- factory();
51
- }, Error);
52
- }
53
- },
54
- "without any transport specified": {
55
- "an error should be raised": function(factory) {
56
- assert.throws(function() {
57
- factory({});
58
- }, Error);
59
- }
60
- },
61
- "with an empty list of transports": {
62
- "an error should be raised": function(factory) {
63
- assert.throws(function() {
64
- factory({transports:[]});
65
- }, Error);
66
- }
67
- },
68
- "with proper options": {
69
- "the result should be a function with four arguments that fit err, req, res, next": function (factory) {
70
- var middleware = factory({
71
- transports: [
72
- new MockTransport({
73
-
74
- })
75
- ]
65
+ if (options.routePath) req.route.path = options.routePath;
66
+
67
+ res = mocks.createResponse();
68
+ res.status(200);
69
+ };
70
+
71
+ describe('expressWinston', function () {
72
+ it('should contain an array with all the properties whitelisted in the req object', function () {
73
+ expressWinston.requestWhitelist.should.be.an.Array;
74
+ });
75
+
76
+ it('should contain an array with all the properties whitelisted in the res object', function () {
77
+ expressWinston.responseWhitelist.should.be.an.Array;
78
+ });
79
+
80
+ it('should contain an array for all the ignored routes', function () {
81
+ expressWinston.ignoredRoutes.should.be.an.Array;
82
+ });
83
+
84
+ it('should contain an array with all the properties whitelisted in the body object', function () {
85
+ expressWinston.bodyWhitelist.should.be.an.Array;
86
+ });
87
+
88
+ it('should contain a default request filter function', function () {
89
+ expressWinston.defaultRequestFilter.should.be.a.Function;
90
+ });
91
+
92
+ it('should contain a default response filter function', function () {
93
+ expressWinston.defaultResponseFilter.should.be.a.Function;
94
+ });
95
+
96
+ it('should contain a default skip function', function () {
97
+ expressWinston.defaultSkip.should.be.a.Function;
98
+ });
99
+
100
+ it('should export a function for the creation of request logger middlewares', function () {
101
+ expressWinston.logger.should.be.a.Function;
102
+ });
103
+
104
+ describe('.errorLogger()', function () {
105
+ it('should be a function', function () {
106
+ expressWinston.errorLogger.should.be.a.Function;
107
+ });
108
+
109
+ it('should throw an error without options', function () {
110
+ (function () {
111
+ expressWinston.errorLogger();
112
+ }).should.throwError();
113
+ });
114
+
115
+ it('should throw an error without any transport specified', function () {
116
+ (function () {
117
+ expressWinston.errorLogger({});
118
+ }).should.throwError();
119
+ });
120
+
121
+ it('should throw an error with an empty list of transports', function () {
122
+ (function () {
123
+ expressWinston.errorLogger({
124
+ transports: []
76
125
  });
77
- assert.equal(middleware.length, 4);
78
- }
79
- }
80
- },
81
- "When the winston-middleware middleware encounter an error in the pipeline": {
82
- topic: function() {
83
- var factory = expressWinston.errorLogger;
84
- var callback = this.callback;
85
- var req = {
86
- url: "/hello?val=1",
87
- headers: {
88
- 'header-1': 'value 1'
89
- },
90
- method: 'GET',
91
- query: {
92
- val: '1'
93
- },
94
- originalUrl: "/hello?val=1",
95
- params: {
96
- id: 20
97
- },
98
- nonWhitelistedProperty: "value that should not be logged"
99
- };
100
- var res = {
101
-
102
- };
103
- var originalError = new Error("This is the Error");
104
- var test = {
105
- req: req,
106
- res: res,
107
- log: {},
108
- originalError: originalError,
109
- pipelineError: null
110
- };
111
- var next = function(pipelineError) {
112
- test.pipelineError = pipelineError;
113
- return callback(null, test);
114
- };
115
-
116
- var transport = new MockTransport({});
117
- transport.log = function(level, msg, meta, cb) {
118
- test.transportInvoked = true;
119
- test.log.level = level;
120
- test.log.msg = msg;
121
- test.log.meta = meta;
122
- this.emit('logged');
123
- return cb();
124
- };
125
- var middleware = factory({
126
- transports: [transport]
126
+ }).should.throwError();
127
+ });
128
+
129
+ it('should return a middleware function with four arguments that fit (err, req, res, next)', function () {
130
+ var middleware = expressWinston.errorLogger({
131
+ transports: [new MockTransport({})]
127
132
  });
128
- middleware(originalError, req, res, next);
129
- }
130
- , "then the transport should be invoked": function(result){
131
- assert.isTrue(result.transportInvoked);
132
- }
133
- , "the error level should be error": function(result){
134
- assert.equal(result.log.level, "error");
135
- }
136
- , "the msg should be middlewareError": function(result){
137
- assert.equal(result.log.msg, "middlewareError");
138
- }
139
- , "the meta should contain a filtered request": function(result){
140
- assert.isTrue(!!result.log.meta.req, "req should be defined in meta");
141
- assert.isNotNull(result.log.meta.req);
142
- assert.equal(result.log.meta.req.method, "GET");
143
- assert.deepEqual(result.log.meta.req.query, {
144
- val: '1'
133
+
134
+ middleware.length.should.eql(4);
135
+ });
136
+
137
+ describe('errorLogger() middleware()', function () {
138
+ var result;
139
+
140
+ before(function (done) {
141
+ setUp();
142
+
143
+ var originalError = new Error('This is the Error');
144
+
145
+ var test = {
146
+ req: req,
147
+ res: res,
148
+ log: {},
149
+ originalError: originalError,
150
+ pipelineError: null
151
+ };
152
+
153
+ function next(pipelineError) {
154
+ test.pipelineError = pipelineError;
155
+
156
+ result = test;
157
+
158
+ return done();
159
+ };
160
+
161
+ var middleware = expressWinston.errorLogger({
162
+ transports: [new MockTransport(test)]
163
+ });
164
+
165
+ middleware(originalError, req, res, next);
145
166
  });
146
- assert.isUndefined(result.log.meta.req.nonWhitelistedProperty);
147
- },
148
- "the winston-middleware middleware should not swallow the pipeline error": function(result) {
149
- assert.isNotNull(result.pipelineError);
150
- assert.strictEqual(result.pipelineError, result.originalError);
151
- }
152
- }
153
- }).export(module);
154
167
 
155
- vows.describe("logger 0.1.x").addBatch({
156
- "when I run the middleware factory": {
157
- topic: function() {
158
- return expressWinston.logger;
159
- },
160
- "without options": {
161
- "an error should be raised": function(factory) {
162
- assert.throws(function() {
163
- factory();
164
- }, Error);
165
- }
166
- },
167
- "without any transport specified": {
168
- "an error should be raised": function(factory) {
169
- assert.throws(function() {
170
- factory({});
171
- }, Error);
172
- }
173
- },
174
- "with an empty list of transports": {
175
- "an error should be raised": function(factory) {
176
- assert.throws(function() {
177
- factory({transports:[]});
178
- }, Error);
179
- }
180
- },
181
- "with proper options": {
182
- "the result should be a function with three arguments that fit req, res, next": function (factory) {
183
- var middleware = factory({
184
- transports: [
185
- new MockTransport({
186
-
187
- })
188
- ]
168
+ describe('encountering an error in the pipeline', function () {
169
+ it('should invoke the transport', function () {
170
+ result.transportInvoked.should.eql(true);
171
+ });
172
+
173
+ it('should find an error level of "error"', function () {
174
+ result.log.level.should.eql('error');
175
+ });
176
+
177
+ it('should find a message of "middlewareError"', function () {
178
+ result.log.msg.should.eql('middlewareError');
179
+ });
180
+
181
+ it('should contain a filtered request', function () {
182
+ result.log.meta.req.should.be.ok;
183
+ result.log.meta.req.method.should.eql('GET');
184
+ result.log.meta.req.query.should.eql({
185
+ val: '1'
186
+ });
187
+
188
+ result.log.meta.req.should.not.have.property('nonWhitelistedProperty');
189
+ });
190
+
191
+ it('should not swallow the pipline error', function () {
192
+ result.pipelineError.should.be.ok;
193
+ result.pipelineError.should.eql(result.originalError);
189
194
  });
190
- assert.equal(middleware.length, 3);
191
- }
192
- }
193
- },
194
- "When the winston-middleware middleware is invoked in pipeline": {
195
- topic: function() {
196
- var factory = expressWinston.logger;
197
- var callback = this.callback;
198
- var req = {
199
- url: "/hello?val=1",
200
- headers: {
201
- 'header-1': 'value 1'
202
- },
203
- method: 'GET',
204
- query: {
205
- val: '2'
206
- },
207
- originalUrl: "/hello?val=2",
208
- params: {
209
- id: 20
210
- },
211
- filteredProperty: "value that should not be logged"
212
- };
213
- var res = {
214
- end: function(chunk, encoding) {}
215
- };
216
- var test = {
217
- req: req,
218
- res: res,
219
- log: {}
220
- };
221
- var next = function(_req, _res, next) {
222
- res.end();
223
- return callback(null, test);
224
- };
225
-
226
- var transport = new MockTransport({});
227
- transport.log = function(level, msg, meta, cb) {
228
- test.transportInvoked = true;
229
- test.log.level = level;
230
- test.log.msg = msg;
231
- test.log.meta = meta;
232
- this.emit('logged');
233
- return cb();
234
- };
235
- var middleware = factory({
236
- transports: [transport]
237
195
  });
238
- middleware(req, res, next);
239
- }
240
- , "then the transport should be invoked": function(result){
241
- assert.isTrue(result.transportInvoked);
242
- }
243
- , "the meta should contain a filtered request": function(result){
244
- assert.isTrue(!!result.log.meta.req, "req should be defined in meta");
245
- assert.isNotNull(result.log.meta.req);
246
- assert.equal(result.log.meta.req.method, "GET");
247
- assert.deepEqual(result.log.meta.req.query, {
248
- val: '2'
196
+ });
197
+ });
198
+
199
+ describe('.logger()', function () {
200
+ it('should be a function', function () {
201
+ expressWinston.logger.should.be.a.Function;
202
+ });
203
+
204
+ it('should throw an error without options', function () {
205
+ (function () {
206
+ expressWinston.logger();
207
+ }).should.throwError();
208
+ });
209
+
210
+ it('should throw an error without any transport specified', function () {
211
+ (function () {
212
+ expressWinston.logger({});
213
+ }).should.throwError();
214
+ });
215
+
216
+ it('should throw an error with an empty list of transports', function () {
217
+ (function () {
218
+ expressWinston.logger({
219
+ transports: []
220
+ });
221
+ }).should.throwError();
222
+ });
223
+
224
+ it('should throw an error if ignoreRoute option is not a function', function () {
225
+ (function () {
226
+ expressWinston.logger({
227
+ transports: [new MockTransport({})],
228
+ ignoreRoute: 'not a function'
229
+ });
230
+ }).should.throwError();
231
+ });
232
+
233
+ it('should return a middleware function with three arguments that fit (req, res, next)', function () {
234
+ var middleware = expressWinston.logger({
235
+ transports: [new MockTransport({})]
249
236
  });
250
- assert.isUndefined(result.log.meta.req.filteredProperty);
251
- }
252
- }
253
- }).export(module);
254
237
 
255
- vows.describe("logger 0.2.x").addBatch({
256
- "when I run the middleware factory": {
257
- topic: function() {
258
- return expressWinston.logger;
259
- },
260
- "without options": {
261
- "an error should be raised": function(factory) {
262
- assert.throws(function() {
263
- factory();
264
- }, Error);
265
- }
266
- },
267
- "without any transport specified": {
268
- "an error should be raised": function(factory) {
269
- assert.throws(function() {
270
- factory({});
271
- }, Error);
272
- }
273
- },
274
- "with an empty list of transports": {
275
- "an error should be raised": function(factory) {
276
- assert.throws(function() {
277
- factory({transports:[]});
278
- }, Error);
279
- }
280
- },
281
- "with proper options": {
282
- "the result should be a function with three arguments that fit req, res, next": function (factory) {
283
- var middleware = factory({
284
- transports: [
285
- new MockTransport({
286
-
287
- })
288
- ]
238
+ middleware.length.should.eql(3);
239
+ });
240
+
241
+ describe('logger() middleware()', function () {
242
+ describe('v0.1.x API', function () {
243
+ describe('when invoked on a route', function () {
244
+ var result;
245
+
246
+ before(function (done) {
247
+ setUp();
248
+
249
+ var test = {
250
+ req: req,
251
+ res: res,
252
+ log: {}
253
+ };
254
+
255
+ function next(_req, _res, next) {
256
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
257
+ result = test;
258
+ return done();
259
+ };
260
+
261
+ var middleware = expressWinston.logger({
262
+ transports: [new MockTransport(test)]
263
+ });
264
+
265
+ middleware(req, res, next);
266
+ });
267
+
268
+ it('should invoke the transport', function () {
269
+ result.transportInvoked.should.eql(true);
270
+ });
271
+
272
+ it('should contain a filtered request', function () {
273
+ result.log.meta.req.should.be.ok;
274
+ result.log.meta.req.method.should.eql('GET');
275
+ result.log.meta.req.query.should.eql({
276
+ val: '1'
277
+ });
278
+
279
+ result.log.meta.req.should.not.have.property('nonWhitelistedProperty');
280
+ });
289
281
  });
290
- assert.equal(middleware.length, 3);
291
- }
292
- }
293
- },
294
- "When the winston-middleware middleware is invoked in pipeline": {
295
- topic: function() {
296
- var factory = expressWinston.logger;
297
- var callback = this.callback;
298
- var req = {
299
- url: "/hello?val=1",
300
- headers: {
301
- 'header-1': 'value 1'
302
- },
303
- method: 'GET',
304
- query: {
305
- val: '2'
306
- },
307
- originalUrl: "/hello?val=2",
308
- params: {
309
- id: 20
310
- },
311
- nonWhitelistedProperty: "value that should not be logged",
312
- routeLevelAddedProperty: "value that should be logged",
313
- body: {
314
- username: 'bobby',
315
- password: 'top-secret'
282
+
283
+ describe('when invoked on a route that should be ignored', function () {
284
+ var result;
285
+
286
+ before(function (done) {
287
+ setUp({
288
+ ignoreRoute: true
289
+ });
290
+
291
+ var test = {
292
+ req: req,
293
+ res: res,
294
+ log: {}
295
+ };
296
+
297
+ function next(_req, _res, next) {
298
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
299
+ result = test;
300
+ return done();
301
+ };
302
+
303
+ var middleware = expressWinston.logger({
304
+ transports: [new MockTransport(test)]
305
+ });
306
+
307
+ middleware(req, res, next);
308
+ });
309
+
310
+ it('should not invoke the transport', function () {
311
+ result.transportInvoked.should.eql(false);
312
+ });
313
+
314
+ it('should contain a filtered request', function () {
315
+ result.log.should.be.empty;
316
+ });
317
+ });
318
+ });
319
+
320
+ describe('v0.2.x API', function () {
321
+ describe('when invoked on a route', function () {
322
+ var result;
323
+
324
+ before(function (done) {
325
+ setUp({
326
+ body: {
327
+ username: "bobby",
328
+ password: "top-secret",
329
+ age: 42,
330
+ potato: 'Russet'
331
+ }
332
+ });
333
+
334
+ req.routeLevelAddedProperty = 'value that should be logged';
335
+
336
+ res.nonWhitelistedProperty = 'value that should not be logged';
337
+ res.routeLevelAddedProperty = 'value that should be logged';
338
+
339
+ var test = {
340
+ req: req,
341
+ res: res,
342
+ log: {}
343
+ };
344
+
345
+ function next(_req, _res, next) {
346
+ req._startTime = (new Date) - 125;
347
+
348
+ req._routeWhitelists.req = ['routeLevelAddedProperty'];
349
+ req._routeWhitelists.res = ['routeLevelAddedProperty'];
350
+
351
+ req._routeWhitelists.body = ['username'];
352
+ req._routeBlacklists.body = ['age'];
353
+
354
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
355
+
356
+ result = test;
357
+
358
+ return done();
359
+ };
360
+
361
+ var middleware = expressWinston.logger({
362
+ transports: [new MockTransport(test)]
363
+ });
364
+
365
+ middleware(req, res, next);
366
+ });
367
+
368
+ it('should invoke the transport', function () {
369
+ result.transportInvoked.should.eql(true);
370
+ });
371
+
372
+ it('should contain a filtered request', function () {
373
+ result.log.meta.req.should.be.ok;
374
+ result.log.meta.req.method.should.eql('GET');
375
+ result.log.meta.req.query.should.eql({
376
+ val: '1'
377
+ });
378
+
379
+ result.log.meta.req.body.should.not.have.property('age');
380
+ result.log.meta.req.body.should.not.have.property('potato');
381
+ });
382
+
383
+ it('should contain a filtered response', function () {
384
+ result.log.meta.res.should.be.ok;
385
+
386
+ result.log.meta.res.statusCode.should.eql(200);
387
+ result.log.meta.res.routeLevelAddedProperty.should.be.ok;
388
+
389
+ result.log.meta.res.should.not.have.property('nonWhitelistedProperty');
390
+ });
391
+
392
+ it('should contain a response time', function () {
393
+ result.log.meta.responseTime.should.be.within(120, 130);
394
+ });
395
+ });
396
+
397
+ describe('when invoked on a route with an empty response body', function () {
398
+ var result;
399
+
400
+ before(function (done) {
401
+ setUp({
402
+ url: '/hello',
403
+ body: {}
404
+ });
405
+
406
+ req.routeLevelAddedProperty = 'value that should be logged';
407
+
408
+ var test = {
409
+ req: req,
410
+ res: res,
411
+ log: {}
412
+ };
413
+
414
+ function next(_req, _res, next) {
415
+ res.end();
416
+
417
+ result = test;
418
+
419
+ return done();
420
+ };
421
+
422
+ var middleware = expressWinston.logger({
423
+ transports: [new MockTransport(test)]
424
+ });
425
+
426
+ middleware(req, res, next);
427
+ });
428
+
429
+ it('should not have an empty body in meta.req', function () {
430
+ result.log.meta.res.should.not.have.property('body');
431
+ });
432
+ });
433
+
434
+ describe('when invoked on a route with transport level of "error"', function () {
435
+ var result;
436
+
437
+ before(function (done) {
438
+ setUp({
439
+ url: "/hello",
440
+ body: {}
441
+ });
442
+
443
+ req.routeLevelAddedProperty = 'value that should be logged';
444
+
445
+ res.nonWhitelistedProperty = 'value that should not be logged';
446
+ res.routeLevelAddedProperty = 'value that should be logged';
447
+
448
+ var test = {
449
+ req: req,
450
+ res: res,
451
+ log: {}
452
+ };
453
+
454
+ function next(_req, _res, next) {
455
+ req._routeWhitelists.req = ['routeLevelAddedProperty'];
456
+ req._routeWhitelists.res = ['routeLevelAddedProperty'];
457
+
458
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
459
+ result = test;
460
+ return done();
461
+ };
462
+
463
+ var middleware = expressWinston.logger({
464
+ transports: [new MockTransport(test, {
465
+ level: 'error'
466
+ })],
467
+ statusLevels: true
468
+ });
469
+
470
+ middleware(req, res, next);
471
+ });
472
+
473
+ it('should not invoke the transport', function () {
474
+ result.transportInvoked.should.eql(false);
475
+ });
476
+ });
477
+
478
+ describe('when invoked on a route that should be ignored (options.ignoreRoute)', function () {
479
+ var result;
480
+
481
+ before(function (done) {
482
+ setUp({
483
+ url: '/is-not-logged'
484
+ });
485
+ req.skip = true;
486
+ var test = {
487
+ req: req,
488
+ res: res,
489
+ log: {}
490
+ };
491
+
492
+ function next(_req, _res, next) {
493
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
494
+ result = test;
495
+ return done();
496
+ };
497
+
498
+ var middleware = expressWinston.logger({
499
+ transports: [new MockTransport(test)],
500
+ ignoreRoute: function (req, res) {
501
+ return req.skip === true && req.url.match(/^\/is-not-log/);
502
+ }
503
+ });
504
+
505
+ middleware(req, res, next);
506
+ });
507
+
508
+ it('should not invoke the transport', function () {
509
+ result.transportInvoked.should.eql(false);
510
+ });
511
+
512
+ it('should contain a filtered request', function () {
513
+ result.log.should.be.empty;
514
+ });
515
+ });
516
+ });
517
+
518
+ describe('log.msg', function () {
519
+ var result;
520
+
521
+ function logMsgSetup(url, msg, expressFormat, done) {
522
+ setUp({
523
+ url: url || '/an-url'
524
+ });
525
+
526
+ var test = {
527
+ req: req,
528
+ res: res,
529
+ log: {}
530
+ };
531
+
532
+ function next(_req, _res, next) {
533
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
534
+
535
+ result = test;
536
+
537
+ return done();
538
+ };
539
+
540
+ var loggerOptions = {
541
+ transports: [new MockTransport(test)]
542
+ };
543
+
544
+ if (msg) {
545
+ loggerOptions.msg = msg;
546
+ }
547
+
548
+ if (expressFormat) {
549
+ delete loggerOptions.msg;
550
+ loggerOptions.expressFormat = true;
551
+ }
552
+
553
+ var middleware = expressWinston.logger(loggerOptions);
554
+
555
+ middleware(req, res, next);
316
556
  }
317
- };
318
- var res = {
319
- statusCode: 200,
320
- nonWhitelistedProperty: "value that should not be logged",
321
- routeLevelAddedProperty: "value that should be logged",
322
- end: function(chunk, encoding) {
323
557
 
558
+ describe('when default', function () {
559
+
560
+ before(function (done) {
561
+ logMsgSetup('/url-of-sandwich', null, false, done);
562
+ });
563
+
564
+ it('should match the custom format', function () {
565
+ result.log.msg.should.eql('HTTP GET /url-of-sandwich');
566
+ });
567
+ });
568
+
569
+ describe('using Express format', function () {
570
+ before(function (done) {
571
+ logMsgSetup('/all-the-things', null, true, done);
572
+ });
573
+
574
+ it('should match the Express format', function () {
575
+ var resultMsg = result.log.msg;
576
+ resultMsg.should.startWith('\u001b[90mGET /all-the-things\u001b[39m \u001b[32m200\u001b[39m \u001b[90m');
577
+ resultMsg.should.endWith('ms\u001b[39m');
578
+ });
579
+ });
580
+
581
+ describe('when customized', function () {
582
+ before(function (done) {
583
+ logMsgSetup('/all-the-things', 'Foo {{ req.method }} {{ req.url }}', false, done);
584
+ });
585
+
586
+ it('should match the custom format', function () {
587
+ result.log.msg.should.eql('Foo GET /all-the-things');
588
+ });
589
+ });
590
+ });
591
+
592
+ describe('log.skip', function () {
593
+ var result;
594
+
595
+ function logSkipSetup(url, skip, done) {
596
+ setUp({
597
+ url: url || '/an-url'
598
+ });
599
+
600
+ var test = {
601
+ req: req,
602
+ res: res,
603
+ log: {}
604
+ };
605
+
606
+ function next(_req, _res, next) {
607
+ res.end('{ "message": "Hi! I\'m a chunk!" }');
608
+
609
+ result = test;
610
+
611
+ return done();
612
+ };
613
+
614
+ var loggerOptions = {
615
+ transports: [new MockTransport(test)]
616
+ };
617
+
618
+ if (skip) {
619
+ loggerOptions.skip = skip;
620
+ }
621
+
622
+ var middleware = expressWinston.logger(loggerOptions);
623
+
624
+ middleware(req, res, next);
324
625
  }
325
- };
326
- var test = {
327
- req: req,
328
- res: res,
329
- log: {}
330
- };
331
- var next = function(_req, _res, next) {
332
- req._startTime = (new Date) - 125;
333
-
334
- req._routeWhitelists.req = [ 'routeLevelAddedProperty' ];
335
- req._routeWhitelists.body = [ 'username' ];
336
-
337
- res.end();
338
- return callback(null, test);
339
- };
340
-
341
- var transport = new MockTransport({});
342
- transport.log = function(level, msg, meta, cb) {
343
- test.transportInvoked = true;
344
- test.log.level = level;
345
- test.log.msg = msg;
346
- test.log.meta = meta;
347
- this.emit('logged');
348
- return cb();
349
- };
350
- var middleware = factory({
351
- transports: [transport]
626
+
627
+ describe('when default', function () {
628
+
629
+ before(function (done) {
630
+ logSkipSetup('/url-of-sandwich', null, done);
631
+ });
632
+
633
+ it('should be logged', function () {
634
+ result.log.msg.should.eql('HTTP GET /url-of-sandwich');
635
+ });
636
+ });
637
+
638
+ describe('when using custom function returning true', function () {
639
+ before(function (done) {
640
+ logSkipSetup('/url-of-sandwich', function(req, res) { return req.url.indexOf('sandwich') != -1 }, done);
641
+ });
642
+
643
+ it('should not be logged', function () {
644
+ should.not.exist(result.log.msg);
645
+ });
646
+ });
647
+
648
+ describe('when using custom function returning false', function () {
649
+ before(function (done) {
650
+ logSkipSetup('/hello', function(req, res) { return req.url.indexOf('sandwich') != -1 }, done);
651
+ });
652
+
653
+ it('should be logged', function () {
654
+ result.log.msg.should.eql('HTTP GET /hello');
655
+ });
656
+ });
352
657
  });
353
- middleware(req, res, next);
354
- }
355
- , "then the transport should be invoked": function(result){
356
- assert.isTrue(result.transportInvoked);
357
- }
358
- , "the meta should contain a filtered request": function(result){
359
- assert.isTrue(!!result.log.meta.req, "req should be defined in meta");
360
- assert.isNotNull(result.log.meta.req);
361
- assert.equal(result.log.meta.req.method, "GET");
362
- assert.deepEqual(result.log.meta.req.query, { val: '2' });
363
- assert.isUndefined(result.log.meta.req.nonWhitelistedProperty);
364
-
365
- assert.isNotNull(result.log.meta.req.routeLevelAddedProperty);
366
- }
367
- , "the meta should contain a filtered request body": function(result) {
368
- assert.deepEqual(result.log.meta.req.body, {username: 'bobby'});
369
- assert.isUndefined(result.log.meta.req.body.password);
370
- }
371
- , "the meta should contain a filtered response": function(result){
372
- assert.isTrue(!!result.log.meta.res, "res should be defined in meta");
373
- assert.isNotNull(result.log.meta.res);
374
- assert.equal(result.log.meta.res.statusCode, 200);
375
- assert.isNotNull(result.log.meta.res.routeLevelAddedProperty);
376
- }
377
- , "the meta should contain a response time": function(result){
378
- assert.isTrue(!!result.log.meta.responseTime, "responseTime should be defined in meta");
379
- assert.isNotNull(result.log.meta.responseTime);
380
- assert.isTrue(result.log.meta.responseTime > 120);
381
- assert.isTrue(result.log.meta.responseTime < 130);
382
- }
383
- }
384
- }).export(module);
658
+ });
659
+ });
660
+ });