diff --git a/index.js b/index.js index 0c5669b..deeed01 100644 --- a/index.js +++ b/index.js @@ -29,8 +29,12 @@ function compose(middleware){ */ return function (context, next) { + // last called middleware # + let index = -1 return dispatch(0) function dispatch(i) { + if (i <= index) return Promise.reject(new Error('next() called multiple times')) + index = i const fn = middleware[i] || next if (!fn) return Promise.resolve() try { diff --git a/test/test.js b/test/test.js index 814bcb1..1f6c742 100644 --- a/test/test.js +++ b/test/test.js @@ -174,9 +174,65 @@ describe('Koa Compose', function(){ return compose(stack.map(co.wrap))({}).then(function () { throw 'promise was not rejected' - }) - .catch(function (e) { + }).catch(function (e) { e.should.be.instanceof(Error) }) }) + + // https://github.com/koajs/compose/pull/27#issuecomment-143109739 + it('should compose w/ other compositions', function() { + var called = []; + + return compose([ + compose([ + (ctx, next) => { + called.push(1) + return next() + }, + (ctx, next) => { + called.push(2) + return next() + } + ]), + (ctx, next) => { + called.push(3) + return next() + } + ])({}).then(() => assert.deepEqual(called, [1, 2, 3])) + }) + + it('should throw if next() is called multiple times', function() { + return compose([ + co.wrap(function* (ctx, next) { + yield next() + yield next() + }) + ])({}).then(() => { + throw new Error('boom') + }, err => { + assert(/multiple times/.test(err.message)) + }) + }) + + it('should return a valid middleware', function () { + var val = 0 + compose([ + compose([ + (ctx, next) => { + val++ + return next() + }, + (ctx, next) => { + val++ + return next() + } + ]), + (ctx, next) => { + val++ + return next() + } + ])({}).then(function () { + val.should.equal(3) + }) + }) })