diff --git a/spec/core/EnvSpec.js b/spec/core/EnvSpec.js index 3b34e2e2..0cdad2cd 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -46,21 +46,19 @@ describe("Env", function() { })); }); - it('can configure a custom promise library', function() { - var myLibrary = { resolve: jasmine.createSpy(), reject: jasmine.createSpy() }; - expect(env.getPromise()).toBeUndefined(); + describe('promise library', function() { + it('can be configured with a custom library', function() { + var myLibrary = { resolve: jasmine.createSpy(), reject: jasmine.createSpy() }; + env.configure({ Promise: myLibrary }); + }); - env.configure({ promiseLibrary: myLibrary }); - expect(env.getPromise()).toBe(myLibrary); - }); + it('cannot be configured with an invalid promise library', function() { + var myLibrary = {}; - it('fails to configure a custom promise library if library is invalid', function() { - var myLibrary = {}; - expect(env.getPromise()).toBeUndefined(); - - expect(function() { - env.configure({ promiseLibrary: myLibrary }); - }).toThrowError('Custom promise library missing `resolve`/`reject` functions'); + expect(function() { + env.configure({ Promise: myLibrary }); + }).toThrowError('Custom promise library missing `resolve`/`reject` functions'); + }); }); it('defaults to multiple failures for specs', function() { diff --git a/spec/core/SpySpec.js b/spec/core/SpySpec.js index 2639aa98..e12a9d83 100644 --- a/spec/core/SpySpec.js +++ b/spec/core/SpySpec.js @@ -171,7 +171,29 @@ describe('Spies', function () { expect(spy('foo')).toEqual(17); }); - describe("When withArgs is used without a base strategy", function() { + describe('any promise-based strategy', function() { + it('works with global Promise library when available', function(done) { + jasmine.getEnv().requirePromises(); + + var spy = env.createSpy('foo').and.resolveValue(42); + spy().then(function(result) { + expect(result).toEqual(42); + done(); + }).catch(done.fail); + }); + + it('works with a custom Promise library', function() { + var customPromise = { resolve: jasmine.createSpy(), reject: jasmine.createSpy() }; + customPromise.resolve.and.returnValue('resolved'); + env.configure({ Promise: customPromise }); + + var spy = env.createSpy('foo').and.resolveValue(42); + expect(spy()).toEqual('resolved'); + expect(customPromise.resolve).toHaveBeenCalledWith(42); + }); + }); + + describe("when withArgs is used without a base strategy", function() { it("uses the matching strategy", function() { var spy = env.createSpy('foo'); spy.withArgs('baz').and.returnValue(-1); diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index cedc5338..ab13e4ab 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -115,7 +115,8 @@ describe("SpyStrategy", function() { jasmine.getEnv().requirePromises(); var originalFn = jasmine.createSpy("original"), - spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); + getPromise = function() { return Promise; }, + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn, getPromise: getPromise}); spyStrategy.resolveValue(37); spyStrategy.exec().then(function (returnValue) { @@ -128,11 +129,9 @@ describe("SpyStrategy", function() { var originalFn = jasmine.createSpy("original"), spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); - spyOn(jasmineUnderTest, 'getPromise'); - expect(function() { spyStrategy.resolveValue(37); - }).toThrowError('resolveValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); + }).toThrowError('resolveValue requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); }); }); @@ -141,7 +140,8 @@ describe("SpyStrategy", function() { jasmine.getEnv().requirePromises(); var originalFn = jasmine.createSpy("original"), - spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); + getPromise = function() { return Promise; }, + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn, getPromise: getPromise}); spyStrategy.rejectValue(new Error('oops')); spyStrategy.exec().then(done.fail).catch(function (error) { @@ -154,11 +154,9 @@ describe("SpyStrategy", function() { var originalFn = jasmine.createSpy("original"), spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); - spyOn(jasmineUnderTest, 'getPromise'); - expect(function() { spyStrategy.rejectValue(new Error('oops')); - }).toThrowError('rejectValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); + }).toThrowError('rejectValue requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); }); }); diff --git a/spec/core/baseSpec.js b/spec/core/baseSpec.js index d7be476f..7f17265b 100644 --- a/spec/core/baseSpec.js +++ b/spec/core/baseSpec.js @@ -27,19 +27,4 @@ describe('base helpers', function() { }, 100); }); }); - - describe('getPromise', function() { - it('returns a custom library if configured', function() { - var myLibrary = { resolve: jasmine.createSpy(), reject: jasmine.createSpy() }; - jasmineUnderTest.getEnv().configure({ promiseLibrary: myLibrary }); - expect(jasmineUnderTest.getPromise()).toBe(myLibrary); - }); - - it('returns global library if not configured', function() { - var globalLibrary = {}; - var global = { Promise: globalLibrary }; - spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global); - expect(jasmineUnderTest.getPromise()).toBe(globalLibrary); - }); - }); }); diff --git a/src/core/Env.js b/src/core/Env.js index 7841fe34..f401526c 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -10,6 +10,7 @@ getJasmineRequireObj().Env = function(j$) { var self = this; var global = options.global || j$.getGlobal(); + var customPromise; var totalSpecsDefined = 0; @@ -79,13 +80,13 @@ getJasmineRequireObj().Env = function(j$) { hideDisabled: false, /** * Set to provide a custom promise library that Jasmine will use if it needs - * to create a promise. If not set, it will default to whatever global promise + * to create a promise. If not set, it will default to whatever global Promise * library is available (if any). - * @name Configuration#promiseLibrary + * @name Configuration#Promise * @type function * @default undefined */ - promiseLibrary: undefined + Promise: undefined }; var currentSuite = function() { @@ -152,10 +153,10 @@ getJasmineRequireObj().Env = function(j$) { config.hideDisabled = configuration.hideDisabled; } - if (configuration.hasOwnProperty('promiseLibrary')) { - if (typeof configuration.promiseLibrary.resolve === 'function' && - typeof configuration.promiseLibrary.reject === 'function') { - config.promiseLibrary = configuration.promiseLibrary; + if (configuration.hasOwnProperty('Promise')) { + if (typeof configuration.Promise.resolve === 'function' && + typeof configuration.Promise.reject === 'function') { + customPromise = configuration.Promise; } else { throw new Error('Custom promise library missing `resolve`/`reject` functions'); } @@ -211,10 +212,6 @@ getJasmineRequireObj().Env = function(j$) { } }; - this.getPromise = function() { - return config.promiseLibrary; - }; - j$.Expectation.addCoreMatchers(j$.matchers); j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers); @@ -642,15 +639,20 @@ getJasmineRequireObj().Env = function(j$) { reporter.clearReporters(); }; - var spyFactory = new j$.SpyFactory(function() { - var runnable = currentRunnable(); + var spyFactory = new j$.SpyFactory( + function getCustomStrategies() { + var runnable = currentRunnable(); - if (runnable) { - return runnableResources[runnable.id].customSpyStrategies; + if (runnable) { + return runnableResources[runnable.id].customSpyStrategies; + } + + return {}; + }, + function getPromise() { + return customPromise || global.Promise; } - - return {}; - }); + ); var spyRegistry = new j$.SpyRegistry({ currentSpies: function() { diff --git a/src/core/Spy.js b/src/core/Spy.js index 639d76f8..e4072f1b 100644 --- a/src/core/Spy.js +++ b/src/core/Spy.js @@ -13,7 +13,7 @@ getJasmineRequireObj().Spy = function (j$) { * @constructor * @name Spy */ - function Spy(name, originalFn, customStrategies) { + function Spy(name, originalFn, customStrategies, getPromise) { var numArgs = (typeof originalFn === 'function' ? originalFn.length : 0), wrapper = makeFunc(numArgs, function () { return spy.apply(this, Array.prototype.slice.call(arguments)); @@ -24,7 +24,8 @@ getJasmineRequireObj().Spy = function (j$) { getSpy: function () { return wrapper; }, - customStrategies: customStrategies + customStrategies: customStrategies, + getPromise: getPromise }), callTracker = new j$.CallTracker(), spy = function () { @@ -98,7 +99,6 @@ getJasmineRequireObj().Spy = function (j$) { return wrapper; } - function SpyStrategyDispatcher(strategyArgs) { var baseStrategy = new j$.SpyStrategy(strategyArgs); var argsStrategies = new StrategyDict(function() { diff --git a/src/core/SpyFactory.js b/src/core/SpyFactory.js index d4821321..4df28e55 100644 --- a/src/core/SpyFactory.js +++ b/src/core/SpyFactory.js @@ -1,10 +1,10 @@ getJasmineRequireObj().SpyFactory = function(j$) { - function SpyFactory(getCustomStrategies) { + function SpyFactory(getCustomStrategies, getPromise) { var self = this; this.createSpy = function(name, originalFn) { - return j$.Spy(name, originalFn, getCustomStrategies()); + return j$.Spy(name, originalFn, getCustomStrategies(), getPromise); }; this.createSpyObj = function(baseName, methodNames) { diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index 3aada4b2..7365f87c 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -6,6 +6,8 @@ getJasmineRequireObj().SpyStrategy = function(j$) { function SpyStrategy(options) { options = options || {}; + var self = this; + /** * Get the identifying information for the spy. * @name SpyStrategy#identity @@ -23,6 +25,46 @@ getJasmineRequireObj().SpyStrategy = function(j$) { this[k] = createCustomPlan(cs[k]); } } + + var getPromise = (typeof options.getPromise === 'function') ? options.getPromise : function() {}; + + var requirePromise = function(name) { + var Promise = getPromise(); + + if (!Promise) { + throw new Error(name + ' requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); + } + + return Promise; + }; + + /** + * Tell the spy to return a promise resolving to the specified value when invoked. + * @name SpyStrategy#resolveValue + * @function + * @param {*} value The value to return. + */ + this.resolveValue = function(value) { + var Promise = requirePromise('resolveValue'); + self.plan = function() { + return Promise.resolve(value); + }; + return self.getSpy(); + }; + + /** + * Tell the spy to return a promise rejecting with the specified value when invoked. + * @name SpyStrategy#rejectValue + * @function + * @param {*} value The value to return. + */ + this.rejectValue = function(value) { + var Promise = requirePromise('rejectValue'); + self.plan = function() { + return Promise.reject(value); + }; + return self.getSpy(); + }; } function createCustomPlan(factory) { @@ -84,44 +126,6 @@ getJasmineRequireObj().SpyStrategy = function(j$) { return this.getSpy(); }; - /** - * Tell the spy to return a promise resolving to the specified value when invoked. - * @name SpyStrategy#resolveValue - * @function - * @param {*} value The value to return. - */ - SpyStrategy.prototype.resolveValue = function(value) { - var Promise = j$.getPromise(); - - if (!Promise) { - throw new Error('resolveValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); - } - - this.plan = function() { - return Promise.resolve(value); - }; - return this.getSpy(); - }; - - /** - * Tell the spy to return a promise rejecting with the specified value when invoked. - * @name SpyStrategy#rejectValue - * @function - * @param {*} value The value to return. - */ - SpyStrategy.prototype.rejectValue = function(value) { - var Promise = j$.getPromise(); - - if (!Promise) { - throw new Error('rejectValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); - } - - this.plan = function() { - return Promise.reject(value); - }; - return this.getSpy(); - }; - /** * Tell the spy to throw an error when invoked. * @name SpyStrategy#throwError diff --git a/src/core/base.js b/src/core/base.js index 6609ef81..3a584f09 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -45,10 +45,6 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return env; }; - j$.getPromise = function() { - return j$.getEnv().getPromise() || j$.getGlobal().Promise; - }; - j$.isArray_ = function(value) { return j$.isA_('Array', value); };