Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

middlewarify

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

middlewarify - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

test/promise-iface.test.js

123

middlewarify.js

@@ -6,6 +6,6 @@ /**

var __ = require('lodash');
var Promise = require('bluebird');
var middlewarify = module.exports = {};
var noop = function() {};
var noopMidd = function(cb) {if (__.isFunction(cb)) cb();};

@@ -27,3 +27,4 @@

* @param {Object=} optParams Optional parameters.
* @param {boolean=} throwErrors default is true.
* @param {boolean=} beforeAfter set to true to add Before/After hooks
* instead of the single use hook.
*/

@@ -41,3 +42,2 @@ middlewarify.make = function(obj, prop, optFinalCb, optParams) {

var defaultParams = {
throwErrors: true,
beforeAfter: false,

@@ -82,30 +82,16 @@ };

var args = Array.prototype.slice.call(arguments, 1);
var doneArgs;
var isDone = false;
var doneActual = noop;
var done = function() {
isDone = true;
doneArgs = arguments;
doneActual.apply(null, arguments);
};
var midds;
if (middObj.params.beforeAfter) {
midds = Array.prototype.slice.call(middObj.beforeMidds, 0);
midds.push(middObj.mainCallback);
midds = midds.concat(middObj.afterMidds);
} else {
midds = Array.prototype.slice.call(middObj.midds, 0);
midds.push(middObj.mainCallback);
}
middlewarify._fetchAndInvoke(midds, args, middObj.params, done);
return {done: function(fn) {
if (isDone) {
fn.apply(null, doneArgs);
return new Promise(function(resolve, reject) {
var deferred = Promise.defer();
deferred.promise.then(resolve, reject);
var midds;
if (middObj.params.beforeAfter) {
midds = Array.prototype.slice.call(middObj.beforeMidds);
midds.push(middObj.mainCallback);
midds = midds.concat(middObj.afterMidds);
} else {
doneActual = fn;
midds = Array.prototype.slice.call(middObj.midds);
midds.push(middObj.mainCallback);
}
}};
middlewarify._fetchAndInvoke(midds, args, deferred);
});
};

@@ -118,35 +104,70 @@

* @param {Array} args An array of arbitrary arguments, can be empty.
* @param {Object} params Parameters passed by the user.
* @param {Function} done Callback.
* @param {...*} optMiddArgs Arguments passed from the last middleware.
* @param {Promise.Defer} deferred Deferred object.
* @private
*/
middlewarify._fetchAndInvoke = function(midds, args, params, done, optMiddArgs) {
var lastMiddArgs = optMiddArgs || [];
middlewarify._fetchAndInvoke = function(midds, args, deferred) {
if (midds.length === 0) {
return deferred.resolve();
}
if (0 === midds.length) {
lastMiddArgs.unshift(null);
return done.apply(null, lastMiddArgs);
var midd = midds.shift();
var arity = midd.length;
var argsLen = args.length;
/** @type {boolean} User defined callback */
var hasCb = false;
// check if there's a callback defined, be explicit expect arity
// to be args.length + 1
if (arity - argsLen === 1) {
hasCb = true;
}
var midd = midds.shift();
try {
midd.apply(null, args.concat(function(err){
if (err) {
done(err);
} else {
var middArgs = Array.prototype.slice.call(arguments, 1);
middlewarify._fetchAndInvoke(midds, args, params, done, middArgs);
}
}));
} catch(ex) {
if (params.throwErrors) {
throw ex;
function userCb(err) {
if (err) {
deferred.reject(err);
} else {
done(ex);
middlewarify._fetchAndInvoke(midds, args, deferred);
}
}
var invokeArgs = Array.prototype.slice.call(args);
if (hasCb) {
invokeArgs.push(userCb);
}
middlewarify._invoke(midd, invokeArgs, function(err) {
if (err) {
return deferred.reject(err);
}
if (!hasCb) {
middlewarify._fetchAndInvoke(midds, args, deferred);
}
});
};
/**
* The actual invocation of the middleware happens here.
*
* @param {Function} midd The middleware to invoke.
* @param {Array} invokeArgs Arguments to invoke middleware with.
* @param {Function(Error=)} cb callback.
* @private
*/
middlewarify._invoke = function(midd, invokeArgs, cb) {
try {
var maybePromise = midd.apply(null, invokeArgs);
if (Promise.is(maybePromise)) {
return maybePromise.then(cb, function(err) {
cb(err || new Error());
});
}
cb();
} catch(ex) {
cb(ex);
}
};
/**
* Add middleware.

@@ -153,0 +174,0 @@ *

{
"name": "middlewarify",
"description": "Apply the middleware pattern to any function.",
"version": "0.1.0",
"version": "0.2.0",
"homepage": "https://github.com/thanpolas/middlewarify",

@@ -34,3 +34,4 @@ "author": {

"lodash": "~1.3.1",
"async": "~0.2.9"
"async": "~0.2.9",
"bluebird": "~1.0.3"
},

@@ -37,0 +38,0 @@ "devDependencies": {

# Middlewarify
Apply the middleware pattern, easy. You can add two types of middleware, a single queue type using the keyword `use()` or a Before/After type using `before()` and `after()` hooks.
Middleware pattern implementation, robust, easy, fast. You can add two types of middleware, a single queue type using the keyword `use()` or a Before/After type using `before()` and `after()` hooks. All middleware accept promises or vanilla callbacks and final resolution is done using the Promises/A+ spec.

@@ -47,8 +47,8 @@ [![Build Status](https://travis-ci.org/thanpolas/middlewarify.png)](https://travis-ci.org/thanpolas/middlewarify)

tasks.create.use(function(next){
tasks.create.use(function(){
console.log('middleware 1');
next();
});
// add another middleware to the 'create' operation
// this time use a callback to indicate asynchronicity
tasks.create.use(function(next){

@@ -59,2 +59,12 @@ console.log('middleware 2');

// add a third middleware to the 'create' operation
// this time use a promise to indicate asynchronicity
tasks.create.use(function(){
return new Promise(resolve, reject) {
console.log('middleware 3');
resolve();
});
});
```

@@ -67,9 +77,16 @@

tasks.create();
// prints
// middleware 1
// middleware 2
// middleware 3
// createTask Final Fn to be invoked
```
Invoking the middleware will return an object with a `done` property which you can use to setup your callbacks:
Invoking the middleware will return a Promise, use the `then` function to determine all middleware including the final function invoked successfully:
```js
tasks.create().done(function(err) {
tasks.create().then(function() {
// all middleware finished.
}, function(err) {
// Middleware failed
});

@@ -80,2 +97,4 @@ ```

To use the Before/After hook types all you need to do is pass an option to Middlewarify's `make()` method.
```js

@@ -114,4 +133,6 @@ var midd = require('middlewarify');

// invoke all middleware
tasks.create().done(function(err){
// at this point all middleware have finished.
tasks.create().then(function(){
// at this point all middleware have finished.
}, function(err) {
// handle error
});

@@ -121,3 +142,2 @@

## Middlewarify Methods

@@ -135,6 +155,8 @@

This example has created the Middleware Container `create` in the object `crud`. `create.crud` is a function that will invoke all the middleware.
This example has created the Middleware Container `create` in the object `crud`. `crud.create()` is a function that will invoke all the middleware.
You can add a third argument, the `optMainCallback`, this is the main payload of your middleware. `optOptions` is one more argument you can pass to Middlewarify to define behavior. Both `optOptions` and `optMainCallback` are optional and can be interswitched, i.e. you can pass options as a third argument, read on for examples and what are the available options.
You can pass a third argument, the `optMainCallback`, a Function. This can be considered the main payload of your middleware.
`optOptions` defines behavior. Both `optOptions` and `optMainCallback` are optional and can be interswitched, i.e. you can pass options as a third argument, read on for examples and what are the available options.
#### make() Options

@@ -144,27 +166,7 @@

* `throwErrors` type: **Boolean**, default: `true` If set to false all thrown errors will be suppressed and available only through the `.done()` method.
* `beforeAfter` type: **Boolean**, default: `false` If set to true the Before/After hooks will be used instead of the single queue `use` hook, which is the default, view the [example displayed above](#using-the-before--after-middleware-type).
##### `throwErrors` Example
```js
// don't throw errors
var crud = {};
middlewarify.make(crud, 'create', {throwErrors: false});
crud.create.use(function(){
throw new Error('an error');
});
// executing the middleware will not throw an error, the exception
// will be available only through the .done() callback
crud.create().done(function(err) {
err.message === 'an error'; // true
});
```
#### The use(fn) Method
The Middleware Container by default exposes a `use` method so you can add any number of middleware. `use()` accepts any number of parameters as long they are of type Function or Arrays of Functions. When the Before/After flag is enabled `use` is no longer there and instead you get `before` and `after` methods to hook your middleware. All three hook types accept the same argument types and patterns as described bellow.
The Middleware Container by default exposes a `use` hook so you can add any number of middleware. `use()` accepts any number of parameters as long they are of type Function or Array of Functions. When the Before/After flag is enabled `use` is no longer there and instead you get `before` and `after` hooks. All three hook types accept the same argument types and patterns as described bellow.

@@ -193,11 +195,43 @@ ```js

All middleware gets invoked with a callback so it can pass control to the next middleware.
All middleware get invoked with the arguments that the *Middleware Container* was invoked with. The same number or arguments, the exact same references.
following up on the previous examples:
```js
app.connect.use(function(req) {
req.a === 1; // true
req.a++;
});
app.connect.use(function(req) {
req.a === 2; // true
});
app.connect({a:1});
```
#### Asynchronous Middleware Using Promises
You can return a Promise from your middleware and Middlewarify will wait for its resolution before passing control to the next one.
```js
crud.create.before(function() {
return new Promise(resolve, reject) {
// do something async...
resolve();
});
});
```
#### Asynchronous Middleware Using Callbacks
Middlewarify determines the arity of your middleware and if it detects that you have one, and only one, more argument that what the *Middleware Container* was invoked with, then it treats it as a callback and you need to invoke it to pass control to the next middleware.
```js
crud.create.use(function(next) {
// do stuff
// Since we expect "create" to be invoked without any arguments
// then Middlewarify assumes this middleware is async and expects
// you to invoked "next"
next();
});
crud.create(); // no arguments passed
```

@@ -244,102 +278,15 @@

Because any argument passed to the Middleware Container (`crud.create(arg1, arg2, fn1);`) will get piped to the middleware, we cannot add a callback within these arguments. Thus the function `.done()` is provided, so you can check for errors or results.
When invoked, the *Middleware Container* returns a promise, with it you can check for ultimate execution outcome.
```js
crud.create(arg1, arg2, fn1).done(function(err) {
if (err) {
return console.error(err);
}
crud.create(arg1, arg2, fn1).then(function() {
// all cool...
}, function(err) {
// ops, handle error
return console.error(err);
});
```
The only way to pass arguments back to the callback of the `.done()` method is through the *Final Callback* that is defined in the `make()` method.
```js
var crud = {};
var lastMiddlware = function(done) {
// since this is the final middleware, we name the
// callback "done" instead of "next"
// and we invoke it with a null value as the first
// argument to indicate there were no errors.
done(null, 'one', 'two');
});
// now create the Middleware Container
middlewarify.make(crud, 'create', lastMiddlware);
// Invoke the Middleware Container
crud.create().done(function(err, arg1, arg2) {
if (err) { /* tough love */ }
arg1 === 'one'; // true
arg2 === 'two'; // true
});
```
> **Beware of Error Handling** Middlewarify will catch all thrown errors from your middleware. They will be piped to the `.done()` method. So if any of your middleware functions throws an error, it will not be visible unless you setup the `.done()` callback.
#### Why a .done() function
The trailling `.done()` function will notify you of the ultimate outcome of the middleware execution. The problem for having the callback as an argument when invoking the middleware with `tasks.create()` is that there is no way to determine if that is the callback to call when all middleware are done, or an argument that should be passed to all middleware.
This becomes more aparent when using the Before/After feature of Middlewarify which binds a `before` and `after` functions instead of `use`.
```js
var midd = require('middlewarify');
var tasks = module.exports = {};
// this is the main callback of your middleware.
function createTask(cb, done) {
anAsyncOp(function(err, result) {
if (err) {
cb(err);
done(err);
return;
}
// cb is the anon function passed as argument when the middleware will be
// invoked, done will signal to Middlewarify that execution has completed.
cb(null, result);
done(null, result);
});
}
// Make the'create' Middleware Container using before/after hooks
midd.make(tasks, 'create', createTask, {beforeAfter: true});
/** ... */
// add a before hook
tasks.create.before(function(cb, next) {
// ...
next();
});
// add an after hook
tasks.create.after(function(cb, result, next) {
// do something with "result"
next();
});
/** ... */
// invoke all middleware
tasks.create(function(err, result, done){
// this is invoked by the "createTask" function and BEFORE any of the
// "after" middleware are executed.
done();
}).done(function(err, fn, result){
// the "fn" is the anon function defined as an argument to tasks.create()!
// at this point all middleware have finished.
});
```
## Release History
- **v0.2.0**, *08 Feb 2014*
- Major API change, introduced Promises to API.
- **v0.1.0**, *28 Jan 2014*

@@ -346,0 +293,0 @@ - Added Before/After feature

@@ -6,6 +6,7 @@ /**

var assert = require('chai').assert;
var Promise = require('bluebird');
var midd = require('../');
// var noop = function(){};
var noop = function(){};

@@ -18,3 +19,2 @@ suite('6. Before / After middleware', function() {

// The numbering (e.g. 1.1.1) has nothing to do with order

@@ -24,3 +24,2 @@ // The purpose is to provide a unique string so specific tests are

test('6.1 Types Test', function() {

@@ -35,3 +34,4 @@ var obj = Object.create(null);

assert.notProperty(obj.create, 'use', 'obj.create should NOT have a use fn');
assert.isFunction(obj.create().done, 'obj.create().done should be a function');
assert.isFunction(obj.create().then, 'obj.create().then should be a Function');
assert.ok(Promise.is(obj.create()), 'obj.create() is a Promise');
});

@@ -52,34 +52,23 @@ });

fnPayload = sinon.spy();
midd.make(obj, 'create', fnPayload, {
beforeAfter: true,
});
midd.make(obj, 'create', fnPayload, {beforeAfter: true});
});
teardown(function() {
obj.create();
teardown(function(done) {
obj.create().then(function() {
assert.ok(midd1.calledOnce, 'midd1 called only once, called: ' + midd1.callCount);
assert.ok(midd2.calledOnce, 'midd2 called only once, called: ' + midd2.callCount);
assert.ok(midd3.calledOnce, 'midd3 called only once, called: ' + midd3.callCount);
assert.ok(midd4.calledOnce, 'midd4 called only once, called: ' + midd4.callCount);
assert.ok(midd5.calledOnce, 'midd5 called only once, called: ' + midd5.callCount);
assert.ok(midd6.calledOnce, 'midd6 called only once, called: ' + midd6.callCount);
assert.ok(fnPayload.calledOnce, 'fnPayload called only once');
midd1.yield();
midd2.yield();
midd3.yield();
fnPayload.yield();
midd4.yield();
midd5.yield();
midd6.yield();
assert.ok(midd1.calledOnce, 'midd1 called only once');
assert.ok(midd2.calledOnce, 'midd2 called only once');
assert.ok(midd3.calledOnce, 'midd3 called only once');
assert.ok(midd4.calledOnce, 'midd4 called only once');
assert.ok(midd5.calledOnce, 'midd5 called only once');
assert.ok(midd6.calledOnce, 'midd6 called only once');
assert.ok(fnPayload.calledOnce, 'fnPayload called only once');
assert.ok(midd1.calledBefore(midd2), '"midd1" called before "midd2"');
assert.ok(midd2.calledBefore(midd3), '"midd2" called before "midd3"');
assert.ok(midd3.calledBefore(fnPayload), '"midd3" called before "fnPayload"');
assert.ok(fnPayload.calledBefore(midd4), '"fnPayload" called before "midd4"');
assert.ok(midd4.calledBefore(midd5), '"midd4" called before "midd5"');
assert.ok(midd5.calledBefore(midd6), '"midd5" called before "midd6"');
assert.ok(midd1.calledBefore(midd2), '"midd1" called before "midd2"');
assert.ok(midd2.calledBefore(midd3), '"midd2" called before "midd3"');
assert.ok(midd3.calledBefore(fnPayload), '"midd3" called before "fnPayload"');
assert.ok(fnPayload.calledBefore(midd4), '"fnPayload" called before "midd4"');
assert.ok(midd4.calledBefore(midd5), '"midd4" called before "midd5"');
assert.ok(midd5.calledBefore(midd6), '"midd5" called before "midd6"');
done();
}, done).then(null, done);
});

@@ -107,3 +96,2 @@

});
});

@@ -113,8 +101,2 @@

var obj, mainMidd, firstMidd, secondMidd, thirdMidd;
function callAll(index) {
firstMidd.callArg(index);
secondMidd.callArg(index);
mainMidd.callArg(index);
thirdMidd.callArg(index);
}
setup(function() {

@@ -137,3 +119,3 @@ obj = Object.create(null);

var bar = {b: 2};
obj.create(1, foo, bar).done(function(err){
obj.create(1, foo, bar).then(function(err){
assert.notOk(err, 'error should not be truthy');

@@ -145,22 +127,6 @@ assert.ok(firstMidd.alwaysCalledWith(1, foo, bar), 'firstMidd should be invoked with these arguments');

done();
});
callAll(3);
}, done).then(null, done);
});
});
suite('6.4. Final middleware arguments', function(){
test('6.4.1 Last middleware passes arguments to create callback', function(done) {
var obj = Object.create(null);
midd.make(obj, 'create', function(cb){
cb(null, 1, 2);
}, {beforeAfter: true});
obj.create().done(function(err, arg1, arg2) {
assert.equal(1, arg1, 'Arg1 should be 1');
assert.equal(2, arg2, 'Arg2 should be 2');
done();
});
});
});
suite('6.5. Failing middleware cases', function(){

@@ -172,22 +138,30 @@ var obj;

});
test('6.5.1.1 Before middleware throws an error', function(){
obj.create.before(function(){
test('6.5.1.1 Before middleware throws an error', function(done){
obj.create.before(function() {
throw new Error('an error');
});
assert.throws(obj.create, Error);
obj.create().then(null, function(err) {
assert.instanceOf(err, Error);
assert.equal(err.message, 'an error');
done();
}).then(null, done);
});
test('6.5.1.1.2 After middleware throws an error', function(){
obj.create.after(function(){
test('6.5.1.1.2 After middleware throws an error', function(done){
obj.create.after(function() {
throw new Error('an error');
});
assert.throws(obj.create, Error);
obj.create().then(null, function(err) {
assert.instanceOf(err, Error);
assert.equal(err.message, 'an error');
done();
}).then(null, done);
});
test('6.5.1.2 Before middleware throws an error when param is not throw', function(){
test('6.5.1.2 Before middleware throws an error when param is not throw', function(done){
var custObj = Object.create(null);
midd.make(custObj, 'create', {throwErrors: false, beforeAfter: true});
midd.make(custObj, 'create', {beforeAfter: true});

@@ -198,39 +172,43 @@ custObj.create.before(function() {

custObj.create().done(function(err){
custObj.create().then(noop, function(err){
assert.instanceOf(err, Error, '"err" should be instanceOf Error');
assert.equal(err.message, 'an error', 'Error message should match');
});
done();
}, done).then(null, done);
});
test('6.5.1.3 After middleware throws an error when param is not throw', function(){
test('6.5.1.3 After middleware throws an error when param is not throw', function(done){
var custObj = Object.create(null);
midd.make(custObj, 'create', {throwErrors: false, beforeAfter: true});
midd.make(custObj, 'create', {beforeAfter: true});
custObj.create.after(function(){
throw new Error('an error');
});
custObj.create().done(function(err){
custObj.create().then(noop, function(err){
assert.instanceOf(err, Error, '"err" should be instanceOf Error');
assert.equal(err.message, 'an error', 'Error message should match');
});
done();
}, done).then(null, done);
});
test('6.5.2 a Before middleware calls next with an error', function(){
test('6.5.2 a Before middleware calls next with an error', function(done){
obj.create.before(function(next){
next(new Error('an error'));
});
obj.create().done(function(err){
obj.create().then(noop, function(err){
assert.instanceOf(err, Error, '"err" should be instanceOf Error');
assert.equal(err.message, 'an error', 'Error message should match');
});
done();
}, done).then(null, done);
});
test('6.5.2.1 a After middleware calls next with an error', function(){
test('6.5.2.1 a After middleware calls next with an error', function(done){
obj.create.after(function(next){
next(new Error('an error'));
});
obj.create().done(function(err){
obj.create().then(noop, function(err) {
assert.instanceOf(err, Error, '"err" should be instanceOf Error');
assert.equal(err.message, 'an error', 'Error message should match');
});
done();
}, done).then(null, done);
});
test('6.5.3 a failing Before middleware prevents rest of middleware from executing', function(){
test('6.5.3 a failing Before middleware prevents rest of middleware from executing', function(done){
obj.create.before(function(next){

@@ -245,8 +223,9 @@ next(new Error('an error'));

obj.create().done(function(){
obj.create().then(noop, function(){
assert.notOk(middSpy.called, 'second Before middleware should not be called');
assert.notOk(afterMiddSpy.called, 'After middleware should not be called');
});
done();
}).then(null, done);
});
test('6.5.4 a failing After middleware prevents rest of middleware from executing', function(){
test('6.5.4 a failing After middleware prevents rest of middleware from executing', function(done){
obj.create.after(function(next){

@@ -259,8 +238,7 @@ next(new Error('an error'));

obj.create().done(function(){
obj.create().then(noop, function(){
assert.notOk(middSpy.called, 'second after middleware should not be called');
});
done();
}).then(null, done);
});
});

@@ -7,6 +7,6 @@ /**

var assert = require('chai').assert;
var Promise = require('bluebird');
var midd = require('../');
// var noop = function(){};
var noop = function(){};

@@ -19,3 +19,2 @@ suite('1. Basic Tests', function() {

// The numbering (e.g. 1.1.1) has nothing to do with order

@@ -25,3 +24,2 @@ // The purpose is to provide a unique string so specific tests are

test('1.1 Types Test', function() {

@@ -32,7 +30,8 @@ var obj = Object.create(null);

assert.isFunction(obj.create.use, 'obj.create.use should be a function');
assert.isFunction(obj.create().done, 'obj.create().done should be a function');
assert.isFunction(obj.create().then, 'obj.create().then should be a Function');
assert.ok(Promise.is(obj.create()), 'obj.create().then is a Promise');
});
});
suite('2. middleware.use() Sequence of invocation', function() {
suite('2. middleware.use() Sequence of invocation Synchronous', function() {
var obj, lastMidd, firstMidd, secondMidd, thirdMidd;

@@ -50,6 +49,2 @@ setup(function() {

obj.create();
firstMidd.yield();
secondMidd.yield();
thirdMidd.yield();
lastMidd.yield();
assert.ok(firstMidd.calledOnce, 'firstMidd should be called only once');

@@ -81,23 +76,55 @@ assert.ok(secondMidd.calledOnce, 'secondMidd should be called only once');

});
});
suite('3. middleware() argument piping', function() {
suite('2.10 middleware.use() Sequence of invocation Asynchronous', function() {
var obj, lastMidd, firstMidd, secondMidd, thirdMidd;
function callAll(index) {
firstMidd.callArg(index);
secondMidd.callArg(index);
thirdMidd.callArg(index);
lastMidd.callArg(index);
}
var spyLastMidd, spyFirstMidd, spySecondMidd, spyThirdMidd;
setup(function() {
spyLastMidd = sinon.spy();
spyFirstMidd = sinon.spy();
spySecondMidd = sinon.spy();
spyThirdMidd = sinon.spy();
obj = Object.create(null);
lastMidd = sinon.spy();
firstMidd = sinon.spy();
secondMidd = sinon.spy();
thirdMidd = sinon.spy();
lastMidd = function(next) {spyLastMidd();next();};
firstMidd = function(next) {spyFirstMidd();next();};
secondMidd = function(next) {spySecondMidd();next();};
thirdMidd = function(next) {spyThirdMidd();next();};
midd.make(obj, 'create', lastMidd);
});
teardown(function(){
obj.create();
assert.ok(spyFirstMidd.calledOnce, 'firstMidd should be called only once');
assert.ok(spySecondMidd.calledOnce, 'secondMidd should be called only once');
assert.ok(spyThirdMidd.calledOnce, 'thirdMidd should be called only once');
assert.ok(spyLastMidd.calledOnce, 'lastMidd should be called only once');
assert.ok(spyFirstMidd.calledBefore(spySecondMidd), 'firstMidd should be called before secondMidd');
assert.ok(spySecondMidd.calledAfter(spyFirstMidd), 'secondMidd should be called after firstMidd');
assert.ok(spyThirdMidd.calledAfter(spySecondMidd), 'thirdMidd should be called after secondMidd');
assert.ok(spyLastMidd.calledAfter(spyThirdMidd), 'lastMidd should be called after thirdMidd');
});
test('2.10.1 Multiple arguments', function() {
obj.create.use(firstMidd, secondMidd, thirdMidd);
});
test('2.10.2 Multiple calls', function() {
obj.create.use(firstMidd);
obj.create.use(secondMidd);
obj.create.use(thirdMidd);
});
test('2.10.3 An array', function() {
obj.create.use([firstMidd, secondMidd, thirdMidd]);
});
test('2.10.4 Array mixed with arg', function() {
obj.create.use([firstMidd, secondMidd], thirdMidd);
});
});
suite('3. middleware() argument piping', function() {
var obj, lastMidd, firstMidd, secondMidd, thirdMidd;
teardown(function(){

@@ -107,13 +134,23 @@ });

test('3.1 Three arguments', function(done) {
function checkMiddlewareArgs(arg1, arg2, arg3) {
assert.equal(arg1, 1);
assert.deepEqual(arg2, {a: 1});
assert.deepEqual(arg3, {b: 2});
}
obj = Object.create(null);
lastMidd = checkMiddlewareArgs;
firstMidd = checkMiddlewareArgs;
secondMidd = checkMiddlewareArgs;
thirdMidd = checkMiddlewareArgs;
midd.make(obj, 'create', lastMidd);
obj.create.use(firstMidd, secondMidd, thirdMidd);
var foo = {a: 1};
var bar = {b: 2};
obj.create(1, foo, bar).done(function(err){
assert.notOk(err, 'error should not be truthy');
assert.ok(firstMidd.alwaysCalledWith(1, foo, bar), 'firstMidd should be invoked with these arguments');
assert.ok(secondMidd.alwaysCalledWith(1, foo, bar), 'secondMidd should be invoked with these arguments');
assert.ok(thirdMidd.alwaysCalledWith(1, foo, bar), 'thirdMidd should be invoked with these arguments');
assert.ok(lastMidd.alwaysCalledWith(1, foo, bar), 'lastMidd should be invoked with these arguments');
obj.create(1, foo, bar).then(function() {
done();
});
callAll(3);
}, done).then(null, done);
});

@@ -140,17 +177,2 @@

suite('4. Final middleware arguments', function(){
test('4.1 Last middleware passes arguments to create callback', function(done) {
var obj = Object.create(null);
midd.make(obj, 'create', function(cb){
cb(null, 1, 2);
});
obj.create().done(function(err, arg1, arg2) {
assert.equal(1, arg1, 'Arg1 should be 1');
assert.equal(2, arg2, 'Arg2 should be 2');
done();
});
});
});
suite('5. Failing middleware cases', function(){

@@ -162,33 +184,28 @@ var obj;

});
test('5.1.1 middleware throws an error', function(){
obj.create.use(function(){
throw new Error('an error');
});
assert.throws(obj.create, Error);
});
test('5.1.2 middleware throws an error when param is not throw', function(){
test('5.1.2 middleware accepts throw error', function(done){
var custObj = Object.create(null);
midd.make(custObj, 'create', {throwErrors: false});
midd.make(custObj, 'create');
custObj.create.use(function(){
throw new Error('an error');
});
custObj.create().done(function(err){
custObj.create().then(noop, function(err){
assert.instanceOf(err, Error, '"err" should be instanceOf Error');
assert.equal(err.message, 'an error', 'Error message should match');
});
done();
}).then(null, done);
});
test('5.2 a middleware calls next with an error', function(){
test('5.2 a middleware calls next with an error', function(done){
obj.create.use(function(next){
next(new Error('an error'));
});
obj.create().done(function(err){
obj.create().then(noop, function(err){
assert.instanceOf(err, Error, '"err" should be instanceOf Error');
assert.equal(err.message, 'an error', 'Error message should match');
});
done();
}).then(null, done);
});
test('5.3 a failing middleware prevents rest of middleware from executing', function(){
test('5.3 a failing middleware prevents rest of middleware from executing', function(done){
obj.create.use(function(next){

@@ -201,7 +218,8 @@ next(new Error('an error'));

obj.create().done(function(){
obj.create().then(null, function() {
assert.notOk(middSpy.called, 'second middleware should not be called');
});
done();
}, done).then(null, done);
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc