diff --git a/lib/ConnectSequence.js b/lib/ConnectSequence.js index 5a94493..420be35 100644 --- a/lib/ConnectSequence.js +++ b/lib/ConnectSequence.js @@ -134,7 +134,7 @@ function appendList (middlewares) { } /** - * Append a middleware if a given filter on the req object is validated + * Append a list of middlewares as argument list if the filter pass the first time * @method * @param {Function} filter A filter function (returning a Boolean) * @param {Function} middlewares A middleware list of functions (calling its third argument as callback) @@ -195,6 +195,41 @@ function appendIf (filter /*, middlewares */) { return this } +/** + * Append many middlewares in an array if the filter pass the first time + * @method + * @param {Function} filter A filter function on the req object + * @param {Array} middlewares An array of middlewares to append to the sequence + * @return {ConnectSequence} a reference to the instance to be chainable + */ +function appendListIf (filter, middlewares) { + var args = [filter] + for (var i = 0; i < middlewares.length; i++) { + args.push(middlewares[i]) + } + return this.appendIf.apply(this, args) +} + +/** + * Tells if a given middleware is a regular middleware or an error handler + * @function + * @inner + * @param {Function} middleware + * @returns {Boolean} + */ +function isErrorHandler (cb) { + var str = cb.toString() + var args = str.split('(')[1].split(')')[0].split(',') + return args.length === 4 +} + +/** + * Append a middleware in function of its nature and the filter value stored in req.__connectSequenceFilterValue + * @function + * @inner + * @param {Function} middleware + * @returns {undefined} + */ function appendOnFilterValue (middleware) { if (isErrorHandler(middleware)) { this.append(function (err, req, res, next) { @@ -214,13 +249,3 @@ function appendOnFilterValue (middleware) { }) } } - -function appendListIf () { - -} - -function isErrorHandler (cb) { - var str = cb.toString() - var args = str.split('(')[1].split(')')[0].split(',') - return args.length === 4 -} diff --git a/tests/ConnectSequence.spec.js b/tests/ConnectSequence.spec.js index 847c845..f8655b3 100644 --- a/tests/ConnectSequence.spec.js +++ b/tests/ConnectSequence.spec.js @@ -447,6 +447,198 @@ describe('ConnectSequence', function () { }) }) + describe('#appendListIf()', function () { + var filter + var mid0, mid1, mid2, mid3, mid4 + var errorEmitter, errorHandler + + beforeEach(function () { + filter = function () { return true } + errorEmitter = function (req, res, next) { + req.errorEmitter = 'errorEmitter' + next('errorEmitter') + } + errorHandler = function (err, req, res, next) { + if (err) { req.errorHandler = 'errorHandler' } + next() + } + mid0 = function (req, res, next) { + req.mid0 = 'mid0' + next() + } + mid1 = function (req, res, next) { + req.mid1 = 'mid1' + next() + } + mid2 = function (req, res, next) { + req.mid2 = 'mid2' + next() + } + mid3 = function (req, res, next) { + req.mid3 = 'mid3' + next() + } + mid4 = function (req, res, next) { + req.mid4 = 'mid4' + next() + } + }) + + it('should be chainable', function () { + seq = new ConnectSequence(req, res, next) + expect(seq.appendListIf(filter, [mid])).to.equal(seq) + }) + + it('should throw TypeError if the first argument is not a function', function () { + seq = new ConnectSequence(req, res, next) + expect(function () { + seq.appendListIf('not a function', [mid0, mid1, mid2, mid3, mid4]) + }).to.throw(TypeError) + + seq = new ConnectSequence(req, res, next) + expect(function () { + seq.appendListIf(filter, [mid0, mid1, mid2, mid3, mid4]) + }).to.not.throw(Error) + }) + + it('should throw TypeError if the second argument is not an array', function () { + seq = new ConnectSequence(req, res, next) + expect(function () { + seq.appendListIf(filter, 'not an array') + }).to.throw(TypeError) + + seq = new ConnectSequence(req, res, next) + expect(function () { + seq.appendListIf(filter, [mid0, mid1, mid2, mid3, mid4]) + }).to.not.throw(Error) + }) + + it('should throw TypeError if the second argument is not an array of functions', function () { + seq = new ConnectSequence(req, res, next) + expect(function () { + seq.appendListIf(filter, ['not', 'an', 'array', 'of', 'functions']) + }).to.throw(TypeError) + + seq = new ConnectSequence(req, res, next) + expect(function () { + seq.appendListIf(filter, [mid0, mid1, mid2, mid3, mid4]) + }).to.not.throw(Error) + }) + + describe('when the previous condition on `req` is `true`', function () { + beforeEach(function () { + filter = function (req) { return true } + }) + + it('should augments the length of the middlewares array by the number of given middlewares', function () { + seq = new ConnectSequence(req, res, next) + expect(seq.middlewares.length).to.equal(0) + seq.appendListIf(filter, [mid0]) + expect(seq.middlewares.length).to.equal(1) + seq.appendListIf(filter, [mid0, mid1]) + expect(seq.middlewares.length).to.equal(3) + seq.appendListIf(filter, [mid0, mid1, mid2]) + expect(seq.middlewares.length).to.equal(6) + }) + + describe('when passing a normal middleware', function () { + it('should run the given middlewares', function (done) { + next = function () { + expect(req.mid0).to.equal('mid0') + expect(req.mid1).to.equal('mid1') + expect(req.mid2).to.equal('mid2') + expect(req.mid3).to.equal('mid3') + expect(req.mid4).to.equal('mid4') + done() + } + seq = new ConnectSequence(req, res, next) + seq.appendListIf(filter, [mid0, mid1, mid2, mid3, mid4]) + seq.run() + }) + }) + + describe('when passing a error handler middleware', function () { + it('should run the given error handler', function (done) { + next = function () { + expect(req.errorHandler).to.equal('errorHandler') + done() + } + seq = new ConnectSequence(req, res, next) + seq.append(errorEmitter) + seq.appendListIf(filter, [errorHandler]) + seq.run() + }) + + it('should run the given error handler and skip the normal middlewares', function (done) { + next = function () { + expect(req.mid0).to.equal('mid0') + expect(req.errorEmitter).to.equal('errorEmitter') + expect(req.mid1).to.be.undefined + expect(req.mid2).to.be.undefined + expect(req.errorHandler).to.equal('errorHandler') + expect(req.mid3).to.equal('mid3') + done() + } + filter = function (req) { return true } + seq = new ConnectSequence(req, res, next) + seq.appendListIf(filter, [mid0, errorEmitter, mid1, mid2, errorHandler, mid3]) + seq.run() + }) + }) + }) + + describe('when the previous condition on `req` is `false`', function () { + beforeEach(function () { + filter = function (req) { return false } + }) + + describe('when passing a normal middleware', function () { + it('should not run the given middlewares', function (done) { + next = function () { + expect(req.mid0).to.be.undefined + expect(req.mid1).to.be.undefined + expect(req.mid2).to.be.undefined + expect(req.mid3).to.be.undefined + expect(req.mid4).to.be.undefined + done() + } + seq = new ConnectSequence(req, res, next) + seq.appendListIf(filter, [mid0, mid1, mid2, mid3, mid4]) + seq.run() + }) + }) + + describe('when passing a error handler middleware', function () { + it('should not run the given error handler', function (done) { + next = function () { + expect(req.errorHandler).to.be.undefined + done() + } + seq = new ConnectSequence(req, res, next) + seq.append(errorEmitter) + seq.appendListIf(filter, [errorHandler]) + seq.run() + }) + + it('should not run any given error handler or normal middlewares', function (done) { + next = function () { + expect(req.mid0).to.equal('mid0') + expect(req.errorEmitter).to.equal('errorEmitter') + expect(req.mid1).to.be.undefined + expect(req.mid2).to.be.undefined + expect(req.errorHandler).to.be.undefined + expect(req.mid3).to.be.undefined + done() + } + seq = new ConnectSequence(req, res, next) + seq.append(mid0, errorEmitter) + seq.appendListIf(filter, [mid1, mid2, errorHandler, mid3]) + seq.run() + }) + }) + }) + }) + describe('#run()', function () { var mid0, mid1, mid2, mid3