extjs-gpl
Version:
GPL licensed version of Sencha Ext JS
1,124 lines (901 loc) • 214 kB
JavaScript
/* global jasmine, describe, it, beforeEach, afterEach, expect, waitsFor, runs, xit, xdescribe */
/*
Adapted from:
Copyright (c) 2013 [DeftJS Framework Contributors](http://deftjs.org)
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
*/
describe('Ext.promise.Promise', function() {
var Deferred = Ext.Deferred,
ExtPromise = Ext.promise.Promise,
hasNativePromise = !!window.Promise,
targetScope = {},
deferred, promise, extLog;
if (Object.freeze) {
Object.freeze(targetScope);
}
beforeEach(function() {
// Prevent raised errors from polluting the console
extLog = Ext.log;
Ext.log = Ext.emptyFn;
deferred = promise = null;
});
afterEach(function() {
Ext.log = extLog;
deferred = promise = extLog = null;
});
function eventuallyResolvesTo(promise, value, equals) {
var done = false,
result;
promise.then(function(v) {
result = v;
done = true;
});
waitsFor(function() {
return done;
});
runs(function() {
if (equals) {
expect(result).toEqual(value);
} else {
expect(result).toBe(value);
}
});
}
function eventuallyRejectedWith(promise, error, message) {
var done = false,
result, reason;
promise.then(function(v) {
result = v;
done = true;
}, function(v) {
reason = v;
done = true;
});
waitsFor(function() {
return done;
});
runs(function() {
expect(result).toBe(undefined);
if (typeof error === 'string') {
expect(reason).toBe(error);
} else {
expect(reason instanceof error).toBe(true);
if (message) {
expect(reason.message).toBe(message);
}
}
});
}
function formatValue(value) {
var formattedValues;
if (value instanceof ExtPromise) {
return 'Promise';
}
if (value instanceof Deferred) {
return 'Deferred';
}
if (value instanceof Ext.ClassManager.get('Ext.Base')) {
return Ext.ClassManager.getName(value);
}
if (Ext.isArray(value)) {
formattedValues = Ext.Array.map(value, formatValue);
return "[" + (formattedValues.join(', ')) + "]";
}
if (Ext.isObject(value)) {
return 'Object';
}
if (Ext.isString(value)) {
return '"' + value + '"';
}
return '' + value;
}
describe('resolved()', function() {
var values = [void 0, null, false, 0, 1, 'expected value', [1, 2, 3], {}, new Error('error message')];
describe('returns a Promise that will resolve with the specified value', function() {
Ext.each(values, function(value) {
it(formatValue(value), function() {
promise = Deferred.resolved(value);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, value);
});
});
});
describe('returns a Promise that will resolve with the resolved value for the specified Promise when it resolves', function() {
Ext.each(values, function(value) {
it(formatValue(value), function() {
var deferred = new Deferred();
deferred.resolve(value);
promise = Deferred.resolved(deferred.promise);
expect(promise).not.toBe(deferred.promise);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, value);
});
});
});
describe('returns a Promise that will reject with the error associated with the specified Promise when it rejects', function() {
it('Error: error message', function() {
deferred = new Deferred();
deferred.reject(new Error('error message'));
promise = Deferred.resolved(deferred.promise);
expect(promise).not.toBe(deferred.promise);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('returns a new Promise that will adapt the specified untrusted (aka third-party) then-able', function() {
var MockThirdPartyPromise = function() {};
MockThirdPartyPromise.prototype.then = function(successCallback, failureCallback) {
this.successCallback = successCallback;
this.failureCallback = failureCallback;
switch (this.state) {
case 'resolved':
this.successCallback(this.value);
break;
case 'rejected':
this.failureCallback(this.value);
}
};
MockThirdPartyPromise.prototype.resolve = function(value) {
this.value = value;
this.state = 'resolved';
if (this.successCallback != null) {
this.successCallback(this.value);
}
};
MockThirdPartyPromise.prototype.reject = function(value) {
this.value = value;
this.state = 'rejected';
if (this.failureCallback != null) {
this.failureCallback(this.value);
}
};
it('resolves when resolved', function() {
var mockThirdPartyPromise = new MockThirdPartyPromise();
mockThirdPartyPromise.resolve('expected value');
promise = Deferred.resolved(mockThirdPartyPromise);
expect(promise).not.toBe(mockThirdPartyPromise);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value');
});
it('rejects when rejected', function() {
var mockThirdPartyPromise = new MockThirdPartyPromise();
mockThirdPartyPromise.reject('error message');
promise = Deferred.resolved(mockThirdPartyPromise);
expect(promise).not.toBe(mockThirdPartyPromise);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, 'error message');
});
});
});
describe('nesting promises', function() {
it('should resolve when returning a resolved deferred', function() {
promise = Deferred.resolved('initial').then(function(v) {
var other = new Deferred();
other.resolve(v + 'ok');
return other.promise;
});
eventuallyResolvesTo(promise, 'initialok');
});
if (hasNativePromise) {
it('should resolve when returning a resolved native', function() {
promise = Deferred.resolved('initial').then(function(v) {
return Promise.resolve(v + 'ok');
});
eventuallyResolvesTo(promise, 'initialok');
});
}
it('should reject when returning a rejected deferred', function() {
promise = Deferred.resolved('initial').then(function(v) {
var other = new Deferred();
other.reject(v + 'ok');
return other.promise;
});
eventuallyRejectedWith(promise, 'initialok');
});
if (hasNativePromise) {
it('should resolve when returning a rejected native', function() {
promise = Deferred.resolved('initial').then(function(v) {
return Promise.reject(v + 'ok');
});
eventuallyRejectedWith(promise, 'initialok');
});
}
});
describe('Promise.is()', function() {
describe('returns true for a Promise or then()-able', function() {
it('Promise', function() {
promise = new Deferred().promise;
expect(ExtPromise.is(promise)).toBe(true);
});
it('returns true for any then()-able', function() {
promise = {
then: function() {}
};
expect(ExtPromise.is(promise)).toBe(true);
});
if (hasNativePromise) {
it('returns true for a native Promise', function() {
var p = new Promise(function() {});
expect(ExtPromise.is(p)).toBe(true);
});
}
});
describe('returns false for non-promises', function() {
var values = [void 0, null, false, 0, 1, 'value', [1, 2, 3], {}, new Error('error message')];
Ext.each(values, function(value) {
it(formatValue(value), function() {
expect(ExtPromise.is(value)).toBe(false);
});
});
});
});
describe('all()', function() {
describe('returns a new Promise that will resolve with the resolved values for the specified Array of Promises(s) or values.', function() {
it('Empty Array', function() {
var value = [];
promise = ExtPromise.all(value);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, value, true);
});
it('Array with one value', function() {
var value = ['expected value'];
promise = ExtPromise.all(value);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, value, true);
});
it('Array of values', function() {
var value = [1, 2, 3];
promise = ExtPromise.all(value);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, value, true);
});
it('Sparse Array', function() {
var value = [, 2, , 4, 5];
promise = ExtPromise.all(value);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, value, true);
});
it('Array with one resolved Promise', function() {
promise = ExtPromise.all([
Deferred.resolved('expected value')
]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Array of resolved Promises', function() {
promise = ExtPromise.all([
Deferred.resolved(1),
Deferred.resolved(2),
Deferred.resolved(3)
]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, [1, 2, 3], true);
});
});
describe('returns a new Promise that will resolve with the resolved values for the specified resolved Promise of an Array of Promises(s) or values.', function() {
it('Promise of an empty Array', function() {
promise = ExtPromise.all(Deferred.resolved([]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, [], true);
});
it('Promise of an Array with one value', function() {
promise = ExtPromise.all(Deferred.resolved(['expected value']));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Promise of an Array of values', function() {
promise = ExtPromise.all(Deferred.resolved([1, 2, 3]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, [1, 2, 3], true);
});
it('Promise of a sparse Array', function() {
promise = ExtPromise.all(Deferred.resolved([, 2, , 4, 5]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, [, 2, , 4, 5], true);
});
it('Promise of an Array with one resolved Promise', function() {
promise = ExtPromise.all(Deferred.resolved([Deferred.resolved('expected value')]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Promise of an Array of resolved Promises', function() {
promise = ExtPromise.all(Deferred.resolved([Deferred.resolved(1), Deferred.resolved(2), Deferred.resolved(3)]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, [1, 2, 3], true);
});
});
describe('returns a new Promise that will reject with the error associated with the first Promise in the specified Array of Promise(s) or value(s) that rejects', function() {
it('Array with one rejected Promise', function() {
promise = ExtPromise.all([Deferred.rejected(new Error('error message'))]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
it('Array of resolved Promises and a rejected Promise', function() {
promise = ExtPromise.all([Deferred.resolved(1), Deferred.rejected(new Error('error message')), Deferred.resolved(3)]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
it('Array of values, pending and resolved Promises and a rejected Promise', function() {
promise = ExtPromise.all([1, 2,
Deferred.rejected(new Error('error message')),
Deferred.resolved(4),
new Deferred().promise
]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('returns a new Promise that will reject with the error associated with the first Promise in the specified resolved Promise of an Array of Promise(s) or value(s) that rejects', function() {
it('Promise of an Array with one rejected Promise', function() {
promise = ExtPromise.all(Deferred.resolved([Deferred.rejected(new Error('error message'))]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
it('Promise of an Array of resolved Promises and a rejected Promise', function() {
promise = ExtPromise.all(Deferred.resolved([
Deferred.resolved(1),
Deferred.rejected(new Error('error message')),
Deferred.resolved(3)
]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
it('Promise of an Array of values, pending and resolved Promises and a rejected Promise', function() {
promise = ExtPromise.all(Deferred.resolved([
1, 2,
Deferred.rejected(new Error('error message')),
Deferred.resolved(4),
new Deferred().promise
]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('returns a new Promise that will reject with the error associated with the rejected Promise of an Array of Promise(s) or value(s)', function() {
it('Error: error message', function() {
promise = ExtPromise.all(Deferred.rejected(new Error('error message')));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('throws an Error if anything other than Array or Promise of an Array is specified', function() {
it('no parameters', function() {
expect(function() {
return ExtPromise.all();
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('a single non-Array parameter', function() {
expect(function() {
return ExtPromise.all(1);
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('multiple non-Array parameters', function() {
expect(function() {
return ExtPromise.all(1, 2, 3);
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
});
});
describe('any()', function() {
function eventuallyResolvesToOneOf(promise, values) {
var done = false,
result;
promise.then(function(v) {
result = v;
done = true;
});
waitsFor(function() {
return done;
});
runs(function() {
expect(Ext.Array.indexOf(values, result)).not.toBe(-1);
});
}
describe('returns a new Promise that will resolve once any one of the specified Array of Promises(s) or values have resolved.', function() {
it('Array with one value', function() {
promise = Deferred.any(['expected value']);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Array of values', function() {
promise = Deferred.any([1, 2, 3]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [1, 2, 3]);
});
it('Sparse Array', function() {
promise = Deferred.any([, 2, , 4, 5]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [2, 4, 5]);
});
it('Array with one resolved Promise', function() {
promise = Deferred.any([Deferred.resolved('expected value')]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Array of resolved Promises', function() {
promise = Deferred.any([Deferred.resolved(1), Deferred.resolved(2), Deferred.resolved(3)]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [1, 2, 3]);
});
it('Array of rejected Promises and one resolved Promise', function() {
promise = Deferred.any([Deferred.rejected('error message'), Deferred.resolved('expected value'), Deferred.rejected('error message')]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Array of pending and rejected Promises and one resolved Promise', function() {
promise = Deferred.any([new Deferred().promise, Deferred.resolved('expected value'), Deferred.rejected('error message')]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Array of pending and rejected Promises and multiple resolved Promises', function() {
promise = Deferred.any([new Deferred().promise, Deferred.resolved(1), Deferred.rejected('error message'), Deferred.resolved(2)]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [1, 2]);
});
});
describe('returns a new Promise that will resolve once any one of the specified resolved Promise of an Array of Promises(s) or values have resolved.', function() {
it('Promise of an Array with one value', function() {
promise = Deferred.any(Deferred.resolved(['expected value']));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Promise of an Array of values', function() {
promise = Deferred.any(Deferred.resolved([1, 2, 3]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [1, 2, 3]);
});
it('Promise of a sparse Array', function() {
promise = Deferred.any(Deferred.resolved([, 2, , 4, 5]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [2, 4, 5]);
});
it('Promise of an Array with one resolved Promise', function() {
promise = Deferred.any(Deferred.resolved([Deferred.resolved('expected value')]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Promise of an Array of resolved Promise', function() {
promise = Deferred.any(Deferred.resolved([Deferred.resolved(1), Deferred.resolved(2), Deferred.resolved(3)]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [1, 2, 3]);
});
it('Promise of an Array of rejected Promises and one resolved Promise', function() {
promise = Deferred.any(Deferred.resolved([Deferred.rejected('error message'), Deferred.resolved('expected value'), Deferred.rejected('error message')]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Promise of an Array of pending and rejected Promises and one resolved Promise', function() {
promise = Deferred.any(Deferred.resolved([new Deferred().promise, Deferred.resolved('expected value'), Deferred.rejected('error message')]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Promise of an Array of pending and rejected Promises and multiple resolved Promises', function() {
promise = Deferred.any(Deferred.resolved([new Deferred().promise, Deferred.resolved(1), Deferred.rejected('error message'), Deferred.resolved(2)]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToOneOf(promise, [1, 2]);
});
});
describe('returns a new Promise that will reject if none of the specified Array of Promises(s) or values resolves.', function() {
it('Empty Array', function() {
promise = Deferred.any([]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'No Promises were resolved.');
});
it('Array with one rejected Promise', function() {
promise = Deferred.any([Deferred.rejected('error message')]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'No Promises were resolved.');
});
it('Array of rejected Promises', function() {
promise = Deferred.any([Deferred.rejected('error message'), Deferred.rejected('error message'), Deferred.rejected('error message')]);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'No Promises were resolved.');
});
});
describe('returns a new Promise that will reject if none of the specified resolved Promise of an Array of Promises(s) or values resolves.', function() {
it('Promise of an empty Array', function() {
promise = Deferred.any(Deferred.resolved([]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'No Promises were resolved.');
});
it('Promise of an Array with one rejected Promise', function() {
promise = Deferred.any(Deferred.resolved([Deferred.rejected('error message')]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'No Promises were resolved.');
});
it('Promise of an Array of rejected Promises', function() {
promise = Deferred.any(Deferred.resolved([Deferred.rejected('error message'), Deferred.rejected('error message'), Deferred.rejected('error message')]));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'No Promises were resolved.');
});
});
describe('returns a new Promise that will reject with the error associated with the rejected Promise of an Array of Promise(s) or value(s)', function() {
it('Error: error message', function() {
promise = Deferred.any(Deferred.rejected(new Error('error message')));
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('throws an Error if anything other than Array or Promise of an Array is specified', function() {
it('no parameters', function() {
expect(function() {
return Deferred.any();
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('a single non-Array parameter', function() {
expect(function() {
return Deferred.any(1);
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('multiple non-Array parameters', function() {
expect(function() {
return Deferred.any(1, 2, 3);
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
});
});
describe('some()', function() {
function eventuallyResolvesToSomeOf (promise, length, values) {
var done = false,
result;
promise.then(function(v) {
result = v;
done = true;
});
waitsFor(function() {
return done;
});
runs(function() {
expect(result.length).toBe(length);
var map = {};
for (var i = 0; i < result.length; ++i) {
var index = Ext.Array.indexOf(values, result[i]);
expect(index).not.toBe(-1);
expect(map[index]).not.toBe(true);
map[index] = true;
}
});
}
describe('returns a new Promise that will resolve once the specified number of the specified Array of Promises(s) or values have resolved.', function() {
it('Array with one value', function() {
promise = Deferred.some(['expected value'], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Array of values', function() {
promise = Deferred.some([1, 2, 3], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2, 3]);
});
it('Sparse Array', function() {
promise = Deferred.some([, 2, , 4, 5], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [2, 4, 5]);
});
it('Array with one resolved Promise', function() {
promise = Deferred.some([Deferred.resolved('expected value')], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Array of resolved Promises', function() {
promise = Deferred.some([Deferred.resolved(1), Deferred.resolved(2), Deferred.resolved(3)], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2, 3]);
});
it('Array of rejected Promises and one resolved Promise', function() {
promise = Deferred.some([Deferred.rejected('error message'), Deferred.resolved('expected value'), Deferred.rejected('error message')], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Array of pending and rejected Promises and one resolved Promise', function() {
promise = Deferred.some([new Deferred().promise, Deferred.resolved('expected value'), Deferred.rejected('error message')], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Array of rejected Promises and multiple resolved Promises', function() {
promise = Deferred.some([Deferred.rejected('error message'), Deferred.resolved(1), Deferred.rejected('error message'), Deferred.resolved(2)], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2]);
});
it('Array of pending and rejected Promises and multiple resolved Promises', function() {
promise = Deferred.some([new Deferred().promise, Deferred.resolved(1), Deferred.rejected('error message'), Deferred.resolved(2)], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2]);
});
});
describe('returns a new Promise that will resolve once the specified number of the specified resolved Promise of an Array of Promises(s) or values have resolved.', function() {
it('Promise of an Array with one value', function() {
promise = Deferred.some(Deferred.resolved(['expected value']), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Promise of an Array of values', function() {
promise = Deferred.some(Deferred.resolved([1, 2, 3]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2, 3]);
});
it('Promise of a sparse Array', function() {
promise = Deferred.some(Deferred.resolved([, 2, , 4, 5]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [2, 4, 5]);
});
it('Promise of an Array with one resolved Promise', function() {
promise = Deferred.some(Deferred.resolved([Deferred.resolved('expected value')]), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Promise of an Array of resolved Promises', function() {
promise = Deferred.some(Deferred.resolved([Deferred.resolved(1), Deferred.resolved(2), Deferred.resolved(3)]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2, 3]);
});
it('Promise of an Array of rejected Promises and one resolved Promise', function() {
promise = Deferred.some(Deferred.resolved([Deferred.rejected('error message'), Deferred.resolved('expected value'), Deferred.rejected('error message')]), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Promise of an Array of pending and rejected Promises and one resolved Promise', function() {
promise = Deferred.some(Deferred.resolved([new Deferred().promise, Deferred.resolved('expected value'), Deferred.rejected('error message')]), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, ['expected value'], true);
});
it('Promise of an Array of rejected Promises and multiple resolved Promises', function() {
promise = Deferred.some(Deferred.resolved([Deferred.rejected('error message'), Deferred.resolved(1), Deferred.rejected('error message'), Deferred.resolved(2)]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2]);
});
it('Promise of an Array of pending and rejected Promises and multiple resolved Promises', function() {
promise = Deferred.some(Deferred.resolved([new Deferred().promise, Deferred.resolved(1), Deferred.rejected('error message'), Deferred.resolved(2)]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesToSomeOf(promise, 2, [1, 2]);
});
});
describe('returns a new Promise that will reject if too few of the specified Array of Promises(s) or values resolves.', function() {
it('Empty Array with one resolved value requested', function() {
promise = Deferred.some([], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Empty Array with multiple resolved values requested', function() {
promise = Deferred.some([], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Array with one rejected Promise with one resolved value requested', function() {
promise = Deferred.some([Deferred.rejected('error message')], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Array with one rejected Promise with multiple resolved values requested', function() {
promise = Deferred.some([Deferred.rejected('error message')], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Array of rejected Promises with one resolved value requested', function() {
promise = Deferred.some([Deferred.rejected('error message'), Deferred.rejected('error message'), Deferred.rejected('error message')], 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Array of rejected Promises with multiple resolved values requested', function() {
promise = Deferred.some([Deferred.rejected('error message'), Deferred.rejected('error message'), Deferred.rejected('error message')], 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
});
describe('returns a new Promise that will reject if too few of the specified resolved Promise of an Array of Promises(s) or values resolves.', function() {
it('Promise of an empty Array with one resolved value requested', function() {
promise = Deferred.some(Deferred.resolved([]), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Promise of an empty Array with multiple resolved values requested', function() {
promise = Deferred.some(Deferred.resolved([]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Promise of an Array with one rejected Promise with one resolved value requested', function() {
promise = Deferred.some(Deferred.resolved([Deferred.rejected('error message')]), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Promise of an Array with one rejected Promise with multiple resolved values requested', function() {
promise = Deferred.some(Deferred.resolved([Deferred.rejected('error message')]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Promise of an Array of rejected Promises with one resolved value requested', function() {
promise = Deferred.some(Deferred.resolved([Deferred.rejected('error message'), Deferred.rejected('error message'), Deferred.rejected('error message')]), 1);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
it('Promise of an Array of rejected Promises with multiple resolved values requested', function() {
promise = Deferred.some(Deferred.resolved([Deferred.rejected('error message'), Deferred.rejected('error message'), Deferred.rejected('error message')]), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Too few Promises were resolved.');
});
});
describe('returns a new Promise that will reject with the error associated with the rejected Promise of an Array of Promise(s) or value(s)', function() {
it('Error: error message', function() {
promise = Deferred.some(Deferred.rejected(new Error('error message')), 2);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('throws an Error if anything other than Array or Promise of an Array is specified', function() {
it('no parameters', function() {
expect(function() {
return Deferred.some();
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('a single non-Array parameter', function() {
expect(function() {
return Deferred.some(1);
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('multiple non-Array parameters', function() {
expect(function() {
return Deferred.some(1, 2, 3);
}).toThrow('Invalid parameter: expected an Array or Promise of an Array.');
});
it('a single Array parameter', function() {
expect(function() {
return Deferred.some([1, 2, 3]);
}).toThrow('Invalid parameter: expected a positive integer.');
});
it('a single Array parameter and a non-numeric value', function() {
expect(function() {
return Deferred.some([1, 2, 3], 'value');
}).toThrow('Invalid parameter: expected a positive integer.');
});
});
}); // some
describe('delay()', function() {
// We have to be careful testing timing due to load during test runs on the
// build system. We basically ensure that delays are at least the specified
// amount but also allow for sloppy IE timers (+/- 16ms).
describe('returns a new Promise that will resolve after the specified delay', function() {
it('0 ms delay', function() {
promise = Deferred.delay(0);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, void 0, true);
});
it('value with 100 ms delay', function() {
promise = Deferred.delay(100);
var start = Ext.now();
expect(promise instanceof ExtPromise).toBe(true);
promise = promise.then(function(value) {
expect(Ext.now() - start).toBeGE(84);
return value;
});
eventuallyResolvesTo(promise, void 0, true);
});
});
describe('returns a new Promise that will resolve with the specified Promise or value after the specified delay', function() {
it('value with 0 ms delay', function() {
promise = Deferred.delay('expected value', 0);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('resolved Promise with 0 delay', function() {
promise = Deferred.delay(Deferred.resolved('expected value'), 0);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('value with 100 ms delay', function() {
promise = Deferred.delay('expected value', 100);
var start = Ext.now();
expect(promise instanceof ExtPromise).toBe(true);
promise = promise.then(function(value) {
expect(Ext.now() - start).toBeGE(84);
return value;
});
eventuallyResolvesTo(promise, 'expected value', true);
});
it('resolved Promise with 100 ms delay', function() {
promise = Deferred.delay(Deferred.resolved('expected value'), 100);
var start = Ext.now();
expect(promise instanceof ExtPromise).toBe(true);
promise = promise.then(function(value) {
expect(Ext.now() - start).toBeGE(84);
return value;
});
eventuallyResolvesTo(promise, 'expected value', true);
});
});
describe('returns a new Promise that will reject with the error associated with the specified rejected Promise after the specified delay', function() {
it('rejected Promise with 100 ms delay', function() {
promise = Deferred.delay(Deferred.rejected(new Error('error message')), 100);
var start = Ext.now();
expect(promise instanceof ExtPromise).toBe(true);
promise = promise.then(function(value) {
return value;
}, function(error) {
expect(Ext.now() - start).toBeGE(84);
throw error;
});
eventuallyRejectedWith(promise, Error, 'error message');
});
});
}); // delay
// TODO Timeout tests are fragile in Firefox
(Ext.isGecko ? xdescribe : describe)('timeout()', function() {
describe('returns a new Promise that will resolve with the specified Promise or value if it resolves before the specified timeout', function() {
it('value with 100 ms timeout', function() {
promise = Deferred.timeout('expected value', 100);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
it('Promise that resolves in 50 ms with a 100 ms timeout', function() {
promise = Deferred.timeout(Deferred.delay('expected value', 50), 100);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyResolvesTo(promise, 'expected value', true);
});
});
describe('returns a new Promise that will reject with the error associated with the specified rejected Promise if it rejects before the specified timeout', function() {
it('Promise that rejects in 50 ms with a 100 ms timeout', function() {
promise = Deferred.timeout(Deferred.delay(Deferred.rejected(new Error('error message')), 50), 100);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'error message');
});
});
describe('returns a new Promise that will reject after the specified timeout if the specified Promise or value has not yet resolved or rejected', function() {
it('Promise that resolves in 100 ms with a 50 ms timeout', function() {
promise = Deferred.timeout(Deferred.delay('expected value', 100), 50);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Promise timed out.');
});
it('Promise that rejects in 50 ms with a 100 ms timeout', function() {
promise = Deferred.timeout(Deferred.delay(Deferred.rejected(new Error('error message')), 100), 50);
expect(promise instanceof ExtPromise).toBe(true);
eventuallyRejectedWith(promise, Error, 'Promise timed out.');
});
});
}); // timeout
describe('memoize()', function() {
function fib (n) {
return (n < 2) ? n : fib(n - 1) + fib(n - 2);
}
function fibonacci (n) {
++fibonacci.calls;
fibonacci.scope = this;
return fib(n);
}
beforeEach(function() {
fibonacci.calls = 0;
delete fibonacci.scope;
});
describe('returns a new function that wraps the specified function, caching results for previously processed inputs, and returns a Promise that will resolve with the result value', function() {
it('value', function() {
var memoFn = Deferred.memoize(fibonacci);
promise = ExtPromise.all([memoFn(12), memoFn(12)]).then(function(value) {
expect(fibonacci.calls).toBe(1);
return value;
}, function(error) {
throw error;
});
eventuallyResolvesTo(promise, [fib(12), fib(12)], true);
});
it('resolved Promise', function() {
var memoFn = Deferred.memoize(fibonacci);
promise = ExtPromise.all([memoFn(Deferred.resolved(12)), memoFn(Deferred.resolved(12))]).then(function(value) {
expect(fibonacci.calls).toBe(1);
return value;
}, function(error) {
throw error;
});
eventuallyResolvesTo(promise, [fib(12), fib(12)], true);
});
});
describe('executes the wrapped function in the optionally specified scope', function() {
it('optional scope omitted', function() {
var memoFn = Deferred.memoize(fibonacci);
promise = memoFn(12).then(function(value) {
expect(fibonacci.calls).toBe(1);
expect(fibonacci.scope == window).toBe(true); // IE needs == not ===
return value;
}, function(error) {
throw error;
});
eventuallyResolvesTo(promise, fib(12), true);
});
it('scope specified', functi