From 72aa0bbe4d7f230cc9c202d302f25a71408abe5a Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Sun, 5 May 2019 08:08:34 -0400 Subject: [PATCH 1/5] Add resolveValue and rejectValue spy strategies --- spec/core/EnvSpec.js | 17 +++++++++++ spec/core/SpyStrategySpec.js | 56 ++++++++++++++++++++++++++++++++++++ spec/core/baseSpec.js | 15 ++++++++++ src/core/Env.js | 24 +++++++++++++++- src/core/SpyStrategy.js | 38 ++++++++++++++++++++++++ src/core/base.js | 4 +++ 6 files changed, 153 insertions(+), 1 deletion(-) diff --git a/spec/core/EnvSpec.js b/spec/core/EnvSpec.js index f731d36b..3b34e2e2 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -46,6 +46,23 @@ describe("Env", function() { })); }); + it('can configure a custom promise library', function() { + var myLibrary = { resolve: jasmine.createSpy(), reject: jasmine.createSpy() }; + expect(env.getPromise()).toBeUndefined(); + + env.configure({ promiseLibrary: myLibrary }); + expect(env.getPromise()).toBe(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'); + }); + it('defaults to multiple failures for specs', function() { spyOn(jasmineUnderTest, 'Spec'); env.it('bar', function() {}); diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index 10e4f583..25078e4c 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -110,6 +110,62 @@ describe("SpyStrategy", function() { }) }); + describe("#resolveValue", function() { + it("allows a resolved promise to be returned", function(done) { + if (!jasmineUnderTest.getPromise()) { + pending('Environment does not support promises.'); + } + + var originalFn = jasmine.createSpy("original"), + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); + + spyStrategy.resolveValue(37); + spyStrategy.exec().then(function (returnValue) { + expect(returnValue).toEqual(37); + done(); + }).catch(done.fail); + }); + + it("fails if promises are not available", function() { + var originalFn = jasmine.createSpy("original"), + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); + + spyOn(jasmineUnderTest, 'getPromise'); + + expect(function() { + spyStrategy.resolveValue(37); + }).toThrowError('resolveValue is unavailable because the environment does not support promises.'); + }); + }); + + describe("#rejectValue", function() { + it("allows a rejected promise to be returned", function(done) { + if (!jasmineUnderTest.getPromise()) { + pending('Environment does not support promises.'); + } + + var originalFn = jasmine.createSpy("original"), + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); + + spyStrategy.rejectValue(new Error('oops')); + spyStrategy.exec().then(done.fail).catch(function (error) { + expect(error).toEqual(new Error('oops')); + done(); + }).catch(done.fail); + }); + + it("fails if promises are not available", function() { + var originalFn = jasmine.createSpy("original"), + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); + + spyOn(jasmineUnderTest, 'getPromise'); + + expect(function() { + spyStrategy.rejectValue(new Error('oops')); + }).toThrowError('rejectValue is unavailable because the environment does not support promises.'); + }); + }); + it("allows a custom strategy to be used", function() { var plan = jasmine.createSpy('custom strategy') .and.returnValue('custom strategy result'), diff --git a/spec/core/baseSpec.js b/spec/core/baseSpec.js index 7f17265b..d7be476f 100644 --- a/spec/core/baseSpec.js +++ b/spec/core/baseSpec.js @@ -27,4 +27,19 @@ 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 680d0d49..7841fe34 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -76,7 +76,16 @@ getJasmineRequireObj().Env = function(j$) { * @type Boolean * @default false */ - hideDisabled: false + 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 + * library is available (if any). + * @name Configuration#promiseLibrary + * @type function + * @default undefined + */ + promiseLibrary: undefined }; var currentSuite = function() { @@ -142,6 +151,15 @@ getJasmineRequireObj().Env = function(j$) { if (configuration.hasOwnProperty('hideDisabled')) { config.hideDisabled = configuration.hideDisabled; } + + if (configuration.hasOwnProperty('promiseLibrary')) { + if (typeof configuration.promiseLibrary.resolve === 'function' && + typeof configuration.promiseLibrary.reject === 'function') { + config.promiseLibrary = configuration.promiseLibrary; + } else { + throw new Error('Custom promise library missing `resolve`/`reject` functions'); + } + } }; /** @@ -193,6 +211,10 @@ getJasmineRequireObj().Env = function(j$) { } }; + this.getPromise = function() { + return config.promiseLibrary; + }; + j$.Expectation.addCoreMatchers(j$.matchers); j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers); diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index ae5d4451..27a42f8e 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -84,6 +84,44 @@ 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 is unavailable because the environment does not support promises.'); + } + + 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 is unavailable because the environment does not support promises.'); + } + + 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 3a584f09..6609ef81 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -45,6 +45,10 @@ 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); }; From 95e1890e647dff97b593be4bc1b390c389f3cb09 Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Tue, 7 May 2019 16:30:48 -0400 Subject: [PATCH 2/5] Improved resolveValue/rejectValue error messages --- spec/core/SpyStrategySpec.js | 12 ++++-------- src/core/SpyStrategy.js | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index 25078e4c..cedc5338 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -112,9 +112,7 @@ describe("SpyStrategy", function() { describe("#resolveValue", function() { it("allows a resolved promise to be returned", function(done) { - if (!jasmineUnderTest.getPromise()) { - pending('Environment does not support promises.'); - } + jasmine.getEnv().requirePromises(); var originalFn = jasmine.createSpy("original"), spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); @@ -134,15 +132,13 @@ describe("SpyStrategy", function() { expect(function() { spyStrategy.resolveValue(37); - }).toThrowError('resolveValue is unavailable because the environment does not support promises.'); + }).toThrowError('resolveValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); }); }); describe("#rejectValue", function() { it("allows a rejected promise to be returned", function(done) { - if (!jasmineUnderTest.getPromise()) { - pending('Environment does not support promises.'); - } + jasmine.getEnv().requirePromises(); var originalFn = jasmine.createSpy("original"), spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); @@ -162,7 +158,7 @@ describe("SpyStrategy", function() { expect(function() { spyStrategy.rejectValue(new Error('oops')); - }).toThrowError('rejectValue is unavailable because the environment does not support promises.'); + }).toThrowError('rejectValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); }); }); diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index 27a42f8e..3aada4b2 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -94,7 +94,7 @@ getJasmineRequireObj().SpyStrategy = function(j$) { var Promise = j$.getPromise(); if (!Promise) { - throw new Error('resolveValue is unavailable because the environment does not support promises.'); + throw new Error('resolveValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); } this.plan = function() { @@ -113,7 +113,7 @@ getJasmineRequireObj().SpyStrategy = function(j$) { var Promise = j$.getPromise(); if (!Promise) { - throw new Error('rejectValue is unavailable because the environment does not support promises.'); + throw new Error('rejectValue requires global Promise, or a `promiseLibrary` configured with `jasmine.getEnv().configure()`'); } this.plan = function() { From 4731b4ee4d215a28db291e3ab6c878a17ad6f39d Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Wed, 8 May 2019 09:07:01 -0400 Subject: [PATCH 3/5] Keep all Promise implementation details internal --- spec/core/EnvSpec.js | 24 +++++------ spec/core/SpySpec.js | 24 ++++++++++- spec/core/SpyStrategySpec.js | 14 +++---- spec/core/baseSpec.js | 15 ------- src/core/Env.js | 38 +++++++++-------- src/core/Spy.js | 6 +-- src/core/SpyFactory.js | 4 +- src/core/SpyStrategy.js | 80 +++++++++++++++++++----------------- src/core/base.js | 4 -- 9 files changed, 107 insertions(+), 102 deletions(-) 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); }; From df818f3fbcdec59aadee88dd72efb512dcc70170 Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Wed, 8 May 2019 09:36:12 -0400 Subject: [PATCH 4/5] rejectValue wraps non-Errors like throwError does --- spec/core/SpyStrategySpec.js | 14 ++++++++++++++ src/core/SpyStrategy.js | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index ab13e4ab..f299792a 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -150,6 +150,20 @@ describe("SpyStrategy", function() { }).catch(done.fail); }); + it("allows a non-Error to be rejected, wrapping it in an exception when executed", function(done) { + jasmine.getEnv().requirePromises(); + + var originalFn = jasmine.createSpy("original"), + getPromise = function() { return Promise; }, + spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn, getPromise: getPromise}); + + spyStrategy.rejectValue('oops'); + spyStrategy.exec().then(done.fail).catch(function (error) { + expect(error).toEqual(new Error('oops')); + done(); + }).catch(done.fail); + }); + it("fails if promises are not available", function() { var originalFn = jasmine.createSpy("original"), spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index 7365f87c..b8a3db88 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -60,8 +60,10 @@ getJasmineRequireObj().SpyStrategy = function(j$) { */ this.rejectValue = function(value) { var Promise = requirePromise('rejectValue'); + var error = (value instanceof Error) ? value : new Error(value); + self.plan = function() { - return Promise.reject(value); + return Promise.reject(error); }; return self.getSpy(); }; From b2fb92eedd1fe017cfe154b04e04abdad34b3e19 Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Thu, 9 May 2019 06:12:06 -0400 Subject: [PATCH 5/5] Promise-based strategies are now named resolveWith and rejectWith --- spec/core/SpySpec.js | 4 ++-- spec/core/SpyStrategySpec.js | 18 +++++++++--------- src/core/SpyStrategy.js | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/spec/core/SpySpec.js b/spec/core/SpySpec.js index e12a9d83..04734e2f 100644 --- a/spec/core/SpySpec.js +++ b/spec/core/SpySpec.js @@ -175,7 +175,7 @@ describe('Spies', function () { it('works with global Promise library when available', function(done) { jasmine.getEnv().requirePromises(); - var spy = env.createSpy('foo').and.resolveValue(42); + var spy = env.createSpy('foo').and.resolveWith(42); spy().then(function(result) { expect(result).toEqual(42); done(); @@ -187,7 +187,7 @@ describe('Spies', function () { customPromise.resolve.and.returnValue('resolved'); env.configure({ Promise: customPromise }); - var spy = env.createSpy('foo').and.resolveValue(42); + var spy = env.createSpy('foo').and.resolveWith(42); expect(spy()).toEqual('resolved'); expect(customPromise.resolve).toHaveBeenCalledWith(42); }); diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index f299792a..709c268b 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -110,7 +110,7 @@ describe("SpyStrategy", function() { }) }); - describe("#resolveValue", function() { + describe("#resolveWith", function() { it("allows a resolved promise to be returned", function(done) { jasmine.getEnv().requirePromises(); @@ -118,7 +118,7 @@ describe("SpyStrategy", function() { getPromise = function() { return Promise; }, spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn, getPromise: getPromise}); - spyStrategy.resolveValue(37); + spyStrategy.resolveWith(37); spyStrategy.exec().then(function (returnValue) { expect(returnValue).toEqual(37); done(); @@ -130,12 +130,12 @@ describe("SpyStrategy", function() { spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); expect(function() { - spyStrategy.resolveValue(37); - }).toThrowError('resolveValue requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); + spyStrategy.resolveWith(37); + }).toThrowError('resolveWith requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); }); }); - describe("#rejectValue", function() { + describe("#rejectWith", function() { it("allows a rejected promise to be returned", function(done) { jasmine.getEnv().requirePromises(); @@ -143,7 +143,7 @@ describe("SpyStrategy", function() { getPromise = function() { return Promise; }, spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn, getPromise: getPromise}); - spyStrategy.rejectValue(new Error('oops')); + spyStrategy.rejectWith(new Error('oops')); spyStrategy.exec().then(done.fail).catch(function (error) { expect(error).toEqual(new Error('oops')); done(); @@ -157,7 +157,7 @@ describe("SpyStrategy", function() { getPromise = function() { return Promise; }, spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn, getPromise: getPromise}); - spyStrategy.rejectValue('oops'); + spyStrategy.rejectWith('oops'); spyStrategy.exec().then(done.fail).catch(function (error) { expect(error).toEqual(new Error('oops')); done(); @@ -169,8 +169,8 @@ describe("SpyStrategy", function() { spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}); expect(function() { - spyStrategy.rejectValue(new Error('oops')); - }).toThrowError('rejectValue requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); + spyStrategy.rejectWith(new Error('oops')); + }).toThrowError('rejectWith requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'); }); }); diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index b8a3db88..5a785d4f 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -40,12 +40,12 @@ getJasmineRequireObj().SpyStrategy = function(j$) { /** * Tell the spy to return a promise resolving to the specified value when invoked. - * @name SpyStrategy#resolveValue + * @name SpyStrategy#resolveWith * @function * @param {*} value The value to return. */ - this.resolveValue = function(value) { - var Promise = requirePromise('resolveValue'); + this.resolveWith = function(value) { + var Promise = requirePromise('resolveWith'); self.plan = function() { return Promise.resolve(value); }; @@ -54,12 +54,12 @@ getJasmineRequireObj().SpyStrategy = function(j$) { /** * Tell the spy to return a promise rejecting with the specified value when invoked. - * @name SpyStrategy#rejectValue + * @name SpyStrategy#rejectWith * @function * @param {*} value The value to return. */ - this.rejectValue = function(value) { - var Promise = requirePromise('rejectValue'); + this.rejectWith = function(value) { + var Promise = requirePromise('rejectWith'); var error = (value instanceof Error) ? value : new Error(value); self.plan = function() {