diff --git a/.circleci/config.yml b/.circleci/config.yml index bdfa47ce..0d3eab9e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,25 +3,22 @@ version: 2.1 -orbs: - node: circleci/node@3.0.0 - executors: node16: docker: - - image: cimg/node:16.1.0-browsers + - image: cimg/node:16.14.0 # Latest 16.x working_directory: ~/workspace node14: docker: - - image: circleci/node:14 + - image: cimg/node:14.17.4 # Latest 14.x working_directory: ~/workspace node12_latest: docker: - - image: circleci/node:12 + - image: cimg/node:12.22.10 # Latest 12.x working_directory: ~/workspace node12_17: docker: - - image: circleci/node:12.17 + - image: cimg/node:12.17.0 # Oldest version supported by Jasmine working_directory: ~/workspace jobs: 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..c71314df 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -7492,7 +7492,7 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { this.emitScalar(''); } else if (value.jasmineToString) { this.emitScalar(value.jasmineToString(this.pp_)); - } else if (typeof value === 'string') { + } else if (j$.isString_(value)) { this.emitString(value); } else if (j$.isSpy(value)) { this.emitScalar('spy on ' + value.and.identity); @@ -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/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index ed239191..3b74e0de 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -5,6 +5,14 @@ describe('PrettyPrinter', function() { expect(pp("som' string")).toEqual("'som' string'"); }); + it('stringifies empty string primitives and objects recognizably', function() { + const pp = jasmineUnderTest.makePrettyPrinter(); + expect(pp(new String(''))).toEqual(pp('')); + expect(pp(new String(''))).toEqual("''"); + expect(pp([new String('')])).toEqual(pp([''])); + expect(pp([new String('')])).toEqual("[ '' ]"); + }); + it('should stringify primitives properly', function() { var pp = jasmineUnderTest.makePrettyPrinter(); expect(pp(true)).toEqual('true'); 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/PrettyPrinter.js b/src/core/PrettyPrinter.js index 5faa3bbf..1903b469 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -40,7 +40,7 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { this.emitScalar(''); } else if (value.jasmineToString) { this.emitScalar(value.jasmineToString(this.pp_)); - } else if (typeof value === 'string') { + } else if (j$.isString_(value)) { this.emitString(value); } else if (j$.isSpy(value)) { this.emitScalar('spy on ' + value.and.identity); 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; };