UNPKG

extjs-gpl

Version:

GPL licensed version of Sencha Ext JS

1,124 lines (901 loc) 214 kB
/* 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