Comparing version 1.1.8 to 1.2.0
465
breeze.js
@@ -1,21 +0,6 @@ | ||
/** | ||
* Determine whether passed object is a promise or not. | ||
* @param {Object} obj Value to be checked | ||
* @return {Boolean} Check result | ||
*/ | ||
function isPromise (obj) { | ||
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' | ||
} | ||
/** | ||
* Breeze Constructor | ||
* | ||
* Accepts a then method as the first argument. | ||
* | ||
* @param {Function} method initialization method, optional. | ||
*/ | ||
// Constructor | ||
function Breeze (method) { | ||
this.steps = [] | ||
if (typeof method === 'function') { | ||
if (typeof method === 'function' || isPromise(method)) { | ||
this.then(method) | ||
@@ -25,144 +10,115 @@ } | ||
/** | ||
* Takes the next (optional) callback, and generates the done callback to be passed as the first argument. | ||
* | ||
* @private | ||
* @param {Function} next Next callback in the system to be invoked. | ||
* @return {Function} Completion callback, first argument is error, subsequent arguments are passed down the chain. | ||
*/ | ||
Breeze.prototype.createDoneCallback = function _breezeCreateDoneCallback () { | ||
var system = this | ||
// Run next step registered on system step list | ||
Breeze.prototype.run = function () { | ||
var args = this.args || [] | ||
var step = this.steps.shift() | ||
var type = step[0] | ||
return function (err) { | ||
var context = this | ||
if (this.skip && typeof this.skip === 'number') { | ||
this.skip-- | ||
return this.check(true) | ||
} | ||
function handler (err) { | ||
if (err) { | ||
if (!system.onError && !system.onDeferredError) { | ||
system.err = err | ||
} else { | ||
if (system.onError) system.onError(err) | ||
if (system.onDeferredError) system.onDeferredError(err) | ||
} | ||
try { | ||
this.running = true | ||
if (this[type + 'Handler']) return this[type + 'Handler'](step, args) | ||
return this.check(true) | ||
} catch (err) { | ||
return this.onUncaughtError(err) | ||
} | ||
} | ||
return (system.steps = [] && system.check()) | ||
} | ||
// Set error on system object, invokes available error methods, short-circuit system | ||
Breeze.prototype.onUncaughtError = function (err) { | ||
this.err = err | ||
if (this.onError) this.onError(err) | ||
if (this.onDeferredError) this.onDeferredError(err) | ||
return (this.steps = [] && this.check()) | ||
} | ||
var args = Array.prototype.slice.call(arguments, 1) | ||
system.args = args | ||
system.context = context | ||
system.check(true) | ||
} | ||
// Determine system state and invoke next step when possible | ||
Breeze.prototype.check = function (pop, skip) { | ||
this.steps = this.steps || [] | ||
if (isPromise(err)) { | ||
var args = Array.prototype.slice.call(arguments, 1) | ||
var success = function () { | ||
var successArgs = Array.prototype.slice.call(arguments, 0) | ||
args = args.concat(successArgs) | ||
args.unshift(null) | ||
handler.apply(context, args) | ||
} | ||
if (pop && this.steps.length) { | ||
return this.run() | ||
} | ||
return typeof err.catch === 'function' | ||
? err.then(success).catch(handler) | ||
: err.then(success, handler) | ||
} | ||
if (pop && !this.steps.length) { | ||
return (this.running = false) | ||
} | ||
return handler.apply(context, arguments) | ||
if (this.steps.length && !this.running) { | ||
return this.run() | ||
} | ||
} | ||
/** | ||
* Starts the next task to be completed. | ||
* | ||
* @private | ||
* @return {void} | ||
*/ | ||
Breeze.prototype.run = function _breezeRun () { | ||
var args = this.args || [] | ||
var context = this.context || this | ||
var func = this.steps.shift() | ||
this.running = true | ||
// Add iteration step to the system | ||
Breeze.prototype.each = function (iterable, iteratee, next) { | ||
if (this.err) return this | ||
this.steps.push(['each', iterable, iteratee, next]) | ||
this.check() | ||
return this | ||
} | ||
try { | ||
if (typeof func === 'function') { | ||
args.unshift(this.createDoneCallback()) | ||
return func.apply(context, args) | ||
} | ||
// Iterate over each iterable and invoke iteratee for each item in iterables, | ||
// on error break iteration and give error to system | ||
// @private | ||
Breeze.prototype.eachHandler = function (step, args) { | ||
var iterables = step[1] | ||
var iteratee = step[2] | ||
var next = step[3] | ||
var system = this | ||
var index = 0 | ||
var count = 0 | ||
var lookup | ||
var length | ||
if (func[0] === 'none') { | ||
if (!this.hasSomeHappened) { | ||
this.hasNoneHappened = true | ||
func = func[1] | ||
args.unshift(this.createDoneCallback()) | ||
return func.apply(context, args) | ||
} | ||
if (typeof iterables === 'function') { | ||
iterables = iterables.apply(this.context, args) | ||
} | ||
return this.check(true) | ||
} | ||
if (isPlainObject(iterables)) { | ||
lookup = iterables | ||
iterables = Object.keys(iterables) | ||
} | ||
if (func[0] === 'some' && this.hasSomeHappened) { | ||
return this.check(true) | ||
length = iterables.length | ||
function iterableCallback (error, value) { | ||
if (system.err) return | ||
if (error) return system.handleError(error) | ||
if (arguments.length > 1) { | ||
if (lookup) { | ||
lookup[iterables[count]] = value | ||
} else { | ||
iterables[count] = value | ||
} | ||
} | ||
if ((typeof func[1] === 'function' && func[1].apply(this.context, args)) || (typeof func[1] !== 'function' && func[1])) { | ||
switch (func[0]) { | ||
case 'when': this.hasWhenHappened = true | ||
break | ||
case 'some': this.hasSomeHappened = true | ||
break | ||
if (++count === length) { | ||
if (typeof next === 'function') { | ||
args.unshift(system.createStepCallback()) | ||
return next.apply(system.context || [], args) | ||
} | ||
func = func[2] | ||
args.unshift(this.createDoneCallback()) | ||
func.apply(context, args) | ||
} else { | ||
return this.check(true) | ||
return system.check(true) | ||
} | ||
} catch (err) { | ||
if (!this.onError && !this.onDeferredError) { | ||
this.err = err | ||
} else { | ||
if (this.onError) this.onError(err) | ||
if (this.onDeferredError) this.onDeferredError(err) | ||
} | ||
return (this.steps = [] && this.check()) | ||
} | ||
} | ||
/** | ||
* Checks whether the system is running, needs to be ran, or has completed | ||
* running. | ||
* | ||
* @private | ||
* @return {void} | ||
*/ | ||
Breeze.prototype.check = function _breezeCheck (pop) { | ||
this.steps = this.steps || [] | ||
if (pop && this.steps.length) { | ||
return this.run() | ||
for (; index < length; index++) { | ||
setImmediate( | ||
iteratee, | ||
lookup ? lookup[iterables[index]] : iterables[index], | ||
lookup ? iterables[index] : index, | ||
iterableCallback | ||
) | ||
} | ||
if (pop && !this.steps.length) { | ||
return (this.running = false) | ||
} | ||
if (this.steps.length && !this.running) { | ||
return this.run() | ||
} | ||
return null | ||
} | ||
/** | ||
* Adds callback to the system stack when first argument passed is of a | ||
* truthy status. | ||
* | ||
* @param {Boolean} arg Argument to be evaluated | ||
* @param {Function} next Callback to be pushed onto the stack | ||
* @return {this} | ||
*/ | ||
Breeze.prototype.when = Breeze.prototype.maybe = function _breezeMaybeWhen (arg, next) { | ||
// Add conditional step to the system | ||
Breeze.prototype.if = Breeze.prototype.when = Breeze.prototype.maybe = function (arg, next) { | ||
if (this.err) return this | ||
this.steps.push(['when', arg, next]) | ||
@@ -173,13 +129,5 @@ this.check() | ||
/** | ||
* Adds callback to the system when first argument is evaluated as true, and | ||
* no none calls have been invoked. | ||
* | ||
* @param {Boolean} arg Argument to be evaluated | ||
* @param {Function} next Callback to be pushed onto stack | ||
* @return {this} | ||
*/ | ||
Breeze.prototype.some = function _breezeSome (arg, next) { | ||
// Add step to evaluate truthyness of first argument to invoke callback | ||
Breeze.prototype.some = function (arg, next) { | ||
if (this.err || this.hasNoneHappened) return this | ||
this.hasSome = true | ||
@@ -191,11 +139,30 @@ this.steps.push(['some', arg, next]) | ||
/** | ||
* Adds callback to the system if no some callback was triggered. | ||
* | ||
* @param {Function} next Callback to be pushed onto stack | ||
* @return {this} | ||
*/ | ||
Breeze.prototype.none = function _breezeNone (next) { | ||
if (this.err) return this | ||
// When some has already been invoked short-circuit and continue, when check is truthy | ||
// invoke the resolution method, otherwise continue. | ||
// @private | ||
Breeze.prototype.someHandler = Breeze.prototype.whenHandler = function (step, args) { | ||
var resolution = step[2] | ||
var check = step[1] | ||
var type = step[0] | ||
if (type === 'some' && this.hasSomeHappened) { | ||
return this.check(true) | ||
} | ||
if ((typeof check === 'function' && check.apply(this.context, args)) || (typeof check !== 'function' && check)) { | ||
if (type === 'when') this.hasWhenHappened = true | ||
if (type === 'some') this.hasSomeHappened = true | ||
step = resolution | ||
args.unshift(this.createStepCallback()) | ||
return step.apply(context, args) | ||
} | ||
return this.check(true) | ||
} | ||
// Add step to handle the case of when no thruthy some statements occured | ||
Breeze.prototype.none = function (next) { | ||
if (this.err || this.hasNoneHappened) return this | ||
if (!this.hasSome) { | ||
@@ -214,12 +181,41 @@ throw new Error('Cannot add .none check before adding .some checks') | ||
/** | ||
* Adds callback to the system | ||
* | ||
* @param {Function} next Callback to be pushed onto the stack | ||
* @return {this} | ||
*/ | ||
Breeze.prototype.then = function _breezeThen (next) { | ||
// Determine whether a some step has passed, when none have passed invoke passed none callback. | ||
// @private | ||
Breeze.prototype.noneHandler = function (step, args) { | ||
if (!this.hasSomeHappened) { | ||
this.hasNoneHappened = true | ||
step = step[1] | ||
args.unshift(this.createStepCallback()) | ||
return step.apply(context, args) | ||
} | ||
return this.check(true) | ||
} | ||
// Add variable passing step to system to allow quick introduction of variables to system | ||
Breeze.prototype.pass = function () { | ||
if (this.err) return this | ||
var step | ||
step = cloneArguments(arguments) | ||
step.unshift('pass') | ||
this.steps.push(step) | ||
this.check() | ||
return this | ||
} | ||
this.steps.push(next) | ||
// Determine step arguments and invoke first argument when it is a function, then concatenate results | ||
// to the system's arguments list. | ||
// @private | ||
Breeze.prototype.passHandler = function (step, args) { | ||
step.shift() | ||
if (step.length === 1 && typeof step === 'function') step[0] = step[0]() | ||
this.args = args | ||
this.args = this.args.concat(step) | ||
return this.check(true) | ||
} | ||
// Add generic thennable step to the system | ||
Breeze.prototype.then = function (next) { | ||
if (this.err) return this | ||
this.steps.push(['then', next]) | ||
this.check() | ||
@@ -229,10 +225,11 @@ return this | ||
/** | ||
* Checks whether system has an err and invokes callback, or saves callback for later | ||
* invocation. | ||
* | ||
* @param {Function} next Callback to be invoked should err exist | ||
* @return {this} | ||
*/ | ||
Breeze.prototype.catch = function _breezeCatch (next) { | ||
// Thennable logic handler | ||
// @private | ||
Breeze.prototype.thenHandler = function (step, args) { | ||
args.unshift(this.createStepCallback()) | ||
return step[1].apply(this.context || this, args) | ||
} | ||
// Add error handler to system, invoked immediately when error exists. | ||
Breeze.prototype.catch = function (next) { | ||
if (this.err) { | ||
@@ -253,8 +250,4 @@ next(this.err) | ||
/** | ||
* Generates a deferred promise | ||
* | ||
* @return {Function} | ||
*/ | ||
Breeze.prototype.promise = function _breezeDeferred () { | ||
// Generate deferred promise object for the current flow system | ||
Breeze.prototype.promise = Breeze.prototype.deferred = function () { | ||
var system = this | ||
@@ -265,5 +258,5 @@ var deferred = { | ||
system.steps.push(function () { | ||
return next.apply(this, Array.prototype.slice.call(arguments, 1)) | ||
}) | ||
system.steps.push(['then', function () { | ||
return next.apply(this, cloneArguments(arguments, 1)) | ||
}]) | ||
@@ -275,6 +268,3 @@ system.check() | ||
catch: function (next) { | ||
if (system.err) { | ||
return next(system.err) | ||
} | ||
if (system.err) return next(system.err) | ||
system.onDeferredError = next | ||
@@ -288,13 +278,49 @@ return deferred | ||
/** | ||
* Resets system | ||
*/ | ||
Breeze.prototype.reset = function _breezeReset () { | ||
this.hasMaybeHappened = undefined | ||
this.hasNoneHappened = undefined | ||
this.hasSomeHappened = undefined | ||
this.hasSome = undefined | ||
this.onError = undefined | ||
this.running = undefined | ||
this.err = undefined | ||
// Takes the next (optional) callback, and generates a callback to be passed as the first argument. | ||
Breeze.prototype.createStepCallback = function () { | ||
var system = this | ||
function handler (err) { | ||
if (err) return system.onUncaughtError(err) | ||
system.args = cloneArguments(arguments, 1) | ||
system.check(true) | ||
} | ||
function success () { | ||
system.args = system.args.concat(cloneArguments(arguments)) | ||
system.args.unshift(null) | ||
handler.apply(system.context, system.args) | ||
} | ||
return function (err) { | ||
if (err === 'skip') { | ||
system.skip = arguments[1] || 1 | ||
system.args = system.args ? system.args.slice(1) : [] | ||
return system.check(true) | ||
} | ||
system.context = this | ||
system.args = cloneArguments(arguments, 1) | ||
if (isPromise(err)) { | ||
return typeof err.catch === 'function' | ||
? err.then(success).catch(handler) | ||
: err.then(success, handler) | ||
} | ||
return handler.apply(system.context, arguments) | ||
} | ||
} | ||
// Resets system state to an empty state | ||
Breeze.prototype.reset = function () { | ||
this.hasMaybeHappened = null | ||
this.hasNoneHappened = null | ||
this.hasSomeHappened = null | ||
this.hasSome = null | ||
this.onError = null | ||
this.running = null | ||
this.err = null | ||
this.args = null | ||
this.context = null | ||
this.steps = [] | ||
@@ -305,7 +331,58 @@ | ||
/** | ||
* Create new instance of Breeze | ||
*/ | ||
// Debug garbage collection utility | ||
// @private | ||
Breeze.prototype.gc = function () { | ||
this.reset() | ||
this.steps = null | ||
} | ||
// Export breeze constructor | ||
module.exports = function breeze (method) { | ||
return new Breeze(method) | ||
} | ||
// Shim for setImmediate using setTimeout | ||
if (typeof setImmediate !== 'function') { | ||
function setImmediate () { | ||
var args = cloneArguments(arguments) | ||
args.splice(1, 0, 0) | ||
return setTimeout.apply(null, args) | ||
} | ||
} | ||
// Convert promise signature into callback signature | ||
function promiseToCallback (promise) { | ||
return function convertedPromiseCallbackStructure (callback) { | ||
return typeof promise.catch === 'function' | ||
? promise.then(function (data) { | ||
setImmediate(callback, null, data) | ||
}).catch(function (error) { | ||
setImmediate(callback, error) | ||
}) | ||
: promise.then(function (data) { | ||
setImmediate(callback, null, data) | ||
}, function (error) { | ||
setImmediate(callback, error) | ||
}) | ||
} | ||
} | ||
// Clone and slice arguments object into a new array without leaking. | ||
function cloneArguments (arg, begin, end) { | ||
var i = 0 | ||
var len = arg.length | ||
var args = new Array(len) | ||
for (; i < len; ++i) args[i] = arg[i] | ||
return args = args.slice(begin || 0, end || undefined) | ||
} | ||
// Determine whether passed object is a promise or promise variation | ||
function isPromise (obj) { | ||
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' | ||
} | ||
// Determine whether passed object is a plain object or not. | ||
function isPlainObject (value) { | ||
return Object.prototype.toString.call(value) === '[object Object]' | ||
} |
{ | ||
"name": "breeze", | ||
"version": "1.1.8", | ||
"version": "1.2.0", | ||
"description": "Functional async flow control library", | ||
@@ -5,0 +5,0 @@ "main": "breeze.js", |
@@ -26,2 +26,3 @@ # Breeze | ||
- `breeze(next)` - Initialize breeze flow system, supports initial `.then` method. | ||
- `.pass(value)` - Introduce new value into flow system, argument is appended to system arguments passed through `next`. | ||
- `.when(check, next)` - When `check` is truthy, add `next` to the stack | ||
@@ -32,4 +33,5 @@ - `.maybe(check, next)` - When `check` is truthy, add `next` to the stack, sugar for `breeze.when` | ||
- `.then(next)` - Add callback to stack | ||
- `.each(iterables, iteratee, next)` - Iterate over an object / array and invoke a method for each entry. `iterables` is not a reference therefore, you must properly store `iterables` outside of the flow if you plan to update or modify the object. | ||
- `.catch(next)` - Any error caught will terminate stack and be sent here | ||
- `.promise()` - Returns a deferred promise system, allowing for a second `.catch` | ||
- `.deferred()` - Returns a deferred promise system, allowing for a passable then / catch. | ||
- `.reset()` - Reset current system | ||
@@ -44,2 +46,4 @@ | ||
#### Promises | ||
When a `promise` is passed the system will attach to either the `then / catch` methods, or the `.then(then, catch)` | ||
@@ -51,56 +55,26 @@ method style depending on the promise type passed. Whenever the `then` is invoked, any `arguments` passed along with | ||
## Example | ||
``` | ||
next(promise, arguments...) | ||
``` | ||
```js | ||
function fetchUserTodos (username) { | ||
// Initialize breeze, fetch a user | ||
var flow = breeze(function (next) { | ||
next(api(token).getUser(username)) | ||
}) | ||
#### Skipping Steps | ||
// Fetch user todos, pass user along the chain | ||
flow.then(function (next, user) { | ||
next(user.getTodos(), user) | ||
}) | ||
When you pass the string `skip` as the first argument in the `next` method, the next step in the sequence will be skipped completely. | ||
// Catch bugs before you do your work! | ||
flow.when(function (user, todos) { | ||
return todos.getLength() < 0 | ||
}, function (next, user, todos) { | ||
todos.reset() | ||
next(todos.save(), user) | ||
}) | ||
You can skip multiple steps by providing a number as the second argument to `next` equalling the number of steps you wish to skip. Defaults to `1`. | ||
// Do whatever else you want | ||
flow.then(function (next, user, todos) { | ||
next(null, user, todos) | ||
}) | ||
``` | ||
next('skip', 1 /* optional; number of steps to skip */) | ||
``` | ||
flow.catch(function (err) { | ||
// handle internal function error should you want | ||
if (err.code === 500) { | ||
console.error('Holy Switch A Roo Batman! I think something really went wrong.') | ||
} | ||
## Examples | ||
console.error(err) | ||
}) | ||
- [basic](examples/basic.js) - Bare-bones example (`breeze`, `then`, `catch`) | ||
- [promises](examples/promises.js) - Returning and using promises within breeze (`then`, `next(promise)`) | ||
- [each](examples/each.js) - Breeze array iteration (`then`, `pass`, `each`, `catch`) | ||
- [when](examples/maybe.js) - Conditional flows (`then`, `when`) | ||
return flow.promise() | ||
} | ||
var promise = fetchUserTodos('nijikokun') | ||
Check out the [examples](examples/) directory for more in-depth examples and tutorials of how to use breeze. | ||
promise.then(function (user, todos) { | ||
// Show todos | ||
}) | ||
promise.catch(function (err) { | ||
// Show error in application | ||
}) | ||
``` | ||
## Examples | ||
Check out the [examples](examples/) directory for in-depth examples and tutorials of how to use breeze. | ||
## License | ||
@@ -127,2 +101,2 @@ | ||
[download]: https://github.com/Nijikokun/breeze/archive/v1.1.8.zip | ||
[download]: https://github.com/Nijikokun/breeze/archive/v1.2.0.zip |
var assert = require('assert') | ||
var breeze = require('../breeze') | ||
var http = require('http') | ||
describe('breeze', function () { | ||
it('should return a promise style object', function () { | ||
it('returns deferred', function () { | ||
var promise = breeze() | ||
@@ -12,3 +11,3 @@ assert(typeof promise.then === 'function') | ||
it('should support an initial then', function () { | ||
it('supports then method as first argument', function (done) { | ||
breeze(function (next) { | ||
@@ -20,14 +19,18 @@ assert(typeof next === 'function') | ||
assert(value === 'passed') | ||
done() | ||
}) | ||
.catch(function (err) { | ||
assert(false) | ||
done(err) | ||
}) | ||
}) | ||
it('should support then chaining', function () { | ||
it('then(): should properly continue on previous step success', function () { | ||
var fixture = 'value' | ||
var flow = breeze() | ||
breeze().then(function (next) { | ||
flow.then(function (next) { | ||
return next(null, fixture) | ||
}).then(function (next, value) { | ||
}) | ||
flow.then(function (next, value) { | ||
assert(value === fixture) | ||
@@ -37,8 +40,11 @@ }) | ||
it('should properly catch errors', function () { | ||
it('catch(): should be invoked when an error occurs', function () { | ||
var fixture = new Error('Simply testing.') | ||
var flow = breeze() | ||
breeze().then(function (next) { | ||
flow.then(function (next) { | ||
return next(fixture) | ||
}).catch(function (err) { | ||
}) | ||
flow.catch(function (err) { | ||
assert(err === fixture) | ||
@@ -48,12 +54,13 @@ }) | ||
it('should choose the proper road when using maybe', function () { | ||
it('maybe(): should invoke second argument when match passes', function (done) { | ||
var route = 'A' | ||
var fixtureA = 'hello' | ||
var fixtureB = 'world' | ||
var flow = breeze() | ||
breeze() | ||
.maybe(route === 'A', function (next) { | ||
flow.maybe(route === 'A', function (next) { | ||
return next(null, fixtureA) | ||
}) | ||
.maybe(function () { | ||
flow.maybe(function () { | ||
route === 'B' | ||
@@ -63,11 +70,14 @@ }, function (next) { | ||
}) | ||
.then(function (next, value) { | ||
flow.then(function (next, value) { | ||
assert(value === fixtureA) | ||
done() | ||
}) | ||
.catch(function (err) { | ||
assert(false) | ||
flow.catch(function (err) { | ||
done(err) | ||
}) | ||
}) | ||
it('should choose none when no some match', function () { | ||
it('none(): should be invoked when no match is successful', function (done) { | ||
var someA = false | ||
@@ -78,22 +88,27 @@ var someB = false | ||
var fixtureC = 'tekken' | ||
var flow = breeze() | ||
breeze() | ||
.some(someA, function (next) { | ||
flow.some(someA, function (next) { | ||
return next(null, fixtureA) | ||
}) | ||
.some(someB, function (next) { | ||
flow.some(someB, function (next) { | ||
return next(null, fixtureB) | ||
}) | ||
.none(function (next) { | ||
flow.none(function (next) { | ||
return next(null, fixtureC) | ||
}) | ||
.then(function (next, value) { | ||
flow.then(function (next, value) { | ||
assert(value === fixtureC) | ||
done() | ||
}) | ||
.catch(function (err) { | ||
assert(false) | ||
flow.catch(function (err) { | ||
done(err) | ||
}) | ||
}) | ||
it('should choose some when some has matched', function () { | ||
it('some(): should invoke when match is successful', function (done) { | ||
var someA = true | ||
@@ -104,22 +119,27 @@ var someB = false | ||
var fixtureC = 'tekken' | ||
var flow = breeze() | ||
breeze() | ||
.some(someA, function (next) { | ||
flow.some(someA, function (next) { | ||
return next(null, fixtureA) | ||
}) | ||
.some(someB, function (next) { | ||
flow.some(someB, function (next) { | ||
return next(null, fixtureB) | ||
}) | ||
.none(function (next) { | ||
flow.none(function (next) { | ||
return next(null, fixtureC) | ||
}) | ||
.then(function (next, value) { | ||
flow.then(function (next, value) { | ||
assert(value === fixtureA) | ||
done() | ||
}) | ||
.catch(function (err) { | ||
assert(false) | ||
flow.catch(function (err) { | ||
done(err) | ||
}) | ||
}) | ||
it('should support check methods', function () { | ||
it('when(): properly handles check method success result', function (done) { | ||
var check = function (value) { | ||
@@ -129,31 +149,31 @@ return value === 'passed' | ||
breeze(function (next) { | ||
var flow = breeze(function (next) { | ||
assert(typeof next === 'function') | ||
next(null, 'passed') | ||
}) | ||
.when(check, function (next, value) { | ||
flow.when(check, function (next, value) { | ||
assert(value === 'passed') | ||
next(null, 'through') | ||
}) | ||
.then(function (next, value) { | ||
flow.then(function (next, value) { | ||
assert(value === 'through') | ||
done() | ||
}) | ||
.catch(function (err) { | ||
assert(false) | ||
flow.catch(function (err) { | ||
done(err) | ||
}) | ||
}) | ||
it('should properly chain when async is involved', function (done) { | ||
var flow = breeze(function (next) { | ||
var request = http.request({ | ||
hostname: 'httpbin.org', | ||
port: 80, | ||
path: '/get', | ||
method: 'GET' | ||
}, function (res) { | ||
next(null, res) | ||
}) | ||
it('when(): supports async values from previous step as arguments for check method', function (done) { | ||
var flow = breeze() | ||
request.on('error', next) | ||
request.end() | ||
flow.then(function (next) { | ||
setTimeout(function () { | ||
next(null, { | ||
statusCode: 200 | ||
}) | ||
}, 0) | ||
}) | ||
@@ -169,8 +189,84 @@ | ||
flow.catch(function (err) { | ||
assert(false) | ||
done(err) | ||
}) | ||
}) | ||
it('next(): sending skip as first argument ignores next step in list', function (done) { | ||
var flow = breeze() | ||
flow.then(function (next) { | ||
next('skip') | ||
}) | ||
flow.then(function (next) { | ||
assert(false, 'Skipping next step failed') | ||
done() | ||
}) | ||
flow.then(function (next) { | ||
done() | ||
}) | ||
flow.catch(function (err) { | ||
done(err) | ||
}) | ||
}) | ||
it('should properly handle try/catch promise success', function (done) { | ||
it('next(): skip supports variable number of steps to skip', function (done) { | ||
var flow = breeze() | ||
flow.then(function (next) { | ||
next('skip', 2) | ||
}) | ||
flow.then(function (next) { | ||
assert(false, 'Skipping first next step failed') | ||
}) | ||
flow.then(function (next) { | ||
console.log('omg2') | ||
assert(false, 'Skipping second next step failed') | ||
}) | ||
flow.then(function (next) { | ||
done() | ||
}) | ||
flow.catch(function (err) { | ||
done(err) | ||
}) | ||
}) | ||
it('next(): supports passing fixtures after skip', function (done) { | ||
var flow = breeze() | ||
var fixture = 'hello world and trent' | ||
flow.then(function (next) { | ||
next(null, fixture) | ||
}) | ||
flow.then(function (next, passed) { | ||
assert(passed === fixture, 'fixture check failed') | ||
next('skip', 2) | ||
}) | ||
flow.then(function (next) { | ||
assert(false, 'Skipping first next step failed') | ||
}) | ||
flow.then(function (next) { | ||
assert(false, 'Skipping second next step failed') | ||
}) | ||
flow.then(function (next, passed) { | ||
assert(passed === fixture, 'fixture check failed after skipping') | ||
return done() | ||
}) | ||
flow.catch(function (err) { | ||
return done(err) | ||
}) | ||
}) | ||
it('next(): supports promise success when promise is passed as first argument', function (done) { | ||
var noop = function () {} | ||
@@ -186,15 +282,24 @@ var fixture = 'hello world' | ||
breeze(function (next) { | ||
var flow = breeze(function (next) { | ||
next(promise) | ||
}).then(function (next, value) { | ||
}) | ||
flow.then(function (next, value) { | ||
assert(value === fixture) | ||
done() | ||
return done() | ||
}) | ||
flow.catch(function (err) { | ||
return done(err) | ||
}) | ||
}) | ||
it('should properly handle try/catch promise error', function (done) { | ||
it('next(): supports promise error when promise is passed as first argument', function (done) { | ||
var fixture = 'hello world' | ||
var flow = breeze() | ||
var noop = function (next) { | ||
next(fixture) | ||
return next(fixture) | ||
} | ||
var promise = { | ||
@@ -209,15 +314,21 @@ then: function () { | ||
breeze(function (next) { | ||
next(promise) | ||
}).then(function (next, value) { | ||
flow.then(function (next) { | ||
return next(promise) | ||
}) | ||
flow.then(function (next, value) { | ||
assert(false) | ||
}).catch(function (err) { | ||
}) | ||
flow.catch(function (err) { | ||
assert(err === fixture) | ||
done() | ||
return done() | ||
}) | ||
}) | ||
it('should properly handle directly passed values w/ promise', function (done) { | ||
it('then(): supports sending additional arguments with promise as first argument', function (done) { | ||
var fixture = 'hello world' | ||
var flow = breeze() | ||
var noop = function () {} | ||
var promise = { | ||
@@ -233,21 +344,29 @@ then: function (next) { | ||
breeze(function (next) { | ||
flow.then(function (next) { | ||
next(promise, 'testing') | ||
}).then(function (next, passedValue, promiseValue) { | ||
}) | ||
flow.then(function (next, passedValue, promiseValue) { | ||
assert(passedValue === 'testing') | ||
assert(promiseValue === fixture) | ||
done() | ||
}).catch(function (err) { | ||
assert(false) | ||
}) | ||
flow.catch(function (err) { | ||
return done(err) | ||
}) | ||
}) | ||
it('should properly success through returned promise', function (done) { | ||
it('deferred(): should properly send success to then()', function (done) { | ||
var fixture = 'hello world' | ||
var flow = breeze() | ||
var promise = flow.deferred() | ||
var flow = breeze(function (next) { | ||
flow.then(function (next) { | ||
next(null, 'testing') | ||
}) | ||
var promise = flow.promise() | ||
flow.catch(function (err) { | ||
return done(err) | ||
}) | ||
@@ -257,6 +376,67 @@ promise.then(function (value) { | ||
done() | ||
}).catch(function (err) { | ||
assert(false) | ||
}) | ||
promise.catch(function (err) { | ||
return done(err) | ||
}) | ||
}) | ||
it('deferred(): should properly send errors to catch()', function (done) { | ||
var fixture = 'hello world' | ||
var flow = breeze() | ||
var promise = flow.deferred() | ||
flow.then(function (next) { | ||
return next('testing') | ||
}) | ||
promise.then(function (value) { | ||
return assert(false) | ||
}) | ||
promise.catch(function (err) { | ||
assert(err === 'testing') | ||
return done() | ||
}) | ||
}) | ||
it('pass(): properly introduce variables into flow', function (done) { | ||
var flow = breeze() | ||
flow.pass('first') | ||
flow.pass('second') | ||
flow.then(function (next, a, b) { | ||
assert(a === 'first') | ||
assert(b === 'second') | ||
return done() | ||
}) | ||
flow.catch(function (err) { | ||
return done(err) | ||
}) | ||
}) | ||
it('each(): properly iterate and apply logic to referenced array values', function (done) { | ||
var flow = breeze() | ||
var fixture = [1, 2, 3] | ||
flow.pass(fixture) | ||
flow.each(function (iterables) { | ||
return iterables | ||
}, function (value, index, next) { | ||
return next(null, value * 3) | ||
}) | ||
flow.then(function (next, iterables) { | ||
assert(iterables[0] === 3) | ||
assert(iterables[1] === 6) | ||
assert(iterables[2] === 9) | ||
return done() | ||
}) | ||
flow.catch(function (err) { | ||
return done(err) | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
29384
11
812
0
98