Comparing version 0.2.0 to 0.3.0
510
lib/pacta.js
@@ -1,245 +0,367 @@ | ||
'use strict'; | ||
/*global module, define, process, setImmediate, setTimeout */ | ||
(function (name, context, definition) { | ||
'use strict'; | ||
var events = require('events'); | ||
if (typeof module === 'object' && module.exports) { | ||
module.exports = definition(); | ||
} else if (typeof define === 'function' && define.amd) { | ||
define(definition); | ||
} else { | ||
context[name] = definition(); | ||
} | ||
}('Promise', this, function () { | ||
'use strict'; | ||
var Promise = function (value) { | ||
this.emitter = new events.EventEmitter(); | ||
this.resolved = false; | ||
this.rejected = false; | ||
var nextTick, indexOf, EventEmitter, Promise, thenable, reduce; | ||
if (arguments.length) { | ||
this.resolve(value); | ||
} | ||
}; | ||
if (typeof Array.prototype.reduce !== 'function') { | ||
reduce = function (array, callback, initialValue) { | ||
var i, value, length = array.length, isValueSet = false; | ||
/* Populate a promise with its final value. */ | ||
Promise.prototype.resolve = Promise.prototype.fulfill = function (x) { | ||
if (this.state() === 'pending') { | ||
this.value = x; | ||
this.resolved = true; | ||
this.emitter.emit('resolved', x); | ||
} | ||
}; | ||
if (arguments.length > 2) { | ||
value = initialValue; | ||
isValueSet = true; | ||
} | ||
/* Reject a promise, populating it with a reason. */ | ||
Promise.prototype.reject = function (reason) { | ||
if (this.state() === 'pending') { | ||
this.reason = reason; | ||
this.rejected = true; | ||
this.emitter.emit('rejected', reason); | ||
for (i = 0; i < length; i += 1) { | ||
if (array.hasOwnProperty(i)) { | ||
if (isValueSet) { | ||
value = callback(value, array[i], i, array); | ||
} else { | ||
value = array[i]; | ||
isValueSet = true; | ||
} | ||
} | ||
} | ||
return value; | ||
}; | ||
} else { | ||
reduce = function (array) { | ||
return Array.prototype.reduce.apply(array, [].slice.call(arguments, 1)); | ||
}; | ||
} | ||
}; | ||
/* Return a promise's current state. */ | ||
Promise.prototype.state = function () { | ||
var result; | ||
if (this.resolved) { | ||
result = 'fulfilled'; | ||
} else if (this.rejected) { | ||
result = 'rejected'; | ||
/* Polyfill process.nextTick. */ | ||
if (typeof process === 'object' && process && | ||
typeof process.nextTick === 'function') { | ||
nextTick = process.nextTick; | ||
} else if (typeof setImmediate === 'function') { | ||
nextTick = setImmediate; | ||
} else { | ||
result = 'pending'; | ||
nextTick = function (f) { | ||
setTimeout(f, 0); | ||
}; | ||
} | ||
return result; | ||
}; | ||
/* Polyfill Array#indexOf. */ | ||
if (typeof Array.prototype.indexOf === 'function') { | ||
indexOf = function (haystack, needle) { | ||
return haystack.indexOf(needle); | ||
}; | ||
} else { | ||
indexOf = function (haystack, needle) { | ||
var i = 0, length = haystack.length, idx = -1, found = false; | ||
/* onRejected :: Promise a -> (a -> b) -> Promise b */ | ||
Promise.prototype.onRejected = function (f) { | ||
var promise = new Promise(), | ||
reason = this.reason; | ||
while (i < length && !found) { | ||
if (haystack[i] === needle) { | ||
idx = i; | ||
found = true; | ||
} | ||
if (this.rejected) { | ||
process.nextTick(function () { | ||
promise.resolve(f(reason)); | ||
}); | ||
} else { | ||
this.emitter.once('rejected', function (reason) { | ||
promise.resolve(f(reason)); | ||
}); | ||
i += 1; | ||
} | ||
return idx; | ||
}; | ||
} | ||
return promise; | ||
}; | ||
/* map :: Promise a -> (a -> b) -> Promise b */ | ||
Promise.prototype.map = function (f) { | ||
var promise = new Promise(), | ||
value = this.value; | ||
/* Polyfill EventEmitter. */ | ||
EventEmitter = function () { | ||
this.events = {}; | ||
}; | ||
if (this.resolved) { | ||
process.nextTick(function () { | ||
promise.resolve(f(value)); | ||
}); | ||
} else { | ||
this.emitter.once('resolved', function (x) { | ||
promise.resolve(f(x)); | ||
}); | ||
} | ||
EventEmitter.prototype.on = function (event, listener) { | ||
if (typeof this.events[event] !== 'object') { | ||
this.events[event] = []; | ||
} | ||
return promise; | ||
}; | ||
this.events[event].push(listener); | ||
}; | ||
/* chain :: Promise a -> (a -> Promise b) -> Promise b */ | ||
Promise.prototype.chain = function (f) { | ||
var promise = new Promise(); | ||
EventEmitter.prototype.removeListener = function (event, listener) { | ||
var idx; | ||
/* Map over the given Promise a with (a -> Promise b), returning a new | ||
* Promise (Promise b). Map over that, thereby gaining access to the inner | ||
* Promise b. Map over that in order to get to the inner value of b and | ||
* resolve another promise with it. Return that promise as it is equivalent | ||
* to Promise b. | ||
*/ | ||
this.map(f).map(function (x) { | ||
x.map(function (y) { | ||
promise.resolve(y); | ||
}); | ||
}); | ||
if (typeof this.events[event] === 'object') { | ||
idx = indexOf(this.events[event], listener); | ||
return promise; | ||
}; | ||
if (idx > -1) { | ||
this.events[event].splice(idx, 1); | ||
} | ||
} | ||
}; | ||
/* concat :: Promise a -> Promise a */ | ||
Promise.prototype.concat = function (other) { | ||
var promise = new Promise(); | ||
EventEmitter.prototype.emit = function (event) { | ||
var i, listeners, length, args = [].slice.call(arguments, 1); | ||
this.map(function (x) { | ||
other.map(function (y) { | ||
promise.resolve(x.concat(y)); | ||
if (typeof this.events[event] === 'object') { | ||
listeners = this.events[event].slice(); | ||
length = listeners.length; | ||
for (i = 0; i < length; i += 1) { | ||
listeners[i].apply(this, args); | ||
} | ||
} | ||
}; | ||
EventEmitter.prototype.once = function (event, listener) { | ||
this.on(event, function g() { | ||
this.removeListener(event, g); | ||
listener.apply(this, arguments); | ||
}); | ||
}); | ||
}; | ||
this.onRejected(function (reason) { | ||
promise.reject(reason); | ||
}); | ||
/* A Promise. */ | ||
Promise = function (value) { | ||
this.emitter = new EventEmitter(); | ||
this.resolved = false; | ||
this.rejected = false; | ||
other.onRejected(function (reason) { | ||
promise.reject(reason); | ||
}); | ||
if (arguments.length) { | ||
this.resolve(value); | ||
} | ||
}; | ||
return promise; | ||
}; | ||
/* Populate a promise with its final value. */ | ||
Promise.prototype.resolve = Promise.prototype.fulfill = function (x) { | ||
if (this.state() === 'pending') { | ||
this.value = x; | ||
this.resolved = true; | ||
this.emitter.emit('resolved', x); | ||
} | ||
}; | ||
/* ap :: Promise (a -> b) -> Promise a -> Promise b */ | ||
Promise.prototype.ap = function (m) { | ||
return this.chain(function (f) { | ||
return m.map(f); | ||
}); | ||
}; | ||
/* Reject a promise, populating it with a reason. */ | ||
Promise.prototype.reject = function (reason) { | ||
if (this.state() === 'pending') { | ||
this.reason = reason; | ||
this.rejected = true; | ||
this.emitter.emit('rejected', reason); | ||
} | ||
}; | ||
/* empty :: Promise a -> Promise a */ | ||
Promise.prototype.empty = function () { | ||
return Promise.of(this.value.empty ? this.value.empty() : this.value.constructor.empty()); | ||
}; | ||
/* Return a promise's current state. */ | ||
Promise.prototype.state = function () { | ||
var result; | ||
/* conjoin :: Promise a -> Promise b -> Promise [a b] | ||
* conjoin :: Promise a -> Promise [b] -> Promise [a b] | ||
* conjoin :: Promise [a] -> Promise b -> Promise [a b] | ||
* conjoin :: Promise [a] -> Promise [b] -> Promise [a b] | ||
*/ | ||
Promise.prototype.conjoin = function (other) { | ||
var wrap = function (x) { return [].concat(x); }; | ||
if (this.resolved) { | ||
result = 'fulfilled'; | ||
} else if (this.rejected) { | ||
result = 'rejected'; | ||
} else { | ||
result = 'pending'; | ||
} | ||
return this.map(wrap).concat(other.map(wrap)); | ||
}; | ||
return result; | ||
}; | ||
/* append :: Promise [a] -> Promise b -> Promise [a b] */ | ||
Promise.prototype.append = function (other) { | ||
return this.concat(other.map(function (x) { | ||
return [x]; | ||
})); | ||
}; | ||
/* onRejected :: Promise a -> (a -> b) -> Promise b */ | ||
Promise.prototype.onRejected = function (f) { | ||
var promise = new Promise(), | ||
reason = this.reason; | ||
/* spread :: Promise a -> (a -> b) -> Promise b */ | ||
Promise.prototype.spread = Promise.prototype.explode = function (f) { | ||
return this.map(function (x) { | ||
return f.apply(null, x); | ||
}); | ||
}; | ||
if (this.rejected) { | ||
nextTick(function () { | ||
promise.resolve(f(reason)); | ||
}); | ||
} else { | ||
this.emitter.once('rejected', function (reason) { | ||
promise.resolve(f(reason)); | ||
}); | ||
} | ||
Promise.prototype.reduce = function () { | ||
var args = [].slice.call(arguments); | ||
return promise; | ||
}; | ||
return this.map(function (x) { | ||
return x.reduce.apply(x, args); | ||
}); | ||
}; | ||
/* map :: Promise a -> (a -> b) -> Promise b */ | ||
Promise.prototype.map = function (f) { | ||
var promise = new Promise(), | ||
value = this.value; | ||
/* Determine whether a value is "thenable" in Promises/A+ terminology. */ | ||
var thenable = function (x) { | ||
return x !== null && typeof x === 'object' && | ||
typeof x.then === 'function'; | ||
}; | ||
if (this.resolved) { | ||
nextTick(function () { | ||
promise.resolve(f(value)); | ||
}); | ||
} else { | ||
this.emitter.once('resolved', function (x) { | ||
promise.resolve(f(x)); | ||
}); | ||
} | ||
/* Compatibility with the Promises/A+ specification. */ | ||
Promise.prototype.then = function (onFulfilled, onRejected) { | ||
var promise = new Promise(); | ||
return promise; | ||
}; | ||
if (typeof onFulfilled === 'function') { | ||
this.map(function (x) { | ||
try { | ||
var value = onFulfilled(x); | ||
/* chain :: Promise a -> (a -> Promise b) -> Promise b */ | ||
Promise.prototype.chain = function (f) { | ||
var promise = new Promise(); | ||
if (thenable(value)) { | ||
value.then(function (x) { | ||
promise.resolve(x); | ||
}, function (reason) { | ||
promise.reject(reason); | ||
}); | ||
} else { | ||
promise.resolve(value); | ||
} | ||
} catch (e) { | ||
promise.reject(e); | ||
} | ||
/* Map over the given Promise a with (a -> Promise b), returning a new | ||
* Promise (Promise b). Map over that, thereby gaining access to the inner | ||
* Promise b. Map over that in order to get to the inner value of b and | ||
* resolve another promise with it. Return that promise as it is equivalent | ||
* to Promise b. | ||
*/ | ||
this.map(f).map(function (x) { | ||
x.map(function (y) { | ||
promise.resolve(y); | ||
}); | ||
}); | ||
} else { | ||
return promise; | ||
}; | ||
/* concat :: Promise a -> Promise a */ | ||
Promise.prototype.concat = function (other) { | ||
var promise = new Promise(); | ||
this.map(function (x) { | ||
promise.resolve(x); | ||
other.map(function (y) { | ||
promise.resolve(x.concat(y)); | ||
}); | ||
}); | ||
} | ||
if (typeof onRejected === 'function') { | ||
this.onRejected(function (reason) { | ||
try { | ||
reason = onRejected(reason); | ||
promise.reject(reason); | ||
}); | ||
if (thenable(reason)) { | ||
reason.then(function (x) { | ||
promise.resolve(x); | ||
}, function (reason) { | ||
promise.reject(reason); | ||
}); | ||
} else { | ||
promise.resolve(reason); | ||
} | ||
} catch (e) { | ||
promise.reject(e); | ||
} | ||
}); | ||
} else { | ||
this.onRejected(function (reason) { | ||
other.onRejected(function (reason) { | ||
promise.reject(reason); | ||
}); | ||
} | ||
return promise; | ||
}; | ||
return promise; | ||
}; | ||
/* of :: a -> Promise a */ | ||
Promise.of = function (x) { | ||
return new Promise(x); | ||
}; | ||
/* ap :: Promise (a -> b) -> Promise a -> Promise b */ | ||
Promise.prototype.ap = function (m) { | ||
return this.chain(function (f) { | ||
return m.map(f); | ||
}); | ||
}; | ||
/* A Monoid interface for Array. */ | ||
Array.empty = function () { | ||
return []; | ||
}; | ||
/* empty :: Promise a -> Promise a */ | ||
Promise.prototype.empty = function () { | ||
return Promise.of(this.value.empty ? this.value.empty() : this.value.constructor.empty()); | ||
}; | ||
/* A Monoid interface for String. */ | ||
String.empty = function () { | ||
return ''; | ||
}; | ||
/* conjoin :: Promise a -> Promise b -> Promise [a b] | ||
* conjoin :: Promise a -> Promise [b] -> Promise [a b] | ||
* conjoin :: Promise [a] -> Promise b -> Promise [a b] | ||
* conjoin :: Promise [a] -> Promise [b] -> Promise [a b] | ||
*/ | ||
Promise.prototype.conjoin = function (other) { | ||
var wrap = function (x) { return [].concat(x); }; | ||
exports.Promise = Promise; | ||
return this.map(wrap).concat(other.map(wrap)); | ||
}; | ||
/* append :: Promise [a] -> Promise b -> Promise [a b] */ | ||
Promise.prototype.append = function (other) { | ||
return this.concat(other.map(function (x) { | ||
return [x]; | ||
})); | ||
}; | ||
/* spread :: Promise a -> (a -> b) -> Promise b */ | ||
Promise.prototype.spread = Promise.prototype.explode = function (f) { | ||
return this.map(function (x) { | ||
return f.apply(null, x); | ||
}); | ||
}; | ||
Promise.prototype.reduce = function () { | ||
var args = [].slice.call(arguments); | ||
return this.map(function (x) { | ||
return reduce.apply(null, [x].concat(args)); | ||
}); | ||
}; | ||
/* Determine whether a value is "thenable" in Promises/A+ terminology. */ | ||
thenable = function (x) { | ||
return x !== null && typeof x === 'object' && | ||
typeof x.then === 'function'; | ||
}; | ||
/* Compatibility with the Promises/A+ specification. */ | ||
Promise.prototype.then = function (onFulfilled, onRejected) { | ||
var promise = new Promise(); | ||
if (typeof onFulfilled === 'function') { | ||
this.map(function (x) { | ||
try { | ||
var value = onFulfilled(x); | ||
if (thenable(value)) { | ||
value.then(function (x) { | ||
promise.resolve(x); | ||
}, function (reason) { | ||
promise.reject(reason); | ||
}); | ||
} else { | ||
promise.resolve(value); | ||
} | ||
} catch (e) { | ||
promise.reject(e); | ||
} | ||
}); | ||
} else { | ||
this.map(function (x) { | ||
promise.resolve(x); | ||
}); | ||
} | ||
if (typeof onRejected === 'function') { | ||
this.onRejected(function (reason) { | ||
try { | ||
reason = onRejected(reason); | ||
if (thenable(reason)) { | ||
reason.then(function (x) { | ||
promise.resolve(x); | ||
}, function (reason) { | ||
promise.reject(reason); | ||
}); | ||
} else { | ||
promise.resolve(reason); | ||
} | ||
} catch (e) { | ||
promise.reject(e); | ||
} | ||
}); | ||
} else { | ||
this.onRejected(function (reason) { | ||
promise.reject(reason); | ||
}); | ||
} | ||
return promise; | ||
}; | ||
/* of :: a -> Promise a */ | ||
Promise.of = function (x) { | ||
return new Promise(x); | ||
}; | ||
/* A Monoid interface for Array. */ | ||
Array.empty = function () { | ||
return []; | ||
}; | ||
/* A Monoid interface for String. */ | ||
String.empty = function () { | ||
return ''; | ||
}; | ||
return Promise; | ||
})); |
@@ -7,3 +7,3 @@ { | ||
"keywords": ["promises", "monad", "functor", "promises-aplus"], | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"main": "./lib/pacta.js", | ||
@@ -10,0 +10,0 @@ "dependencies": {}, |
# pacta [![Build Status](https://travis-ci.org/mudge/pacta.png?branch=master)](https://travis-ci.org/mudge/pacta) | ||
```javascript | ||
{ 'pacta': '0.2.0' } | ||
{ 'pacta': '0.3.0' } | ||
``` | ||
```shell | ||
$ npm install pacta # for node | ||
$ bower install pacta # for the browser | ||
``` | ||
This is an implementation of [algebraic][Fantasy Land], [Promises/A+][A+] | ||
compliant Promises in [node.js](http://nodejs.org). | ||
compliant Promises in JavaScript (both for the browser and | ||
[node.js](http://nodejs.org)). | ||
@@ -22,3 +28,4 @@ Promises can be thought of as objects representing a value that may not have | ||
```javascript | ||
var Promise = require('pacta').Promise; | ||
/* Include pacta.js or require explicitly in node.js: */ | ||
var Promise = require('pacta'); | ||
@@ -128,3 +135,3 @@ var p = new Promise(); | ||
```javascript | ||
var Promise = require('pacta').Promise; | ||
var Promise = require('pacta'); | ||
@@ -131,0 +138,0 @@ var p = new Promise(); |
'use strict'; | ||
/* An adapter for the Promises/A+ compatibility suite. */ | ||
var Promise = require('../lib/pacta').Promise; | ||
var Promise = require('../lib/pacta'); | ||
@@ -6,0 +6,0 @@ exports.fulfilled = function (value) { |
@@ -1,164 +0,162 @@ | ||
/*global describe, it, beforeEach */ | ||
'use strict'; | ||
/*global describe, it, beforeEach, require, setTimeout */ | ||
(function (context, test) { | ||
'use strict'; | ||
var assert = require('assert'), | ||
Promise = require('../lib/pacta').Promise, | ||
adapter = require('./pacta_adapter'); | ||
if (typeof context.assert === 'object' && typeof context.Promise === 'function') { | ||
test(context.assert, context.Promise); | ||
} else { | ||
test(require('assert'), require('../lib/pacta')); | ||
} | ||
}(this, function (assert, Promise) { | ||
'use strict'; | ||
describe('Promise', function () { | ||
var p, p2, p3; | ||
describe('Promise', function () { | ||
var p, p2, p3, p4; | ||
beforeEach(function () { | ||
p = new Promise(); | ||
setTimeout(function () { | ||
p.resolve('foo'); | ||
}, 50); | ||
beforeEach(function () { | ||
p = new Promise(); | ||
setTimeout(function () { | ||
p.resolve('foo'); | ||
}, 50); | ||
p2 = new Promise(); | ||
setTimeout(function () { | ||
p2.resolve('bar'); | ||
}, 25); | ||
p2 = new Promise(); | ||
setTimeout(function () { | ||
p2.resolve('bar'); | ||
}, 25); | ||
p3 = new Promise(); | ||
setTimeout(function () { | ||
p3.resolve('baz'); | ||
}, 75); | ||
}); | ||
p3 = new Promise(); | ||
setTimeout(function () { | ||
p3.resolve('baz'); | ||
}, 75); | ||
}); | ||
describe('.of', function () { | ||
it('wraps a value in a new promise', function (done) { | ||
Promise.of(1).map(function (x) { | ||
assert.equal(1, x); | ||
done(); | ||
describe('.of', function () { | ||
it('wraps a value in a new promise', function (done) { | ||
Promise.of(1).map(function (x) { | ||
assert.equal(1, x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#state', function () { | ||
it('is pending for unfulfilled and unrejected promises', function () { | ||
var p = new Promise(); | ||
describe('#state', function () { | ||
it('is pending for unfulfilled and unrejected promises', function () { | ||
p = new Promise(); | ||
assert.equal('pending', p.state()); | ||
}); | ||
assert.equal('pending', p.state()); | ||
}); | ||
it('is fulfilled for fulfilled promises', function () { | ||
var p = Promise.of(1); | ||
it('is fulfilled for fulfilled promises', function () { | ||
p = Promise.of(1); | ||
assert.equal('fulfilled', p.state()); | ||
}); | ||
assert.equal('fulfilled', p.state()); | ||
}); | ||
it('is rejected for rejected promises', function () { | ||
var p = new Promise(); | ||
p.reject('error'); | ||
it('is rejected for rejected promises', function () { | ||
p = new Promise(); | ||
p.reject('error'); | ||
assert.equal('rejected', p.state()); | ||
assert.equal('rejected', p.state()); | ||
}); | ||
}); | ||
}); | ||
describe('#resolve', function () { | ||
it('resolves a promise with its final value', function () { | ||
var p = new Promise(); | ||
p.resolve(1); | ||
assert.equal('fulfilled', p.state()); | ||
}); | ||
it('triggers any listeners for resolution', function (done) { | ||
var triggered = false, | ||
describe('#resolve', function () { | ||
it('resolves a promise with its final value', function () { | ||
p = new Promise(); | ||
p.resolve(1); | ||
p.map(function () { | ||
triggered = true; | ||
done(); | ||
assert.equal('fulfilled', p.state()); | ||
}); | ||
p.resolve(1); | ||
it('triggers any listeners for resolution', function (done) { | ||
var triggered = false; | ||
assert.ok(triggered); | ||
}); | ||
p = new Promise(); | ||
p.map(function () { | ||
triggered = true; | ||
done(); | ||
}); | ||
it('does nothing to rejected promises', function () { | ||
var p = new Promise(); | ||
p.reject('error'); | ||
p.resolve(1); | ||
p.resolve(1); | ||
assert.equal('rejected', p.state()); | ||
}); | ||
assert.ok(triggered); | ||
}); | ||
it('does not trigger listeners if the promise is rejected', function () { | ||
var triggered = false, | ||
it('does nothing to rejected promises', function () { | ||
p = new Promise(); | ||
p.reject('error'); | ||
p.resolve(1); | ||
p.reject('error'); | ||
p.map(function () { | ||
triggered = true; | ||
assert.equal('rejected', p.state()); | ||
}); | ||
p.resolve(1); | ||
assert.ok(!triggered); | ||
}); | ||
}); | ||
it('does not trigger listeners if the promise is rejected', function () { | ||
var triggered = false; | ||
describe('#reject', function () { | ||
it('rejects a promise, setting a reason', function () { | ||
var p = new Promise(); | ||
p.reject('error'); | ||
p = new Promise(); | ||
p.reject('error'); | ||
p.map(function () { | ||
triggered = true; | ||
}); | ||
p.resolve(1); | ||
assert.equal('rejected', p.state()); | ||
assert.ok(!triggered); | ||
}); | ||
}); | ||
it('does nothing to fulfilled promises', function () { | ||
var p = Promise.of(1); | ||
p.reject('error'); | ||
describe('#reject', function () { | ||
it('rejects a promise, setting a reason', function () { | ||
p = new Promise(); | ||
p.reject('error'); | ||
assert.equal('fulfilled', p.state()); | ||
}); | ||
assert.equal('rejected', p.state()); | ||
}); | ||
it('triggers onRejected listeners', function (done) { | ||
var triggered = false, | ||
p = new Promise(); | ||
p.onRejected(function () { | ||
triggered = true; | ||
done(); | ||
it('does nothing to fulfilled promises', function () { | ||
p = Promise.of(1); | ||
p.reject('error'); | ||
assert.equal('fulfilled', p.state()); | ||
}); | ||
p.reject('error'); | ||
assert.ok(triggered); | ||
}); | ||
it('triggers onRejected listeners', function (done) { | ||
var triggered = false; | ||
it('does not trigger onRejected listeners if already fulfilled', function () { | ||
var triggered = false, | ||
p = Promise.of(1); | ||
p.onRejected(function () { | ||
triggered = true; | ||
p = new Promise(); | ||
p.onRejected(function () { | ||
triggered = true; | ||
done(); | ||
}); | ||
p.reject('error'); | ||
assert.ok(triggered); | ||
}); | ||
p.reject('error'); | ||
assert.ok(!triggered); | ||
}); | ||
}); | ||
it('does not trigger onRejected listeners if already fulfilled', function () { | ||
var triggered = false; | ||
describe('#onRejected', function () { | ||
it('binds a listener to be fired on rejection', function (done) { | ||
var p = new Promise(); | ||
p.reject('error'); | ||
p = Promise.of(1); | ||
p.onRejected(function () { | ||
triggered = true; | ||
}); | ||
p.reject('error'); | ||
p.onRejected(function (reason) { | ||
assert.equal('error', reason); | ||
done(); | ||
assert.ok(!triggered); | ||
}); | ||
}); | ||
}); | ||
describe('#map', function () { | ||
it('yields the value of the promise', function (done) { | ||
p.map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
describe('#onRejected', function () { | ||
it('binds a listener to be fired on rejection', function (done) { | ||
p = new Promise(); | ||
p.reject('error'); | ||
p.onRejected(function (reason) { | ||
assert.equal('error', reason); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('yields the value after resolution', function (done) { | ||
p.map(function () { | ||
/* Promise is now resolved so map again... */ | ||
describe('#map', function () { | ||
it('yields the value of the promise', function (done) { | ||
p.map(function (x) { | ||
@@ -169,20 +167,8 @@ assert.equal('foo', x); | ||
}); | ||
}); | ||
it('can be chained', function (done) { | ||
p.map(function (x) { | ||
return x + '!'; | ||
}).map(function (y) { | ||
assert.equal('foo!', y); | ||
done(); | ||
}); | ||
}); | ||
it('can be nested', function (done) { | ||
p.map(function (x) { | ||
p2.map(function (y) { | ||
p3.map(function (z) { | ||
it('yields the value after resolution', function (done) { | ||
p.map(function () { | ||
/* Promise is now resolved so map again... */ | ||
p.map(function (x) { | ||
assert.equal('foo', x); | ||
assert.equal('bar', y); | ||
assert.equal('baz', z); | ||
done(); | ||
@@ -192,84 +178,104 @@ }); | ||
}); | ||
}); | ||
it('fulfils the identity property of a functor', function (done) { | ||
p.map(function (x) { | ||
return x; | ||
}).map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
it('can be chained', function (done) { | ||
p.map(function (x) { | ||
return x + '!'; | ||
}).map(function (y) { | ||
assert.equal('foo!', y); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the composition property of a functor #1', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }, | ||
g = function (x) { return 'g(' + x + ')'; }; | ||
it('can be nested', function (done) { | ||
p.map(function (x) { | ||
p2.map(function (y) { | ||
p3.map(function (z) { | ||
assert.equal('foo', x); | ||
assert.equal('bar', y); | ||
assert.equal('baz', z); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
p.map(function (x) { return f(g(x)); }).map(function (x) { | ||
assert.equal('f(g(foo))', x); | ||
done(); | ||
it('fulfils the identity property of a functor', function (done) { | ||
p.map(function (x) { | ||
return x; | ||
}).map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the composition property of a functor #2', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }, | ||
g = function (x) { return 'g(' + x + ')'; }; | ||
it('fulfils the composition property of a functor #1', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }, | ||
g = function (x) { return 'g(' + x + ')'; }; | ||
p.map(g).map(f).map(function (x) { | ||
assert.equal('f(g(foo))', x); | ||
done(); | ||
p.map(function (x) { return f(g(x)); }).map(function (x) { | ||
assert.equal('f(g(foo))', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#then', function () { | ||
it('yields its value like #map', function (done) { | ||
p.then(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
it('fulfils the composition property of a functor #2', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }, | ||
g = function (x) { return 'g(' + x + ')'; }; | ||
p.map(g).map(f).map(function (x) { | ||
assert.equal('f(g(foo))', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('can be chained when returning a value', function (done) { | ||
p.then(function (x) { | ||
return x + '!'; | ||
}).then(function (x) { | ||
assert.equal('foo!', x); | ||
done(); | ||
describe('#then', function () { | ||
it('yields its value like #map', function (done) { | ||
p.then(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('does not wrap a promise in a promise', function (done) { | ||
p.then(function (x) { | ||
return Promise.of(x); | ||
}).map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
it('can be chained when returning a value', function (done) { | ||
p.then(function (x) { | ||
return x + '!'; | ||
}).then(function (x) { | ||
assert.equal('foo!', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('always returns a promise', function () { | ||
assert.equal('object', typeof p.then()); | ||
}); | ||
it('does not wrap a promise in a promise', function (done) { | ||
p.then(function (x) { | ||
return Promise.of(x); | ||
}).map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
}); | ||
}); | ||
it('returns a fulfilled promise with the return value of onRejected', function (done) { | ||
var p = new Promise(), p2; | ||
it('always returns a promise', function () { | ||
assert.equal('object', typeof p.then()); | ||
}); | ||
p.reject('foo'); | ||
it('returns a fulfilled promise with the return value of onRejected', function (done) { | ||
p = new Promise(); | ||
p.reject('foo'); | ||
p2 = p.then(function () { | ||
return 1; | ||
}, function () { | ||
return 'error'; | ||
}); | ||
p2 = p.then(function () { | ||
return 1; | ||
}, function () { | ||
return 'error'; | ||
}); | ||
p2.map(function (x) { | ||
assert.equal('error', x); | ||
assert.equal('fulfilled', p2.state()); | ||
done(); | ||
p2.map(function (x) { | ||
assert.equal('error', x); | ||
assert.equal('fulfilled', p2.state()); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('assumes the return value of onFulfilled', function (done) { | ||
var p = Promise.of('foo'), | ||
it('assumes the return value of onFulfilled', function (done) { | ||
p = Promise.of('foo'); | ||
p2 = p.then(function () { | ||
@@ -281,309 +287,310 @@ return 1; | ||
p2.map(function (x) { | ||
assert.equal(1, x); | ||
assert.equal('fulfilled', p2.state()); | ||
done(); | ||
p2.map(function (x) { | ||
assert.equal(1, x); | ||
assert.equal('fulfilled', p2.state()); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#concat', function () { | ||
it('fulfils the associativity property of semigroups #1', function (done) { | ||
var p = Promise.of([1]), | ||
p2 = Promise.of([2]), | ||
describe('#concat', function () { | ||
it('fulfils the associativity property of semigroups #1', function (done) { | ||
p = Promise.of([1]); | ||
p2 = Promise.of([2]); | ||
p3 = Promise.of([3]); | ||
p.concat(p2).concat(p3).map(function (x) { | ||
assert.equal(1, x[0]); | ||
assert.equal(2, x[1]); | ||
assert.equal(3, x[2]); | ||
done(); | ||
p.concat(p2).concat(p3).map(function (x) { | ||
assert.equal(1, x[0]); | ||
assert.equal(2, x[1]); | ||
assert.equal(3, x[2]); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the associativity property of semigroups #2', function (done) { | ||
var p = Promise.of([1]), | ||
p2 = Promise.of([2]), | ||
it('fulfils the associativity property of semigroups #2', function (done) { | ||
p = Promise.of([1]); | ||
p2 = Promise.of([2]); | ||
p3 = Promise.of([3]); | ||
p.concat(p2.concat(p3)).map(function (x) { | ||
assert.equal(1, x[0]); | ||
assert.equal(2, x[1]); | ||
assert.equal(3, x[2]); | ||
done(); | ||
p.concat(p2.concat(p3)).map(function (x) { | ||
assert.equal(1, x[0]); | ||
assert.equal(2, x[1]); | ||
assert.equal(3, x[2]); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the identity of a semigroup', function (done) { | ||
var p = Promise.of([1]), | ||
p2 = Promise.of([2]), | ||
it('fulfils the identity of a semigroup', function (done) { | ||
p = Promise.of([1]); | ||
p2 = Promise.of([2]); | ||
p3 = Promise.of([3]); | ||
p.concat(p2).concat(p3).map(function (x) { | ||
return x; | ||
}).map(function (x) { | ||
assert.deepEqual([1, 2, 3], x); | ||
done(); | ||
p.concat(p2).concat(p3).map(function (x) { | ||
return x; | ||
}).map(function (x) { | ||
assert.deepEqual([1, 2, 3], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('concatenates any monoid including strings', function (done) { | ||
p.concat(p2).concat(p3).map(function (x) { | ||
assert.equal('foobarbaz', x); | ||
done(); | ||
it('concatenates any monoid including strings', function (done) { | ||
p.concat(p2).concat(p3).map(function (x) { | ||
assert.equal('foobarbaz', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('is rejected if the first promise is rejected', function (done) { | ||
p.reject('Foo'); | ||
p.concat(p2).onRejected(function (reason) { | ||
assert.equal('Foo', reason); | ||
done(); | ||
it('is rejected if the first promise is rejected', function (done) { | ||
p.reject('Foo'); | ||
p.concat(p2).onRejected(function (reason) { | ||
assert.equal('Foo', reason); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('is rejected if the second promise is rejected', function (done) { | ||
p2.reject('Foo'); | ||
p.concat(p2).onRejected(function (reason) { | ||
assert.equal('Foo', reason); | ||
done(); | ||
it('is rejected if the second promise is rejected', function (done) { | ||
p2.reject('Foo'); | ||
p.concat(p2).onRejected(function (reason) { | ||
assert.equal('Foo', reason); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('takes the first rejection if both promises are rejected', function (done) { | ||
p.reject('Foo'); | ||
p2.reject('Bar'); | ||
p.concat(p2).onRejected(function (reason) { | ||
assert.equal('Foo', reason); | ||
done(); | ||
it('takes the first rejection if both promises are rejected', function (done) { | ||
p.reject('Foo'); | ||
p2.reject('Bar'); | ||
p.concat(p2).onRejected(function (reason) { | ||
assert.equal('Foo', reason); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#chain', function () { | ||
it('fulfils the associativity property of chain #1', function (done) { | ||
var f = function (x) { return Promise.of('f(' + x + ')'); }, | ||
g = function (x) { return Promise.of('g(' + x + ')'); }; | ||
describe('#chain', function () { | ||
it('fulfils the associativity property of chain #1', function (done) { | ||
var f = function (x) { return Promise.of('f(' + x + ')'); }, | ||
g = function (x) { return Promise.of('g(' + x + ')'); }; | ||
p.chain(f).chain(g).map(function (x) { | ||
assert.equal('g(f(foo))', x); | ||
done(); | ||
p.chain(f).chain(g).map(function (x) { | ||
assert.equal('g(f(foo))', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the associativity property of chain #2', function (done) { | ||
var f = function (x) { return Promise.of('f(' + x + ')'); }, | ||
g = function (x) { return Promise.of('g(' + x + ')'); }; | ||
it('fulfils the associativity property of chain #2', function (done) { | ||
var f = function (x) { return Promise.of('f(' + x + ')'); }, | ||
g = function (x) { return Promise.of('g(' + x + ')'); }; | ||
p.chain(function (x) { return f(x).chain(g); }).map(function (x) { | ||
assert.equal('g(f(foo))', x); | ||
done(); | ||
p.chain(function (x) { return f(x).chain(g); }).map(function (x) { | ||
assert.equal('g(f(foo))', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#ap', function () { | ||
it('fulfils the identity property of applicative', function (done) { | ||
Promise.of(function (a) { return a; }).ap(p).map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
describe('#ap', function () { | ||
it('fulfils the identity property of applicative', function (done) { | ||
Promise.of(function (a) { return a; }).ap(p).map(function (x) { | ||
assert.equal('foo', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the composition property of applicative #1', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
v = Promise.of(function (x) { return 'v(' + x + ')'; }), | ||
w = Promise.of('foo'); | ||
it('fulfils the composition property of applicative #1', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
v = Promise.of(function (x) { return 'v(' + x + ')'; }), | ||
w = Promise.of('foo'); | ||
Promise.of(function (f) { | ||
return function (g) { | ||
return function (x) { | ||
return f(g(x)); | ||
Promise.of(function (f) { | ||
return function (g) { | ||
return function (x) { | ||
return f(g(x)); | ||
}; | ||
}; | ||
}; | ||
}).ap(u).ap(v).ap(w).map(function (x) { | ||
assert.equal('u(v(foo))', x); | ||
done(); | ||
}).ap(u).ap(v).ap(w).map(function (x) { | ||
assert.equal('u(v(foo))', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the composition property of applicative #2', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
v = Promise.of(function (x) { return 'v(' + x + ')'; }), | ||
w = Promise.of('foo'); | ||
it('fulfils the composition property of applicative #2', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
v = Promise.of(function (x) { return 'v(' + x + ')'; }), | ||
w = Promise.of('foo'); | ||
u.ap(v.ap(w)).map(function (x) { | ||
assert.equal('u(v(foo))', x); | ||
done(); | ||
u.ap(v.ap(w)).map(function (x) { | ||
assert.equal('u(v(foo))', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the homomorphism property of applicative #1', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }; | ||
it('fulfils the homomorphism property of applicative #1', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }; | ||
Promise.of(f).ap(Promise.of('foo')).map(function (x) { | ||
assert.equal('f(foo)', x); | ||
done(); | ||
Promise.of(f).ap(Promise.of('foo')).map(function (x) { | ||
assert.equal('f(foo)', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the homomorphism property of applicative #2', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }; | ||
it('fulfils the homomorphism property of applicative #2', function (done) { | ||
var f = function (x) { return 'f(' + x + ')'; }; | ||
Promise.of(f('foo')).map(function (x) { | ||
assert.equal('f(foo)', x); | ||
done(); | ||
Promise.of(f('foo')).map(function (x) { | ||
assert.equal('f(foo)', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the interchange property of applicative #1', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
y = 'y'; | ||
it('fulfils the interchange property of applicative #1', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
y = 'y'; | ||
u.ap(Promise.of(y)).map(function (x) { | ||
assert.equal('u(y)', x); | ||
done(); | ||
u.ap(Promise.of(y)).map(function (x) { | ||
assert.equal('u(y)', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('fulfils the interchange property of applicative #2', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
y = 'y'; | ||
it('fulfils the interchange property of applicative #2', function (done) { | ||
var u = Promise.of(function (x) { return 'u(' + x + ')'; }), | ||
y = 'y'; | ||
Promise.of(function (f) { | ||
return f(y); | ||
}).ap(u).map(function (x) { | ||
assert.equal('u(y)', x); | ||
done(); | ||
Promise.of(function (f) { | ||
return f(y); | ||
}).ap(u).map(function (x) { | ||
assert.equal('u(y)', x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#empty', function () { | ||
it('conforms to the right identity', function (done) { | ||
var p = Promise.of([1]); | ||
describe('#empty', function () { | ||
it('conforms to the right identity', function (done) { | ||
p = Promise.of([1]); | ||
p.concat(p.empty()).map(function (x) { | ||
assert.deepEqual([1], x); | ||
done(); | ||
p.concat(p.empty()).map(function (x) { | ||
assert.deepEqual([1], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('conforms to the left identity', function (done) { | ||
var p = Promise.of([1]); | ||
it('conforms to the left identity', function (done) { | ||
p = Promise.of([1]); | ||
p.empty().concat(p).map(function (x) { | ||
assert.deepEqual([1], x); | ||
done(); | ||
p.empty().concat(p).map(function (x) { | ||
assert.deepEqual([1], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#conjoin', function () { | ||
it('concatenates values into a list regardless of type', function (done) { | ||
p.conjoin(p2).conjoin(p3).map(function (x) { | ||
assert.deepEqual(['foo', 'bar', 'baz'], x); | ||
done(); | ||
describe('#conjoin', function () { | ||
it('concatenates values into a list regardless of type', function (done) { | ||
p.conjoin(p2).conjoin(p3).map(function (x) { | ||
assert.deepEqual(['foo', 'bar', 'baz'], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('concatenates values into a list even if already a list', function (done) { | ||
var p = Promise.of([1]), | ||
p2 = Promise.of([2, 3]), | ||
it('concatenates values into a list even if already a list', function (done) { | ||
p = Promise.of([1]); | ||
p2 = Promise.of([2, 3]); | ||
p3 = Promise.of([4]); | ||
p.conjoin(p2).conjoin(p3).map(function (x) { | ||
assert.deepEqual([1, 2, 3, 4], x); | ||
done(); | ||
p.conjoin(p2).conjoin(p3).map(function (x) { | ||
assert.deepEqual([1, 2, 3, 4], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('concatenates values of mixed types', function (done) { | ||
var p2 = Promise.of([2, 3]); | ||
it('concatenates values of mixed types', function (done) { | ||
p2 = Promise.of([2, 3]); | ||
p.conjoin(p2).map(function (x) { | ||
assert.deepEqual(['foo', 2, 3], x); | ||
done(); | ||
p.conjoin(p2).map(function (x) { | ||
assert.deepEqual(['foo', 2, 3], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#append', function () { | ||
it('appends promises to a promise of an array', function (done) { | ||
var p = Promise.of([1]), | ||
describe('#append', function () { | ||
it('appends promises to a promise of an array', function (done) { | ||
p = Promise.of([1]); | ||
p2 = Promise.of(2); | ||
p.append(p2).map(function (x) { | ||
assert.deepEqual([1, 2], x); | ||
done(); | ||
p.append(p2).map(function (x) { | ||
assert.deepEqual([1, 2], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('appends promises of arrays to arrays without joining them', function (done) { | ||
var p = Promise.of([1]), | ||
it('appends promises of arrays to arrays without joining them', function (done) { | ||
p = Promise.of([1]); | ||
p2 = Promise.of([2]); | ||
p.append(p2).map(function (x) { | ||
assert.deepEqual([1, [2]], x); | ||
done(); | ||
p.append(p2).map(function (x) { | ||
assert.deepEqual([1, [2]], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('can be chained without nesting arrays', function (done) { | ||
var p = Promise.of([]), | ||
p2 = Promise.of([1]), | ||
p3 = Promise.of([2, 3]), | ||
it('can be chained without nesting arrays', function (done) { | ||
p = Promise.of([]); | ||
p2 = Promise.of([1]); | ||
p3 = Promise.of([2, 3]); | ||
p4 = Promise.of([4]); | ||
p.append(p2).append(p3).append(p4).map(function (x) { | ||
assert.deepEqual([[1], [2, 3], [4]], x); | ||
done(); | ||
p.append(p2).append(p3).append(p4).map(function (x) { | ||
assert.deepEqual([[1], [2, 3], [4]], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#spread', function () { | ||
it('calls the given function with each value of the Promise', function (done) { | ||
var p = Promise.of([1, 2, 3]); | ||
describe('#spread', function () { | ||
it('calls the given function with each value of the Promise', function (done) { | ||
p = Promise.of([1, 2, 3]); | ||
p.spread(function (x, y, z) { | ||
assert.equal(1, x); | ||
assert.equal(2, y); | ||
assert.equal(3, z); | ||
done(); | ||
p.spread(function (x, y, z) { | ||
assert.equal(1, x); | ||
assert.equal(2, y); | ||
assert.equal(3, z); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('returns a promise with a single value', function (done) { | ||
var p = Promise.of([1, 2, 3]); | ||
it('returns a promise with a single value', function (done) { | ||
p = Promise.of([1, 2, 3]); | ||
p.spread(function (x, y, z) { | ||
return x + y + z; | ||
}).map(function (x) { | ||
assert.equal(6, x); | ||
done(); | ||
p.spread(function (x, y, z) { | ||
return x + y + z; | ||
}).map(function (x) { | ||
assert.equal(6, x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#reduce', function () { | ||
it('returns a new promise with the result', function (done) { | ||
var p = Promise.of([[1], [2], [3]]); | ||
describe('#reduce', function () { | ||
it('returns a new promise with the result', function (done) { | ||
p = Promise.of([[1], [2], [3]]); | ||
p.reduce(function (acc, e) { | ||
return acc.concat(e); | ||
}).map(function (x) { | ||
assert.deepEqual([1, 2, 3], x); | ||
done(); | ||
p.reduce(function (acc, e) { | ||
return acc.concat(e); | ||
}).map(function (x) { | ||
assert.deepEqual([1, 2, 3], x); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('takes an optional initial value', function (done) { | ||
var p = Promise.of([1, 2, 3]); | ||
it('takes an optional initial value', function (done) { | ||
p = Promise.of([1, 2, 3]); | ||
p.reduce(function (acc, e) { | ||
return acc + e; | ||
}, 0).map(function (x) { | ||
assert.equal(6, x); | ||
done(); | ||
p.reduce(function (acc, e) { | ||
return acc + e; | ||
}, 0).map(function (x) { | ||
assert.equal(6, x); | ||
done(); | ||
}); | ||
}); | ||
@@ -593,17 +600,13 @@ }); | ||
describe('Promises/A+ compliance', function () { | ||
require('promises-aplus-tests').mocha(adapter); | ||
describe('Array', function () { | ||
describe('.empty', function () { | ||
assert.deepEqual([], Array.empty()); | ||
}); | ||
}); | ||
}); | ||
describe('Array', function () { | ||
describe('.empty', function () { | ||
assert.deepEqual([], Array.empty()); | ||
describe('String', function () { | ||
describe('.empty', function () { | ||
assert.equal('', String.empty()); | ||
}); | ||
}); | ||
}); | ||
describe('String', function () { | ||
describe('.empty', function () { | ||
assert.equal('', String.empty()); | ||
}); | ||
}); | ||
})); |
Sorry, the diff of this file is not supported yet
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
78031
18
942
450