diff --git a/RELEASE.md b/RELEASE.md index 6762af90..47f32104 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -36,7 +36,7 @@ When ready to release - specs are all green and the stories are done: ### Commit and push core changes 1. Run the browser tests using `scripts/run-all-browsers`. -1. Commit release notes and version changes (jasmine.js, version.rb, package.json) +1. Commit release notes and version changes (jasmine.js, package.json) 1. Push 1. Wait for Circle CI to go green diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 717d0c2d..acbe32c8 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -8035,7 +8035,10 @@ getJasmineRequireObj().QueueRunner = function(j$) { maybeThenable = queueableFn.fn.call(self.userContext); if (maybeThenable && j$.isFunction_(maybeThenable.then)) { - maybeThenable.then(next, onPromiseRejection); + maybeThenable.then( + wrapInPromiseResolutionHandler(next), + onPromiseRejection + ); completedSynchronously = false; return { completedSynchronously: false }; } @@ -8134,6 +8137,16 @@ getJasmineRequireObj().QueueRunner = function(j$) { } }; + function wrapInPromiseResolutionHandler(fn) { + return function(maybeArg) { + if (j$.isError_(maybeArg)) { + fn(maybeArg); + } else { + fn(); + } + }; + } + return QueueRunner; }; @@ -10190,5 +10203,5 @@ getJasmineRequireObj().UserContext = function(j$) { }; getJasmineRequireObj().version = function() { - return '4.0.0'; + return '4.0.1'; }; diff --git a/package.json b/package.json index dd9b0cf8..e5ed1ff5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jasmine-core", "license": "MIT", - "version": "4.0.0", + "version": "4.0.1", "repository": { "type": "git", "url": "https://github.com/jasmine/jasmine.git" diff --git a/release_notes/3.99.1.md b/release_notes/3.99.1.md new file mode 100644 index 00000000..263a15a9 --- /dev/null +++ b/release_notes/3.99.1.md @@ -0,0 +1,22 @@ +# Jasmine Core 3.99.1 Release Notes + +This release fixes a bug in 3.99.0, which incorrectly reported a deprecation +warning when a promise returned from a function passed to `it`, `beforeEach`, +etc was resolved to a value. + +## Supported environments + +jasmine-core 3.99.1 has been tested in the following environments. + +| Environment | Supported versions | +|-------------------|--------------------| +| Node | 10, 12, 14, 16 | +| Safari | 10-14 | +| Chrome | 98 | +| Firefox | 97, 78, 68 | +| Edge | 98 | +| Internet Explorer | 10, 11 | + +------ + +_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_ diff --git a/release_notes/4.0.1.md b/release_notes/4.0.1.md new file mode 100644 index 00000000..151beeb1 --- /dev/null +++ b/release_notes/4.0.1.md @@ -0,0 +1,21 @@ +# Jasmine Core 4.0.1 Release Notes + +This release fixes a bug in 4.0.0, which incorrectly reported a failure +when a promise returned from a function passed to `it`, `beforeEach`, +etc was resolved to a value. + +## Supported environments + +jasmine-core 4.0.1 has been tested in the following environments. + +| Environment | Supported versions | +|-------------------|--------------------| +| Node | 12.17+, 14, 16 | +| Safari | 14-15 | +| Chrome | 98 | +| Firefox | 91, 97 | +| Edge | 98 | + +------ + +_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_ diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index 5adf6ea7..b098f378 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -156,6 +156,81 @@ describe('QueueRunner', function() { expect(failFn).toHaveBeenCalledWith(err); expect(queueableFn2.fn).toHaveBeenCalled(); }); + + describe('as a result of a promise', function() { + describe('and the argument is an Error', function() { + // Since promise support was added, Jasmine has failed specs that + // return a promise that resolves to an error. That's probably not + // the desired behavior but it's also not something we should change + // except on a major release and with a deprecation warning in + // advance. + it('explicitly fails and moves to the next function', function(done) { + var err = new Error('foo'), + queueableFn1 = { + fn: function() { + return Promise.resolve(err); + } + }, + queueableFn2 = { fn: jasmine.createSpy('fn2') }, + failFn = jasmine.createSpy('fail'), + queueRunner = new jasmineUnderTest.QueueRunner({ + queueableFns: [queueableFn1, queueableFn2], + fail: failFn, + onComplete: function() { + expect(failFn).toHaveBeenCalledWith(err); + expect(queueableFn2.fn).toHaveBeenCalled(); + done(); + } + }); + + queueRunner.execute(); + }); + + it('does not log a deprecation', function(done) { + var err = new Error('foo'), + queueableFn1 = { + fn: function() { + return Promise.resolve(err); + } + }, + deprecated = jasmine.createSpy('deprecated'), + queueRunner = new jasmineUnderTest.QueueRunner({ + queueableFns: [queueableFn1], + deprecated: deprecated, + onComplete: function() { + expect(deprecated).not.toHaveBeenCalled(); + done(); + } + }); + + queueRunner.execute(); + }); + }); + + describe('and the argument is not an Error', function() { + it('does not log a deprecation or report a failure', function(done) { + var queueableFn1 = { + fn: function() { + return Promise.resolve('not an error'); + } + }, + failFn = jasmine.createSpy('fail'), + deprecated = jasmine.createSpy('deprecated'), + queueRunner = new jasmineUnderTest.QueueRunner({ + queueableFns: [queueableFn1], + deprecated: deprecated, + fail: failFn, + onComplete: function() { + expect(deprecated).not.toHaveBeenCalled(); + expect(failFn).not.toHaveBeenCalled(); + done(); + } + }); + + queueRunner.execute(); + }); + }); + }); }); it('does not cause an explicit fail if execution is being stopped', function() { diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index ebf3b5c3..7896529b 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -177,7 +177,10 @@ getJasmineRequireObj().QueueRunner = function(j$) { maybeThenable = queueableFn.fn.call(self.userContext); if (maybeThenable && j$.isFunction_(maybeThenable.then)) { - maybeThenable.then(next, onPromiseRejection); + maybeThenable.then( + wrapInPromiseResolutionHandler(next), + onPromiseRejection + ); completedSynchronously = false; return { completedSynchronously: false }; } @@ -276,5 +279,15 @@ getJasmineRequireObj().QueueRunner = function(j$) { } }; + function wrapInPromiseResolutionHandler(fn) { + return function(maybeArg) { + if (j$.isError_(maybeArg)) { + fn(maybeArg); + } else { + fn(); + } + }; + } + return QueueRunner; };