From 076093c16c9641882c4089438de34554b343fd69 Mon Sep 17 00:00:00 2001 From: Adam Milligan Date: Mon, 4 Nov 2019 11:38:53 -0500 Subject: [PATCH 01/57] Properly import jasmineRequire object before using --- lib/jasmine-core/boot.js | 1 + lib/jasmine-core/jasmine-html.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/lib/jasmine-core/boot.js b/lib/jasmine-core/boot.js index aa501180..fcd11f1b 100644 --- a/lib/jasmine-core/boot.js +++ b/lib/jasmine-core/boot.js @@ -31,6 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function() { + var jasmineRequire = window.jasmineRequire || require('./jasmine.js'); /** * ## Require & Instantiate diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index aecf2f1b..d08611de 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -20,6 +20,9 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +var jasmineRequire = window.jasmineRequire || require('./jasmine.js'); + jasmineRequire.html = function(j$) { j$.ResultsNode = jasmineRequire.ResultsNode(); j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); From 3d1a96e020e97ceb20d3944fdd42bad81509e0b2 Mon Sep 17 00:00:00 2001 From: Adam Milligan Date: Tue, 5 Nov 2019 10:54:46 -0500 Subject: [PATCH 02/57] Extend Jasmine env into correct global --- lib/jasmine-core/boot.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/boot.js b/lib/jasmine-core/boot.js index fcd11f1b..b46871cf 100644 --- a/lib/jasmine-core/boot.js +++ b/lib/jasmine-core/boot.js @@ -38,7 +38,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. */ - window.jasmine = jasmineRequire.core(jasmineRequire); + var jasmine = jasmineRequire.core(jasmineRequire), + global = jasmine.getGlobal(); + global.jasmine = jasmine; /** * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. @@ -60,7 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. */ - extend(window, jasmineInterface); + extend(global, jasmineInterface); /** * ## Runner Parameters From 13ff1e037e86378a8aa49e7a0003c96c86a7a905 Mon Sep 17 00:00:00 2001 From: Adam Milligan Date: Fri, 22 Nov 2019 17:47:20 -0500 Subject: [PATCH 03/57] Make changes in source files --- lib/jasmine-core/boot/boot.js | 7 +++++-- lib/jasmine-core/jasmine-html.js | 1 - src/html/requireHtml.js | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/jasmine-core/boot/boot.js b/lib/jasmine-core/boot/boot.js index 2d684628..e1e20f1c 100644 --- a/lib/jasmine-core/boot/boot.js +++ b/lib/jasmine-core/boot/boot.js @@ -9,13 +9,16 @@ */ (function() { + var jasmineRequire = window.jasmineRequire || require('./jasmine.js'); /** * ## Require & Instantiate * * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. */ - window.jasmine = jasmineRequire.core(jasmineRequire); + var jasmine = jasmineRequire.core(jasmineRequire), + global = jasmine.getGlobal(); + global.jasmine = jasmine; /** * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. @@ -37,7 +40,7 @@ /** * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. */ - extend(window, jasmineInterface); + extend(global, jasmineInterface); /** * ## Runner Parameters diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index d08611de..a727d01e 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -20,7 +20,6 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - var jasmineRequire = window.jasmineRequire || require('./jasmine.js'); jasmineRequire.html = function(j$) { diff --git a/src/html/requireHtml.js b/src/html/requireHtml.js index b60c3ba5..a8fe2a1e 100644 --- a/src/html/requireHtml.js +++ b/src/html/requireHtml.js @@ -1,3 +1,5 @@ +var jasmineRequire = window.jasmineRequire || require('./jasmine.js'); + jasmineRequire.html = function(j$) { j$.ResultsNode = jasmineRequire.ResultsNode(); j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); From 6c68715554463446ee0feeb849c8fbc7f5162e4d Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 13 Feb 2020 09:26:33 -0800 Subject: [PATCH 04/57] Removed unnecessary uses of new --- .../async/toBeRejectedWithErrorSpec.js | 24 +++++++++---------- .../core/matchers/async/toBeResolvedToSpec.js | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spec/core/matchers/async/toBeRejectedWithErrorSpec.js b/spec/core/matchers/async/toBeRejectedWithErrorSpec.js index 97260d59..71c53d55 100644 --- a/spec/core/matchers/async/toBeRejectedWithErrorSpec.js +++ b/spec/core/matchers/async/toBeRejectedWithErrorSpec.js @@ -2,7 +2,7 @@ describe('#toBeRejectedWithError', function () { it('passes when Error type matches', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new TypeError('foo')); @@ -17,7 +17,7 @@ describe('#toBeRejectedWithError', function () { it('passes when Error type and message matches', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new TypeError('foo')); @@ -32,7 +32,7 @@ describe('#toBeRejectedWithError', function () { it('passes when Error matches and is exactly Error', function() { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error()); @@ -48,7 +48,7 @@ describe('#toBeRejectedWithError', function () { it('passes when Error message matches a string', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error('foo')); @@ -63,7 +63,7 @@ describe('#toBeRejectedWithError', function () { it('passes when Error message matches a RegExp', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error('foo')); @@ -78,7 +78,7 @@ describe('#toBeRejectedWithError', function () { it('passes when Error message is empty', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error()); @@ -93,7 +93,7 @@ describe('#toBeRejectedWithError', function () { it('passes when no arguments', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error()); @@ -108,7 +108,7 @@ describe('#toBeRejectedWithError', function () { it('fails when resolved', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.resolve(new Error('foo')); @@ -123,7 +123,7 @@ describe('#toBeRejectedWithError', function () { it('fails when rejected with non Error type', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject('foo'); @@ -138,7 +138,7 @@ describe('#toBeRejectedWithError', function () { it('fails when Error type mismatches', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error('foo')); @@ -153,7 +153,7 @@ describe('#toBeRejectedWithError', function () { it('fails when Error message mismatches', function () { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = Promise.reject(new Error('foo')); @@ -166,7 +166,7 @@ describe('#toBeRejectedWithError', function () { }); it('fails if actual is not a promise', function() { - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWithError(matchersUtil), actual = 'not a promise'; diff --git a/spec/core/matchers/async/toBeResolvedToSpec.js b/spec/core/matchers/async/toBeResolvedToSpec.js index c68eb0e0..b721c89e 100644 --- a/spec/core/matchers/async/toBeResolvedToSpec.js +++ b/spec/core/matchers/async/toBeResolvedToSpec.js @@ -14,7 +14,7 @@ describe('#toBeResolvedTo', function() { it('fails if the promise is rejected', function() { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(matchersUtil), actual = Promise.reject('AsyncExpectationSpec error'); @@ -29,7 +29,7 @@ describe('#toBeResolvedTo', function() { it('fails if the promise is resolved to a different value', function() { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(matchersUtil), actual = Promise.resolve({foo: 17}); @@ -44,7 +44,7 @@ describe('#toBeResolvedTo', function() { it('builds its message correctly when negated', function() { jasmine.getEnv().requirePromises(); - var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: new jasmineUnderTest.makePrettyPrinter()}), + var matchersUtil = new jasmineUnderTest.MatchersUtil({pp: jasmineUnderTest.makePrettyPrinter()}), matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(matchersUtil), actual = Promise.resolve(true); From a6a9550d1eacfc303d668d8c1901185b1e66bcf6 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 13 Feb 2020 10:52:54 -0800 Subject: [PATCH 05/57] Fixed 'since' versions for MatchersUtil --- lib/jasmine-core/jasmine.js | 4 +++- src/core/matchers/matchersUtil.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index c91846b4..79e8100b 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -4409,7 +4409,6 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * _Note:_ Do not construct this directly. Jasmine will construct one and * pass it to matchers and asymmetric equality testers. * @name MatchersUtil - * @since 2.0.0 * @classdesc Utilities for use in implementing matchers * @constructor */ @@ -4421,6 +4420,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * taking into account the current set of custom value formatters. * @function * @name MatchersUtil#pp + * @since 3.6.0 * @param {*} value The value to pretty-print * @return {string} The pretty-printed value */ @@ -4432,6 +4432,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * logic as {@link MatchersUtil#equals}. * @function * @name MatchersUtil#contains + * @since 2.0.0 * @param {*} haystack The collection to search * @param {*} needle The value to search for * @param [customTesters] An array of custom equality testers @@ -4524,6 +4525,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * Determines whether two values are deeply equal to each other. * @function * @name MatchersUtil#equals + * @since 2.0.0 * @param {*} a The first value to compare * @param {*} b The second value to compare * @param [customTesters] An array of custom equality testers diff --git a/src/core/matchers/matchersUtil.js b/src/core/matchers/matchersUtil.js index 8ee6368e..d473976d 100644 --- a/src/core/matchers/matchersUtil.js +++ b/src/core/matchers/matchersUtil.js @@ -5,7 +5,6 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * _Note:_ Do not construct this directly. Jasmine will construct one and * pass it to matchers and asymmetric equality testers. * @name MatchersUtil - * @since 2.0.0 * @classdesc Utilities for use in implementing matchers * @constructor */ @@ -17,6 +16,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * taking into account the current set of custom value formatters. * @function * @name MatchersUtil#pp + * @since 3.6.0 * @param {*} value The value to pretty-print * @return {string} The pretty-printed value */ @@ -28,6 +28,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * logic as {@link MatchersUtil#equals}. * @function * @name MatchersUtil#contains + * @since 2.0.0 * @param {*} haystack The collection to search * @param {*} needle The value to search for * @param [customTesters] An array of custom equality testers @@ -120,6 +121,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { * Determines whether two values are deeply equal to each other. * @function * @name MatchersUtil#equals + * @since 2.0.0 * @param {*} a The first value to compare * @param {*} b The second value to compare * @param [customTesters] An array of custom equality testers From 93ad31e0af4c01e4e80539899ecd4cecb1279bc9 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 22 Feb 2020 13:54:24 -0800 Subject: [PATCH 06/57] Correctly report spec and suite duration Previously, suite duration was always reported as 0 and spec duration was always reported as null. Suites always used a no-op timer, and specs set their result.duration after the result had already been sent to reporters. Fixes #1676. --- lib/jasmine-core/jasmine.js | 19 +++--------- spec/core/SpecSpec.js | 27 +++++++++++------ spec/core/integration/EnvSpec.js | 52 ++++++++++++++++++++++++++++++++ src/core/Env.js | 1 + src/core/JsApiReporter.js | 2 +- src/core/Spec.js | 4 +-- src/core/Suite.js | 2 +- src/core/Timer.js | 9 ------ src/core/requireCore.js | 1 - 9 files changed, 80 insertions(+), 37 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 79e8100b..0e6c91d4 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -71,7 +71,6 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.Expector = jRequire.Expector(j$); j$.Expectation = jRequire.Expectation(j$); j$.buildExpectationResult = jRequire.buildExpectationResult(j$); - j$.noopTimer = jRequire.noopTimer(); j$.JsApiReporter = jRequire.JsApiReporter(j$); j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim( j$ @@ -681,7 +680,7 @@ getJasmineRequireObj().Spec = function(j$) { return true; }; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; - this.timer = attrs.timer || j$.noopTimer; + this.timer = attrs.timer || new j$.Timer(); if (!this.queueableFn.fn) { this.pend(); @@ -746,6 +745,7 @@ getJasmineRequireObj().Spec = function(j$) { fn: function(done) { self.queueableFn.fn = null; self.result.status = self.status(excluded, failSpecWithNoExp); + self.result.duration = self.timer.elapsed(); self.resultCallback(self.result, done); } }; @@ -761,7 +761,6 @@ getJasmineRequireObj().Spec = function(j$) { self.onException.apply(self, arguments); }, onComplete: function() { - self.result.duration = self.timer.elapsed(); onComplete( self.result.status === 'failed' && new j$.StopExecutionError('spec failed') @@ -1878,6 +1877,7 @@ getJasmineRequireObj().Env = function(j$) { id: getNextSuiteId(), description: description, parentSuite: currentDeclarationSuite, + timer: new j$.Timer(), expectationFactory: expectationFactory, asyncExpectationFactory: suiteAsyncExpectationFactory, expectationResultFactory: expectationResultFactory, @@ -2166,7 +2166,7 @@ getJasmineRequireObj().JsApiReporter = function(j$) { * @hideconstructor */ function JsApiReporter(options) { - var timer = options.timer || j$.noopTimer, + var timer = options.timer || new j$.Timer(), status = 'loaded'; this.started = false; @@ -8246,7 +8246,7 @@ getJasmineRequireObj().Suite = function(j$) { this.beforeAllFns = []; this.afterAllFns = []; - this.timer = attrs.timer || j$.noopTimer; + this.timer = attrs.timer || new j$.Timer(); this.children = []; @@ -8449,15 +8449,6 @@ getJasmineRequireObj().Timer = function() { return Timer; }; -getJasmineRequireObj().noopTimer = function() { - return { - start: function() {}, - elapsed: function() { - return 0; - } - }; -}; - getJasmineRequireObj().TreeProcessor = function() { function TreeProcessor(attrs) { var tree = attrs.tree, diff --git a/spec/core/SpecSpec.js b/spec/core/SpecSpec.js index 8219a1cd..38a8e780 100644 --- a/spec/core/SpecSpec.js +++ b/spec/core/SpecSpec.js @@ -227,7 +227,7 @@ describe('Spec', function() { passedExpectations: [], deprecationWarnings: [], pendingReason: '', - duration: null + duration: jasmine.any(Number) }, 'things' ); @@ -273,21 +273,30 @@ describe('Spec', function() { }); it('should report the duration of the test', function() { - var done = jasmine.createSpy('done callback'), - timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }), + var timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }), spec = new jasmineUnderTest.Spec({ queueableFn: { fn: jasmine.createSpy('spec body') }, catchExceptions: function() { return false; }, - resultCallback: function() {}, - queueRunnerFactory: function(attrs) { - attrs.onComplete(); + resultCallback: function(result) { + duration = result.duration; + }, + queueRunnerFactory: function(config) { + config.queueableFns.forEach(function(qf) { + qf.fn(); + }); + config.cleanupFns.forEach(function(qf) { + qf.fn(); + }); + config.onComplete(); }, timer: timer - }); - spec.execute(done); - expect(spec.result.duration).toBe(77000); + }), + duration = undefined; + + spec.execute(function() {}); + expect(duration).toBe(77000); }); it('#status returns passing by default', function() { diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index bd35817c..8c5c1941 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -616,6 +616,58 @@ describe("Env integration", function() { env.execute(); }); + + it('reports the duration of the suite', function(done) { + var duration; + + env.addReporter({ + suiteDone: function(result) { + expect(duration).toBeUndefined(); + duration = result.duration; + }, + jasmineDone: function() { + expect(duration).toBeGreaterThanOrEqual(10); + done(); + } + }); + + env.describe('my suite', function() { + env.it('takes time', function(done) { + // We can't just use the mock clock here because the timer is designed + // to record real time even when the mock clock is installed. + setTimeout(done, 10); + }) + }); + + env.execute(); + }); + }); + + describe('specDone reporting', function() { + it('reports the duration of the spec', function(done) { + var duration; + + env.addReporter({ + specDone: function(result) { + expect(duration).toBeUndefined(); + duration = result.duration; + }, + jasmineDone: function() { + expect(duration).toBeGreaterThanOrEqual(10); + done(); + } + }); + + env.describe('my suite', function() { + env.it('takes time', function(done) { + // We can't just use the mock clock here because the timer is designed + // to record real time even when the mock clock is installed. + setTimeout(done, 10); + }) + }); + + env.execute(); + }); }); it('reports expectation failures in global beforeAll', function(done) { diff --git a/src/core/Env.js b/src/core/Env.js index 2cb9c2cc..47915c0a 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -952,6 +952,7 @@ getJasmineRequireObj().Env = function(j$) { id: getNextSuiteId(), description: description, parentSuite: currentDeclarationSuite, + timer: new j$.Timer(), expectationFactory: expectationFactory, asyncExpectationFactory: suiteAsyncExpectationFactory, expectationResultFactory: expectationResultFactory, diff --git a/src/core/JsApiReporter.js b/src/core/JsApiReporter.js index 8875a45e..a498f388 100644 --- a/src/core/JsApiReporter.js +++ b/src/core/JsApiReporter.js @@ -6,7 +6,7 @@ getJasmineRequireObj().JsApiReporter = function(j$) { * @hideconstructor */ function JsApiReporter(options) { - var timer = options.timer || j$.noopTimer, + var timer = options.timer || new j$.Timer(), status = 'loaded'; this.started = false; diff --git a/src/core/Spec.js b/src/core/Spec.js index b8791890..db35de64 100644 --- a/src/core/Spec.js +++ b/src/core/Spec.js @@ -31,7 +31,7 @@ getJasmineRequireObj().Spec = function(j$) { return true; }; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; - this.timer = attrs.timer || j$.noopTimer; + this.timer = attrs.timer || new j$.Timer(); if (!this.queueableFn.fn) { this.pend(); @@ -96,6 +96,7 @@ getJasmineRequireObj().Spec = function(j$) { fn: function(done) { self.queueableFn.fn = null; self.result.status = self.status(excluded, failSpecWithNoExp); + self.result.duration = self.timer.elapsed(); self.resultCallback(self.result, done); } }; @@ -111,7 +112,6 @@ getJasmineRequireObj().Spec = function(j$) { self.onException.apply(self, arguments); }, onComplete: function() { - self.result.duration = self.timer.elapsed(); onComplete( self.result.status === 'failed' && new j$.StopExecutionError('spec failed') diff --git a/src/core/Suite.js b/src/core/Suite.js index 75104068..4d33ceaa 100644 --- a/src/core/Suite.js +++ b/src/core/Suite.js @@ -14,7 +14,7 @@ getJasmineRequireObj().Suite = function(j$) { this.beforeAllFns = []; this.afterAllFns = []; - this.timer = attrs.timer || j$.noopTimer; + this.timer = attrs.timer || new j$.Timer(); this.children = []; diff --git a/src/core/Timer.js b/src/core/Timer.js index 35ef9f32..ebe6983d 100644 --- a/src/core/Timer.js +++ b/src/core/Timer.js @@ -22,12 +22,3 @@ getJasmineRequireObj().Timer = function() { return Timer; }; - -getJasmineRequireObj().noopTimer = function() { - return { - start: function() {}, - elapsed: function() { - return 0; - } - }; -}; diff --git a/src/core/requireCore.js b/src/core/requireCore.js index e2d7ef87..df7f2571 100644 --- a/src/core/requireCore.js +++ b/src/core/requireCore.js @@ -49,7 +49,6 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.Expector = jRequire.Expector(j$); j$.Expectation = jRequire.Expectation(j$); j$.buildExpectationResult = jRequire.buildExpectationResult(j$); - j$.noopTimer = jRequire.noopTimer(); j$.JsApiReporter = jRequire.JsApiReporter(j$); j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim( j$ From 6440ca434d0bf41b687bd49145c9fb480f17eb6d Mon Sep 17 00:00:00 2001 From: Chives Date: Sat, 29 Feb 2020 04:30:03 -0500 Subject: [PATCH 07/57] Add trailing newlines to example code --- lib/jasmine-core/example/src/Player.js | 2 +- lib/jasmine-core/example/src/Song.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/example/src/Player.js b/lib/jasmine-core/example/src/Player.js index fcce8268..11851966 100644 --- a/lib/jasmine-core/example/src/Player.js +++ b/lib/jasmine-core/example/src/Player.js @@ -19,4 +19,4 @@ Player.prototype.resume = function() { Player.prototype.makeFavorite = function() { this.currentlyPlayingSong.persistFavoriteStatus(true); -}; \ No newline at end of file +}; diff --git a/lib/jasmine-core/example/src/Song.js b/lib/jasmine-core/example/src/Song.js index a8a3f2dd..02527cb1 100644 --- a/lib/jasmine-core/example/src/Song.js +++ b/lib/jasmine-core/example/src/Song.js @@ -4,4 +4,4 @@ function Song() { Song.prototype.persistFavoriteStatus = function(value) { // something complicated throw new Error("not yet implemented"); -}; \ No newline at end of file +}; From e13fd13529099e2f8b65d030c415435098258778 Mon Sep 17 00:00:00 2001 From: Maksym Kobieliev Date: Fri, 13 Mar 2020 20:41:24 +0200 Subject: [PATCH 08/57] Add a toHaveBeenCalledOnceWith matcher --- spec/core/integration/MatchersSpec.js | 16 ++++ .../matchers/toHaveBeenCalledOnceWithSpec.js | 89 +++++++++++++++++++ src/core/matchers/requireMatchers.js | 1 + src/core/matchers/toHaveBeenCalledOnceWith.js | 56 ++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 spec/core/matchers/toHaveBeenCalledOnceWithSpec.js create mode 100644 src/core/matchers/toHaveBeenCalledOnceWith.js diff --git a/spec/core/integration/MatchersSpec.js b/spec/core/integration/MatchersSpec.js index 25af3217..b0cf91f0 100644 --- a/spec/core/integration/MatchersSpec.js +++ b/spec/core/integration/MatchersSpec.js @@ -425,6 +425,22 @@ describe('Matchers (Integration)', function() { }); }); + describe('toHaveBeenCalledOnceWith', function() { + verifyPasses(function(env) { + var spy = env.createSpy(); + spy('5', 3); + env.addCustomEqualityTester(function(a, b) { + return a.toString() === b.toString(); + }); + env.expect(spy).toHaveBeenCalledOnceWith(5, 3); + }); + + verifyFails(function(env) { + var spy = env.createSpy(); + env.expect(spy).toHaveBeenCalledOnceWith(5, 3); + }); + }); + describe('toHaveClass', function() { beforeEach(function() { this.domHelpers = jasmine.getEnv().domHelpers(); diff --git a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js new file mode 100644 index 00000000..b3678bfb --- /dev/null +++ b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js @@ -0,0 +1,89 @@ +describe("toHaveBeenCalledOnceWith", function () { + + it("passes when the actual was called only once and with matching parameters", function () { + var util = jasmineUnderTest.matchersUtil, + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), + calledSpy = new jasmineUnderTest.Spy('called-spy'), + result; + + calledSpy('a', 'b'); + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected spy called-spy to have been called 0 times, multiple times, or once, but with arguments different from:\n [ 'a', 'b' ]\nBut the actual call was:\n [ 'a', 'b' ].\n\n"); + }); + + it("passes through the custom equality testers", function () { + var util = { + contains: jasmine.createSpy('delegated-contains').and.returnValue(false) + }, + customEqualityTesters = [function () { return true; }], + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util, customEqualityTesters), + calledSpy = new jasmineUnderTest.Spy('called-spy'); + + calledSpy('a', 'b'); + matcher.compare(calledSpy, 'a', 'b'); + + expect(util.contains).toHaveBeenCalledWith([['a', 'b']], ['a', 'b'], customEqualityTesters); + }); + + it("fails when the actual was never called", function () { + var util = jasmineUnderTest.matchersUtil, + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), + calledSpy = new jasmineUnderTest.Spy('called-spy'), + result; + + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected spy called-spy to have been called only once, and with given args:\n [ 'a', 'b' ]\nBut it was never called.\n\n"); + }); + + it("fails when the actual was called once with different parameters", function () { + var util = jasmineUnderTest.matchersUtil, + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), + calledSpy = new jasmineUnderTest.Spy('called-spy'), + result; + + calledSpy('a', 'c'); + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected spy called-spy to have been called only once, and with given args:\n [ 'a', 'b' ]\nBut the actual calls were:\n [ 'a', 'c' ].\n\n"); + }); + + it("fails when the actual was called multiple times with expected parameters", function () { + var util = jasmineUnderTest.matchersUtil, + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), + calledSpy = new jasmineUnderTest.Spy('called-spy'), + result; + + calledSpy('a', 'b'); + calledSpy('a', 'b'); + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected spy called-spy to have been called only once, and with given args:\n [ 'a', 'b' ]\nBut the actual calls were:\n [ 'a', 'b' ],\n [ 'a', 'b' ].\n\n"); + }); + + it("fails when the actual was called multiple times (one of them - with expected parameters)", function () { + var util = jasmineUnderTest.matchersUtil, + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), + calledSpy = new jasmineUnderTest.Spy('called-spy'), + result; + + calledSpy('a', 'b'); + calledSpy('a', 'c'); + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected spy called-spy to have been called only once, and with given args:\n [ 'a', 'b' ]\nBut the actual calls were:\n [ 'a', 'b' ],\n [ 'a', 'c' ].\n\n"); + }); + + it("throws an exception when the actual is not a spy", function () { + var matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(), + fn = function () { }; + + expect(function () { matcher.compare(fn) }).toThrowError(/Expected a spy, but got Function./); + }); +}); diff --git a/src/core/matchers/requireMatchers.js b/src/core/matchers/requireMatchers.js index e8b1fd58..4ff1f841 100644 --- a/src/core/matchers/requireMatchers.js +++ b/src/core/matchers/requireMatchers.js @@ -22,6 +22,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) { 'toEqual', 'toHaveBeenCalled', 'toHaveBeenCalledBefore', + 'toHaveBeenCalledOnceWith', 'toHaveBeenCalledTimes', 'toHaveBeenCalledWith', 'toHaveClass', diff --git a/src/core/matchers/toHaveBeenCalledOnceWith.js b/src/core/matchers/toHaveBeenCalledOnceWith.js new file mode 100644 index 00000000..ccd707c7 --- /dev/null +++ b/src/core/matchers/toHaveBeenCalledOnceWith.js @@ -0,0 +1,56 @@ +getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledOnceWith(...arguments)'); + + /** + * {@link expect} the actual (a {@link Spy}) to have been called exactly once, and exactly with the particular arguments. + * @function + * @name matchers#toHaveBeenCalledOnceWith + * @since 3.6.0 + * @param {...Object} - The arguments to look for + * @example + * expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar', 2); + */ + function toHaveBeenCalledOnceWith(util, customEqualityTesters) { + return { + compare: function () { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1); + + if (!j$.isSpy(actual)) { + throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); + } + + var prettyPrintedCalls = actual.calls.allArgs().map(function (argsForCall) { + return ' ' + j$.pp(argsForCall); + }); + + if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + return { + pass: true, + message: 'Expected spy ' + actual.and.identity + ' to have been called 0 times, multiple times, or once, but with arguments different from:\n' + + ' ' + j$.pp(expectedArgs) + '\n' + + 'But the actual call was:\n' + + prettyPrintedCalls.join(',\n') + '.\n\n' + }; + } + + function butString() { + return actual.calls.count() !== 0 + ? 'But the actual calls were:\n' + prettyPrintedCalls.join(',\n') + '.\n\n' + : 'But it was never called.\n\n'; + } + + return { + pass: false, + message: 'Expected spy ' + actual.and.identity + ' to have been called only once, and with given args:\n' + + ' ' + j$.pp(expectedArgs) + '\n' + + butString() + }; + } + }; + } + + return toHaveBeenCalledOnceWith; +}; From 66fe69a149e89456700ae2c1a71623b1fd24a1ad Mon Sep 17 00:00:00 2001 From: Chives Date: Mon, 16 Mar 2020 03:15:58 -0400 Subject: [PATCH 09/57] Add test for resolveTo/rejectWith with empty parameters --- spec/core/SpyStrategySpec.js | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index e861dc8b..5e454b64 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -140,6 +140,28 @@ describe('SpyStrategy', function() { .catch(done.fail); }); + it('allows an empty resolved promise to be returned', function(done) { + jasmine.getEnv().requirePromises(); + + var originalFn = jasmine.createSpy('original'), + getPromise = function() { + return Promise; + }, + spyStrategy = new jasmineUnderTest.SpyStrategy({ + fn: originalFn, + getPromise: getPromise + }); + + spyStrategy.resolveTo(); + spyStrategy + .exec() + .then(function(returnValue) { + expect(returnValue).toBe(); + done(); + }) + .catch(done.fail); + }); + it('fails if promises are not available', function() { var originalFn = jasmine.createSpy('original'), spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }); @@ -176,6 +198,29 @@ describe('SpyStrategy', function() { .catch(done.fail); }); + it('allows an empty rejected promise to be returned', function(done) { + jasmine.getEnv().requirePromises(); + + var originalFn = jasmine.createSpy('original'), + getPromise = function() { + return Promise; + }, + spyStrategy = new jasmineUnderTest.SpyStrategy({ + fn: originalFn, + getPromise: getPromise + }); + + spyStrategy.rejectWith(); + spyStrategy + .exec() + .then(done.fail) + .catch(function(error) { + expect(error).toBe(); + done(); + }) + .catch(done.fail); + }); + it('allows a non-Error to be rejected', function(done) { jasmine.getEnv().requirePromises(); From c521b4d47c1931f53051f38285a2e8c614e455ab Mon Sep 17 00:00:00 2001 From: Francois Wauquier Date: Fri, 28 Feb 2020 18:18:14 +0100 Subject: [PATCH 10/57] toHaveSize --- lib/jasmine-core/jasmine.js | 154 +++++++++++++------------- package.json | 2 +- spec/core/integration/MatchersSpec.js | 73 +++++++++++- spec/core/matchers/toHaveSizeSpec.js | 21 ++++ src/core/matchers/requireMatchers.js | 1 + src/core/matchers/toHaveSize.js | 79 +++++++++++++ 6 files changed, 250 insertions(+), 80 deletions(-) create mode 100644 spec/core/matchers/toHaveSizeSpec.js create mode 100644 src/core/matchers/toHaveSize.js diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 0e6c91d4..4c17bf3c 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -290,9 +290,9 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return typeof jasmineGlobal.Node !== 'undefined' ? obj instanceof jasmineGlobal.Node : obj !== null && - typeof obj === 'object' && - typeof obj.nodeType === 'number' && - typeof obj.nodeName === 'string'; + typeof obj === 'object' && + typeof obj.nodeType === 'number' && + typeof obj.nodeName === 'string'; // return obj.nodeType > 0; }; @@ -763,7 +763,7 @@ getJasmineRequireObj().Spec = function(j$) { onComplete: function() { onComplete( self.result.status === 'failed' && - new j$.StopExecutionError('spec failed') + new j$.StopExecutionError('spec failed') ); }, userContext: this.userContext() @@ -828,8 +828,8 @@ getJasmineRequireObj().Spec = function(j$) { this.result.failedExpectations.length > 0 || (failSpecWithNoExpectations && this.result.failedExpectations.length + - this.result.passedExpectations.length === - 0) + this.result.passedExpectations.length === + 0) ) { return 'failed'; } @@ -1170,7 +1170,7 @@ getJasmineRequireObj().Env = function(j$) { } runnableResources[ currentRunnable().id - ].defaultStrategyFn = defaultStrategyFn; + ].defaultStrategyFn = defaultStrategyFn; }; this.addSpyStrategy = function(name, fn) { @@ -2565,7 +2565,7 @@ getJasmineRequireObj().ObjectContaining = function(j$) { for (var property in this.sample) { if (!hasProperty(other, property) || - !matchersUtil.equals(this.sample[property], other[property])) { + !matchersUtil.equals(this.sample[property], other[property])) { return false; } } @@ -3373,7 +3373,7 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) { // scheduled in a funcToRun from forcing an extra iteration currentTime !== endTime && scheduledLookup[0] <= endTime - ); + ); // ran out of functions to call, but still time left on the clock if (currentTime !== endTime) { @@ -4108,24 +4108,24 @@ getJasmineRequireObj().toBeRejectedWith = function(j$) { return actualPromise.then( function() { - return { - pass: false, - message: prefix(false) + ' but it was resolved.' - }; - }, - function(actualValue) { - if (matchersUtil.equals(actualValue, expectedValue)) { - return { - pass: true, - message: prefix(true) + '.' - }; - } else { return { pass: false, - message: prefix(false) + ' but it was rejected with ' + matchersUtil.pp(actualValue) + '.' + message: prefix(false) + ' but it was resolved.' }; + }, + function(actualValue) { + if (matchersUtil.equals(actualValue, expectedValue)) { + return { + pass: true, + message: prefix(true) + '.' + }; + } else { + return { + pass: false, + message: prefix(false) + ' but it was rejected with ' + matchersUtil.pp(actualValue) + '.' + }; + } } - } ); } }; @@ -4494,9 +4494,9 @@ getJasmineRequireObj().MatchersUtil = function(j$) { MatchersUtil.prototype.asymmetricMatch_ = function(a, b, aStack, bStack, customTesters, diffBuilder) { var asymmetricA = j$.isAsymmetricEqualityTester_(a), - asymmetricB = j$.isAsymmetricEqualityTester_(b), - shim, - result; + asymmetricB = j$.isAsymmetricEqualityTester_(b), + shim, + result; if (asymmetricA === asymmetricB) { return undefined; @@ -4731,7 +4731,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { // otherwise explicitly look up the mapKey in the other Map since we want keys with unique // obj identity (that are otherwise equal) to not match. if (j$.isAsymmetricEqualityTester_(mapKey) || j$.isAsymmetricEqualityTester_(cmpKey) && - this.eq_(mapKey, cmpKey, aStack, bStack, customTesters, j$.NullDiffBuilder())) { + this.eq_(mapKey, cmpKey, aStack, bStack, customTesters, j$.NullDiffBuilder())) { mapValueB = b.get(cmpKey); } else { mapValueB = b.get(mapKey); @@ -4800,9 +4800,9 @@ getJasmineRequireObj().MatchersUtil = function(j$) { // or `Array`s from different frames are. var aCtor = a.constructor, bCtor = b.constructor; if (aCtor !== bCtor && - isFunction(aCtor) && isFunction(bCtor) && - a instanceof aCtor && b instanceof bCtor && - !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { + isFunction(aCtor) && isFunction(bCtor) && + a instanceof aCtor && b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { diffBuilder.recordMismatch(constructorsAreDifferentFormatter.bind(null, this.pp)); return false; @@ -4849,13 +4849,13 @@ getJasmineRequireObj().MatchersUtil = function(j$) { function keys(obj, isArray) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) { - var keys = []; - for (var key in o) { - if (j$.util.has(o, key)) { - keys.push(key); - } + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); } - return keys; + } + return keys; })(obj); if (!isArray) { @@ -4863,7 +4863,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { } if (allKeys.length === 0) { - return allKeys; + return allKeys; } var extraKeys = []; @@ -4882,10 +4882,10 @@ getJasmineRequireObj().MatchersUtil = function(j$) { function objectKeysAreDifferentFormatter(pp, actual, expected, path) { var missingProperties = j$.util.objectDifference(expected, actual), - extraProperties = j$.util.objectDifference(actual, expected), - missingPropertiesMessage = formatKeyValuePairs(pp, missingProperties), - extraPropertiesMessage = formatKeyValuePairs(pp, extraProperties), - messages = []; + extraProperties = j$.util.objectDifference(actual, expected), + missingPropertiesMessage = formatKeyValuePairs(pp, missingProperties), + extraPropertiesMessage = formatKeyValuePairs(pp, extraProperties), + messages = []; if (!path.depth()) { path = 'object'; @@ -5302,15 +5302,15 @@ getJasmineRequireObj().toBeInstanceOf = function(j$) { return { compare: function(actual, expected) { var actualType = actual && actual.constructor ? j$.fnNameFor(actual.constructor) : matchersUtil.pp(actual), - expectedType = expected ? j$.fnNameFor(expected) : matchersUtil.pp(expected), - expectedMatcher, - pass; + expectedType = expected ? j$.fnNameFor(expected) : matchersUtil.pp(expected), + expectedMatcher, + pass; try { - expectedMatcher = new j$.Any(expected); - pass = expectedMatcher.asymmetricMatch(actual); + expectedMatcher = new j$.Any(expected); + pass = expectedMatcher.asymmetricMatch(actual); } catch (error) { - throw new Error(usageError('Expected value is not a constructor function')); + throw new Error(usageError('Expected value is not a constructor function')); } if (pass) { @@ -5805,7 +5805,7 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { }); var diffs = actual.calls.allArgs().map(function(argsForCall, callIx) { - var diffBuilder = new j$.DiffBuilder(); + var diffBuilder = new j$.DiffBuilder(); matchersUtil.equals(argsForCall, expectedArgs, diffBuilder); return 'Call ' + callIx + ':\n' + diffBuilder.getMessage().replace(/^/mg, ' '); @@ -6050,7 +6050,7 @@ getJasmineRequireObj().toThrowError = function(j$) { function thrownDescription(thrown) { var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception', - thrownMessage = ''; + thrownMessage = ''; if (expected) { thrownMessage = ' with message ' + matchersUtil.pp(thrown.message); @@ -6157,10 +6157,10 @@ getJasmineRequireObj().toThrowMatching = function(j$) { if (predicate(thrown)) { return pass('Expected function not to throw an exception matching a predicate.'); } else { - return fail(function() { - return 'Expected function to throw an exception matching a predicate, ' + - 'but it threw ' + thrownDescription(thrown) + '.'; - }); + return fail(function() { + return 'Expected function to throw an exception matching a predicate, ' + + 'but it threw ' + thrownDescription(thrown) + '.'; + }); } } }; @@ -6378,8 +6378,8 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { } else if (j$.util.arrayContains(this.seen, value)) { this.emitScalar( '' + (j$.isArray_(value) ? 'Array' : 'Object') + + '>' ); } else if (j$.isArray_(value) || j$.isA_('Object', value)) { this.seen.push(value); @@ -6648,14 +6648,14 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) { - var keys = []; - for (var key in o) { - if (j$.util.has(o, key)) { - keys.push(key); - } + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); } - return keys; - })(obj); + } + return keys; + })(obj); if (!isArray) { return allKeys; @@ -6841,11 +6841,11 @@ getJasmineRequireObj().QueueRunner = function(j$) { timeoutId = self.setTimeout(function() { var error = new Error( 'Timeout - Async function did not complete within ' + - timeoutInterval + - 'ms ' + - (queueableFn.timeout - ? '(custom timeout)' - : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)') + timeoutInterval + + 'ms ' + + (queueableFn.timeout + ? '(custom timeout)' + : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)') ); onException(error); next(); @@ -7563,10 +7563,10 @@ getJasmineRequireObj().Spy = function(j$) { if (argsStrategies.any() && !baseStrategy.isConfigured()) { throw new Error( "Spy '" + - strategyArgs.name + - "' received a call with arguments " + - j$.pp(Array.prototype.slice.call(args)) + - ' but all configured strategies specify other arguments.' + strategyArgs.name + + "' received a call with arguments " + + j$.pp(Array.prototype.slice.call(args)) + + ' but all configured strategies specify other arguments.' ); } else { strategy = baseStrategy; @@ -7789,8 +7789,8 @@ getJasmineRequireObj().SpyRegistry = function(j$) { throw new Error( getErrorMsg( 'spyOn could not find an object to spy upon for ' + - propertyName + - '' + propertyName + + '' ) ); } @@ -7815,9 +7815,9 @@ getJasmineRequireObj().SpyRegistry = function(j$) { throw new Error( getErrorMsg( 'Property ' + - propertyName + - ' does not have access type ' + - accessType + propertyName + + ' does not have access type ' + + accessType ) ); } @@ -7948,7 +7948,7 @@ getJasmineRequireObj().SpyStrategy = function(j$) { if (!Promise) { throw new Error( name + - ' requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`' + ' requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`' ); } diff --git a/package.json b/package.json index bc602f6f..8db8eace 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jasmine-core", "license": "MIT", - "version": "3.5.0", + "version": "3.5.1", "repository": { "type": "git", "url": "https://github.com/jasmine/jasmine.git" diff --git a/spec/core/integration/MatchersSpec.js b/spec/core/integration/MatchersSpec.js index 7f19a95c..ec3404ff 100644 --- a/spec/core/integration/MatchersSpec.js +++ b/spec/core/integration/MatchersSpec.js @@ -47,6 +47,9 @@ describe('Matchers (Integration)', function() { expect(result.failedExpectations[0].message) .withContext('Failed with a thrown error rather than a matcher failure') .not.toMatch(/^Error: /); + expect(result.failedExpectations[0].message) + .withContext('Failed with a thrown type error rather than a matcher failure') + .not.toMatch(/^TypeError: /); expect(result.failedExpectations[0].matcherName).withContext('Matcher name') .not.toEqual(''); }; @@ -477,9 +480,9 @@ describe('Matchers (Integration)', function() { verifyFailsWithCustomObjectFormatters({ formatter: function(val) { if (val === 5) { - return "five" + return 'five'; } else if (val === 4) { - return "four" + return 'four'; } }, expectations: function(env) { @@ -489,6 +492,72 @@ describe('Matchers (Integration)', function() { }); }); + describe('toHaveSize', function() { + verifyPasses(function(env) { + env.expect(['a','b']).toHaveSize(2); + }); + verifyFails(function(env) { + env.expect(['a','b']).toHaveSize(1); + }); + + verifyPasses(function(env) { + env.expect({a: 1, b: 2}).toHaveSize(2); + }); + verifyFails(function(env) { + env.expect({a: 1, b: 2}).toHaveSize(1); + }); + + verifyPasses(function(env) { + env.expect({a: 1, b: 2, length: 5}).toHaveSize(5); + }); + verifyFails(function(env) { + env.expect({a: 1, b: 2, length: 5}).toHaveSize(1); + }); + + verifyPasses(function(env) { + env.expect('ab').toHaveSize(2); + }); + verifyFails(function(env) { + env.expect('ab').toHaveSize(1); + }); + + verifyPasses(function(env) { + var map = new Map(); + map.set('a',1); + map.set('b',2); + env.expect(map).toHaveSize(2); + }); + verifyFails(function(env) { + var map = new Map(); + map.set('a',1); + map.set('b',2); + env.expect(map).toHaveSize(1); + }); + + verifyPasses(function(env) { + var set = new Set(); + set.add('a'); + set.add('b'); + env.expect(set).toHaveSize(2); + }); + verifyFails(function(env) { + var set = new Set(); + set.add('a'); + set.add('b'); + env.expect(set).toHaveSize(1); + }); + + verifyFails(function(env) { + env.expect(new WeakSet()).toHaveSize(1); + }); + verifyFails(function(env) { + env.expect(new WeakMap()).toHaveSize(1); + }); + verifyFails(function(env) { + env.expect(new DataView(new ArrayBuffer(128))).toHaveSize(1); + }); + }); + describe('toHaveBeenCalled', function() { verifyPasses(function(env) { var spy = env.createSpy('spy'); diff --git a/spec/core/matchers/toHaveSizeSpec.js b/spec/core/matchers/toHaveSizeSpec.js new file mode 100644 index 00000000..08045432 --- /dev/null +++ b/spec/core/matchers/toHaveSizeSpec.js @@ -0,0 +1,21 @@ +describe('toHaveSize', function() { + 'use strict'; + + it('delegates to equals function', function() { + var matchersUtil = { + equals: jasmine.createSpy('delegated-equals').and.returnValue(true), + buildFailureMessage: function() { + return 'does not matter'; + }, + DiffBuilder: new jasmineUnderTest.DiffBuilder() + }, + matcher = jasmineUnderTest.matchers.toHaveSize(matchersUtil), + result; + + result = matcher.compare([1], 1); + + expect(matchersUtil.equals).toHaveBeenCalledWith(1, 1, jasmine.anything(), jasmine.anything()); + expect(result.pass).toBe(true); + }); + +}); diff --git a/src/core/matchers/requireMatchers.js b/src/core/matchers/requireMatchers.js index e8b1fd58..e0b256e5 100644 --- a/src/core/matchers/requireMatchers.js +++ b/src/core/matchers/requireMatchers.js @@ -20,6 +20,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) { 'toBeUndefined', 'toContain', 'toEqual', + 'toHaveSize', 'toHaveBeenCalled', 'toHaveBeenCalledBefore', 'toHaveBeenCalledTimes', diff --git a/src/core/matchers/toHaveSize.js b/src/core/matchers/toHaveSize.js new file mode 100644 index 00000000..b4ea9c55 --- /dev/null +++ b/src/core/matchers/toHaveSize.js @@ -0,0 +1,79 @@ +getJasmineRequireObj().toHaveSize = function(j$) { + /** + * {@link expect} the actual size to be equal to the expected, using array-like length or object keys size. + * @function + * @name matchers#toHaveSize + * @since 3.5.1 + * @param {Object} expected - Expected size + * @example + * array = [1,2]; + * expect(array).toHaveSize(2); + */ + function toHaveSize(matchersUtil) { + return { + compare: function(actual, expected) { + var result = { + pass: false + }, + simpleEqualityTesters = [function(a, b) { + return a === b; + }], + diffBuilder = j$.DiffBuilder(); + + // Avoid misleading collections size matching + if (actual instanceof WeakSet + || actual instanceof WeakMap + || actual instanceof DataView) { + result.message = 'Cannot get size of ' + actual + '.'; + return result; + } + + // Ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects + if (Array.isArray(actual) || isArrayLike(actual)) + result.pass = matchersUtil.equals(actual.length, expected, simpleEqualityTesters, diffBuilder); + else if ( actual instanceof String || typeof actual === 'string') + result.pass = matchersUtil.equals(actual.length, expected, simpleEqualityTesters, diffBuilder); + else if (actual instanceof Set || actual instanceof Map) + result.pass = matchersUtil.equals(actual.size, expected, simpleEqualityTesters, diffBuilder); + // instanceof Object + else + result.pass = matchersUtil.equals(Object.keys(actual).length, expected, simpleEqualityTesters, diffBuilder); + + if(!result.pass) + result.message = diffBuilder.getMessage() ; + return result; + } + }; + } + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * From lodash + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * _.isArrayLike([1, 2, 3]); + * // => true + * _.isArrayLike(document.body.children); + * // => true + * _.isArrayLike('abc'); + * // => true + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + var MAX_SAFE_INTEGER = 9007199254740991; + function isLength(value) { + return (typeof value == 'number') && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + var functionTags = ['[object Function]','[object GeneratorFunction]','[object AsyncFunction]','[object Proxy]']; + function isFunction(functionToCheck) { + return functionToCheck && functionTags.indexOf( Object.prototype.toString.call(functionToCheck) ) != -1; + } + + return toHaveSize; +}; From ec3ebcb7bb2c8612e2b18662a0582859439ac56d Mon Sep 17 00:00:00 2001 From: Gregg Van Hove Date: Wed, 18 Mar 2020 08:12:40 -0700 Subject: [PATCH 11/57] Clean up toHaveSize --- lib/jasmine-core/jasmine.js | 200 ++++++++++++++++---------- spec/core/integration/MatchersSpec.js | 58 +------- spec/core/matchers/toHaveSizeSpec.js | 140 ++++++++++++++++-- src/core/matchers/toHaveSize.js | 63 ++------ 4 files changed, 263 insertions(+), 198 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 4c17bf3c..824036b1 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -144,6 +144,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) { 'toBeUndefined', 'toContain', 'toEqual', + 'toHaveSize', 'toHaveBeenCalled', 'toHaveBeenCalledBefore', 'toHaveBeenCalledTimes', @@ -290,9 +291,9 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return typeof jasmineGlobal.Node !== 'undefined' ? obj instanceof jasmineGlobal.Node : obj !== null && - typeof obj === 'object' && - typeof obj.nodeType === 'number' && - typeof obj.nodeName === 'string'; + typeof obj === 'object' && + typeof obj.nodeType === 'number' && + typeof obj.nodeName === 'string'; // return obj.nodeType > 0; }; @@ -763,7 +764,7 @@ getJasmineRequireObj().Spec = function(j$) { onComplete: function() { onComplete( self.result.status === 'failed' && - new j$.StopExecutionError('spec failed') + new j$.StopExecutionError('spec failed') ); }, userContext: this.userContext() @@ -828,8 +829,8 @@ getJasmineRequireObj().Spec = function(j$) { this.result.failedExpectations.length > 0 || (failSpecWithNoExpectations && this.result.failedExpectations.length + - this.result.passedExpectations.length === - 0) + this.result.passedExpectations.length === + 0) ) { return 'failed'; } @@ -1170,7 +1171,7 @@ getJasmineRequireObj().Env = function(j$) { } runnableResources[ currentRunnable().id - ].defaultStrategyFn = defaultStrategyFn; + ].defaultStrategyFn = defaultStrategyFn; }; this.addSpyStrategy = function(name, fn) { @@ -2565,7 +2566,7 @@ getJasmineRequireObj().ObjectContaining = function(j$) { for (var property in this.sample) { if (!hasProperty(other, property) || - !matchersUtil.equals(this.sample[property], other[property])) { + !matchersUtil.equals(this.sample[property], other[property])) { return false; } } @@ -3373,7 +3374,7 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) { // scheduled in a funcToRun from forcing an extra iteration currentTime !== endTime && scheduledLookup[0] <= endTime - ); + ); // ran out of functions to call, but still time left on the clock if (currentTime !== endTime) { @@ -4108,24 +4109,24 @@ getJasmineRequireObj().toBeRejectedWith = function(j$) { return actualPromise.then( function() { + return { + pass: false, + message: prefix(false) + ' but it was resolved.' + }; + }, + function(actualValue) { + if (matchersUtil.equals(actualValue, expectedValue)) { + return { + pass: true, + message: prefix(true) + '.' + }; + } else { return { pass: false, - message: prefix(false) + ' but it was resolved.' + message: prefix(false) + ' but it was rejected with ' + matchersUtil.pp(actualValue) + '.' }; - }, - function(actualValue) { - if (matchersUtil.equals(actualValue, expectedValue)) { - return { - pass: true, - message: prefix(true) + '.' - }; - } else { - return { - pass: false, - message: prefix(false) + ' but it was rejected with ' + matchersUtil.pp(actualValue) + '.' - }; - } } + } ); } }; @@ -4494,9 +4495,9 @@ getJasmineRequireObj().MatchersUtil = function(j$) { MatchersUtil.prototype.asymmetricMatch_ = function(a, b, aStack, bStack, customTesters, diffBuilder) { var asymmetricA = j$.isAsymmetricEqualityTester_(a), - asymmetricB = j$.isAsymmetricEqualityTester_(b), - shim, - result; + asymmetricB = j$.isAsymmetricEqualityTester_(b), + shim, + result; if (asymmetricA === asymmetricB) { return undefined; @@ -4731,7 +4732,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { // otherwise explicitly look up the mapKey in the other Map since we want keys with unique // obj identity (that are otherwise equal) to not match. if (j$.isAsymmetricEqualityTester_(mapKey) || j$.isAsymmetricEqualityTester_(cmpKey) && - this.eq_(mapKey, cmpKey, aStack, bStack, customTesters, j$.NullDiffBuilder())) { + this.eq_(mapKey, cmpKey, aStack, bStack, customTesters, j$.NullDiffBuilder())) { mapValueB = b.get(cmpKey); } else { mapValueB = b.get(mapKey); @@ -4800,9 +4801,9 @@ getJasmineRequireObj().MatchersUtil = function(j$) { // or `Array`s from different frames are. var aCtor = a.constructor, bCtor = b.constructor; if (aCtor !== bCtor && - isFunction(aCtor) && isFunction(bCtor) && - a instanceof aCtor && b instanceof bCtor && - !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { + isFunction(aCtor) && isFunction(bCtor) && + a instanceof aCtor && b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { diffBuilder.recordMismatch(constructorsAreDifferentFormatter.bind(null, this.pp)); return false; @@ -4849,13 +4850,13 @@ getJasmineRequireObj().MatchersUtil = function(j$) { function keys(obj, isArray) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) { - var keys = []; - for (var key in o) { - if (j$.util.has(o, key)) { - keys.push(key); + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); + } } - } - return keys; + return keys; })(obj); if (!isArray) { @@ -4863,7 +4864,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { } if (allKeys.length === 0) { - return allKeys; + return allKeys; } var extraKeys = []; @@ -4882,10 +4883,10 @@ getJasmineRequireObj().MatchersUtil = function(j$) { function objectKeysAreDifferentFormatter(pp, actual, expected, path) { var missingProperties = j$.util.objectDifference(expected, actual), - extraProperties = j$.util.objectDifference(actual, expected), - missingPropertiesMessage = formatKeyValuePairs(pp, missingProperties), - extraPropertiesMessage = formatKeyValuePairs(pp, extraProperties), - messages = []; + extraProperties = j$.util.objectDifference(actual, expected), + missingPropertiesMessage = formatKeyValuePairs(pp, missingProperties), + extraPropertiesMessage = formatKeyValuePairs(pp, extraProperties), + messages = []; if (!path.depth()) { path = 'object'; @@ -5302,15 +5303,15 @@ getJasmineRequireObj().toBeInstanceOf = function(j$) { return { compare: function(actual, expected) { var actualType = actual && actual.constructor ? j$.fnNameFor(actual.constructor) : matchersUtil.pp(actual), - expectedType = expected ? j$.fnNameFor(expected) : matchersUtil.pp(expected), - expectedMatcher, - pass; + expectedType = expected ? j$.fnNameFor(expected) : matchersUtil.pp(expected), + expectedMatcher, + pass; try { - expectedMatcher = new j$.Any(expected); - pass = expectedMatcher.asymmetricMatch(actual); + expectedMatcher = new j$.Any(expected); + pass = expectedMatcher.asymmetricMatch(actual); } catch (error) { - throw new Error(usageError('Expected value is not a constructor function')); + throw new Error(usageError('Expected value is not a constructor function')); } if (pass) { @@ -5805,7 +5806,7 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { }); var diffs = actual.calls.allArgs().map(function(argsForCall, callIx) { - var diffBuilder = new j$.DiffBuilder(); + var diffBuilder = new j$.DiffBuilder(); matchersUtil.equals(argsForCall, expectedArgs, diffBuilder); return 'Call ' + callIx + ':\n' + diffBuilder.getMessage().replace(/^/mg, ' '); @@ -5862,6 +5863,49 @@ getJasmineRequireObj().toHaveClass = function(j$) { return toHaveClass; }; +getJasmineRequireObj().toHaveSize = function(j$) { + /** + * {@link expect} the actual size to be equal to the expected, using array-like length or object keys size. + * @function + * @name matchers#toHaveSize + * @since 3.5.1 + * @param {Object} expected - Expected size + * @example + * array = [1,2]; + * expect(array).toHaveSize(2); + */ + function toHaveSize() { + return { + compare: function(actual, expected) { + var result = { + pass: false + }; + + if (actual instanceof WeakSet || actual instanceof WeakMap || actual instanceof DataView) { + throw new Error('Cannot get size of ' + actual + '.'); + } + + if (actual instanceof Set || actual instanceof Map) { + result.pass = actual.size === expected; + } else if (isLength(actual.length)) { + result.pass = actual.length === expected; + } else { + result.pass = Object.keys(actual).length === expected; + } + + return result; + } + }; + } + + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + function isLength(value) { + return (typeof value == 'number') && value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER; + } + + return toHaveSize; +}; + getJasmineRequireObj().toMatch = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect().toMatch( || )'); @@ -6050,7 +6094,7 @@ getJasmineRequireObj().toThrowError = function(j$) { function thrownDescription(thrown) { var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception', - thrownMessage = ''; + thrownMessage = ''; if (expected) { thrownMessage = ' with message ' + matchersUtil.pp(thrown.message); @@ -6157,10 +6201,10 @@ getJasmineRequireObj().toThrowMatching = function(j$) { if (predicate(thrown)) { return pass('Expected function not to throw an exception matching a predicate.'); } else { - return fail(function() { - return 'Expected function to throw an exception matching a predicate, ' + - 'but it threw ' + thrownDescription(thrown) + '.'; - }); + return fail(function() { + return 'Expected function to throw an exception matching a predicate, ' + + 'but it threw ' + thrownDescription(thrown) + '.'; + }); } } }; @@ -6378,8 +6422,8 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { } else if (j$.util.arrayContains(this.seen, value)) { this.emitScalar( '' + (j$.isArray_(value) ? 'Array' : 'Object') + + '>' ); } else if (j$.isArray_(value) || j$.isA_('Object', value)) { this.seen.push(value); @@ -6648,14 +6692,14 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) { - var keys = []; - for (var key in o) { - if (j$.util.has(o, key)) { - keys.push(key); + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); + } } - } - return keys; - })(obj); + return keys; + })(obj); if (!isArray) { return allKeys; @@ -6841,11 +6885,11 @@ getJasmineRequireObj().QueueRunner = function(j$) { timeoutId = self.setTimeout(function() { var error = new Error( 'Timeout - Async function did not complete within ' + - timeoutInterval + - 'ms ' + - (queueableFn.timeout - ? '(custom timeout)' - : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)') + timeoutInterval + + 'ms ' + + (queueableFn.timeout + ? '(custom timeout)' + : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)') ); onException(error); next(); @@ -7563,10 +7607,10 @@ getJasmineRequireObj().Spy = function(j$) { if (argsStrategies.any() && !baseStrategy.isConfigured()) { throw new Error( "Spy '" + - strategyArgs.name + - "' received a call with arguments " + - j$.pp(Array.prototype.slice.call(args)) + - ' but all configured strategies specify other arguments.' + strategyArgs.name + + "' received a call with arguments " + + j$.pp(Array.prototype.slice.call(args)) + + ' but all configured strategies specify other arguments.' ); } else { strategy = baseStrategy; @@ -7789,8 +7833,8 @@ getJasmineRequireObj().SpyRegistry = function(j$) { throw new Error( getErrorMsg( 'spyOn could not find an object to spy upon for ' + - propertyName + - '' + propertyName + + '' ) ); } @@ -7815,9 +7859,9 @@ getJasmineRequireObj().SpyRegistry = function(j$) { throw new Error( getErrorMsg( 'Property ' + - propertyName + - ' does not have access type ' + - accessType + propertyName + + ' does not have access type ' + + accessType ) ); } @@ -7948,7 +7992,7 @@ getJasmineRequireObj().SpyStrategy = function(j$) { if (!Promise) { throw new Error( name + - ' requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`' + ' requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`' ); } @@ -8724,5 +8768,5 @@ getJasmineRequireObj().UserContext = function(j$) { }; getJasmineRequireObj().version = function() { - return '3.5.0'; + return '3.5.1'; }; diff --git a/spec/core/integration/MatchersSpec.js b/spec/core/integration/MatchersSpec.js index ec3404ff..c1d2dd09 100644 --- a/spec/core/integration/MatchersSpec.js +++ b/spec/core/integration/MatchersSpec.js @@ -496,66 +496,10 @@ describe('Matchers (Integration)', function() { verifyPasses(function(env) { env.expect(['a','b']).toHaveSize(2); }); + verifyFails(function(env) { env.expect(['a','b']).toHaveSize(1); }); - - verifyPasses(function(env) { - env.expect({a: 1, b: 2}).toHaveSize(2); - }); - verifyFails(function(env) { - env.expect({a: 1, b: 2}).toHaveSize(1); - }); - - verifyPasses(function(env) { - env.expect({a: 1, b: 2, length: 5}).toHaveSize(5); - }); - verifyFails(function(env) { - env.expect({a: 1, b: 2, length: 5}).toHaveSize(1); - }); - - verifyPasses(function(env) { - env.expect('ab').toHaveSize(2); - }); - verifyFails(function(env) { - env.expect('ab').toHaveSize(1); - }); - - verifyPasses(function(env) { - var map = new Map(); - map.set('a',1); - map.set('b',2); - env.expect(map).toHaveSize(2); - }); - verifyFails(function(env) { - var map = new Map(); - map.set('a',1); - map.set('b',2); - env.expect(map).toHaveSize(1); - }); - - verifyPasses(function(env) { - var set = new Set(); - set.add('a'); - set.add('b'); - env.expect(set).toHaveSize(2); - }); - verifyFails(function(env) { - var set = new Set(); - set.add('a'); - set.add('b'); - env.expect(set).toHaveSize(1); - }); - - verifyFails(function(env) { - env.expect(new WeakSet()).toHaveSize(1); - }); - verifyFails(function(env) { - env.expect(new WeakMap()).toHaveSize(1); - }); - verifyFails(function(env) { - env.expect(new DataView(new ArrayBuffer(128))).toHaveSize(1); - }); }); describe('toHaveBeenCalled', function() { diff --git a/spec/core/matchers/toHaveSizeSpec.js b/spec/core/matchers/toHaveSizeSpec.js index 08045432..a1b4cccb 100644 --- a/spec/core/matchers/toHaveSizeSpec.js +++ b/spec/core/matchers/toHaveSizeSpec.js @@ -1,21 +1,135 @@ describe('toHaveSize', function() { 'use strict'; - it('delegates to equals function', function() { - var matchersUtil = { - equals: jasmine.createSpy('delegated-equals').and.returnValue(true), - buildFailureMessage: function() { - return 'does not matter'; - }, - DiffBuilder: new jasmineUnderTest.DiffBuilder() - }, - matcher = jasmineUnderTest.matchers.toHaveSize(matchersUtil), - result; + it('passes for an array whose length matches', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare([1, 2], 2); - result = matcher.compare([1], 1); - - expect(matchersUtil.equals).toHaveBeenCalledWith(1, 1, jasmine.anything(), jasmine.anything()); expect(result.pass).toBe(true); }); + it('fails for an array whose length does not match', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare([1, 2, 3], 2); + + expect(result.pass).toBe(false); + }); + + it('passes for an object with the proper number of keys', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare({a: 1, b: 2}, 2); + + expect(result.pass).toBe(true); + }); + + it('fails for an object with a different number of keys', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare({a: 1, b: 2}, 1); + + expect(result.pass).toBe(false); + }); + + it('passes for an object with an explicit `length` property that matches', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare({a: 1, b: 2, length: 5}, 5); + + expect(result.pass).toBe(true); + }); + + it('fails for an object with an explicit `length` property that does not match', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare({a: 1, b: 2, length: 5}, 1); + + expect(result.pass).toBe(false); + }); + + it('passes for a string whose length matches', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare('ab', 2); + + expect(result.pass).toBe(true); + }); + + it('fails for a string whose length does not match', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare('abc', 2); + + expect(result.pass).toBe(false); + }); + + it('passes for a Map whose length matches', function() { + jasmine.getEnv().requireFunctioningMaps(); + + var map = new Map(); + map.set('a',1); + map.set('b',2); + + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare(map, 2); + + expect(result.pass).toBe(true); + }); + + it('fails for a Map whose length does not match', function() { + jasmine.getEnv().requireFunctioningMaps(); + + var map = new Map(); + map.set('a',1); + map.set('b',2); + + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare(map, 1); + + expect(result.pass).toBe(false); + }); + + it('passes for a Set whose length matches', function() { + jasmine.getEnv().requireFunctioningSets(); + + var set = new Set(); + set.add('a'); + set.add('b'); + + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare(set, 2); + + expect(result.pass).toBe(true); + }); + + it('fails for a Set whose length does not match', function() { + jasmine.getEnv().requireFunctioningSets(); + + var set = new Set(); + set.add('a'); + set.add('b'); + + var matcher = jasmineUnderTest.matchers.toHaveSize(), + result = matcher.compare(set, 1); + + expect(result.pass).toBe(false); + }); + + it('throws an error for WeakSet', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(); + + expect(function() { + matcher.compare(new WeakSet(), 2); + }).toThrowError('Cannot get size of [object WeakSet].'); + }); + + it('throws an error for WeakMap', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(); + + expect(function() { + matcher.compare(new WeakMap(), 2); + }).toThrowError('Cannot get size of [object WeakMap].'); + }); + + it('throws an error for DataView', function() { + var matcher = jasmineUnderTest.matchers.toHaveSize(); + + expect(function() { + matcher.compare(new DataView(new ArrayBuffer(128)), 2); + }).toThrowError('Cannot get size of [object DataView].'); + }); }); diff --git a/src/core/matchers/toHaveSize.js b/src/core/matchers/toHaveSize.js index b4ea9c55..ae344ca9 100644 --- a/src/core/matchers/toHaveSize.js +++ b/src/core/matchers/toHaveSize.js @@ -9,70 +9,33 @@ getJasmineRequireObj().toHaveSize = function(j$) { * array = [1,2]; * expect(array).toHaveSize(2); */ - function toHaveSize(matchersUtil) { + function toHaveSize() { return { compare: function(actual, expected) { var result = { pass: false - }, - simpleEqualityTesters = [function(a, b) { - return a === b; - }], - diffBuilder = j$.DiffBuilder(); + }; - // Avoid misleading collections size matching - if (actual instanceof WeakSet - || actual instanceof WeakMap - || actual instanceof DataView) { - result.message = 'Cannot get size of ' + actual + '.'; - return result; + if (actual instanceof WeakSet || actual instanceof WeakMap || actual instanceof DataView) { + throw new Error('Cannot get size of ' + actual + '.'); } - // Ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects - if (Array.isArray(actual) || isArrayLike(actual)) - result.pass = matchersUtil.equals(actual.length, expected, simpleEqualityTesters, diffBuilder); - else if ( actual instanceof String || typeof actual === 'string') - result.pass = matchersUtil.equals(actual.length, expected, simpleEqualityTesters, diffBuilder); - else if (actual instanceof Set || actual instanceof Map) - result.pass = matchersUtil.equals(actual.size, expected, simpleEqualityTesters, diffBuilder); - // instanceof Object - else - result.pass = matchersUtil.equals(Object.keys(actual).length, expected, simpleEqualityTesters, diffBuilder); + if (actual instanceof Set || actual instanceof Map) { + result.pass = actual.size === expected; + } else if (isLength(actual.length)) { + result.pass = actual.length === expected; + } else { + result.pass = Object.keys(actual).length === expected; + } - if(!result.pass) - result.message = diffBuilder.getMessage() ; return result; } }; } - /** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. - * From lodash - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - * @example - * _.isArrayLike([1, 2, 3]); - * // => true - * _.isArrayLike(document.body.children); - * // => true - * _.isArrayLike('abc'); - * // => true - * _.isArrayLike(_.noop); - * // => false - */ - function isArrayLike(value) { - return value != null && isLength(value.length) && !isFunction(value); - } - var MAX_SAFE_INTEGER = 9007199254740991; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; function isLength(value) { - return (typeof value == 'number') && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; - } - var functionTags = ['[object Function]','[object GeneratorFunction]','[object AsyncFunction]','[object Proxy]']; - function isFunction(functionToCheck) { - return functionToCheck && functionTags.indexOf( Object.prototype.toString.call(functionToCheck) ) != -1; + return (typeof value == 'number') && value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER; } return toHaveSize; From 79d55216fcf17f17a6e05e32a5564a03508705bf Mon Sep 17 00:00:00 2001 From: Gregg Van Hove Date: Wed, 18 Mar 2020 08:57:44 -0700 Subject: [PATCH 12/57] Use internal type checks instead of `instanceof` to support browsers that don't include the types --- lib/jasmine-core/jasmine.js | 2 +- src/core/matchers/toHaveSize.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 824036b1..5f9e531e 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -5881,7 +5881,7 @@ getJasmineRequireObj().toHaveSize = function(j$) { pass: false }; - if (actual instanceof WeakSet || actual instanceof WeakMap || actual instanceof DataView) { + if (j$.isA_('WeakSet', actual) || j$.isA_('WeakMap', actual) || j$.isA_('DataView', actual)) { throw new Error('Cannot get size of ' + actual + '.'); } diff --git a/src/core/matchers/toHaveSize.js b/src/core/matchers/toHaveSize.js index ae344ca9..c0e84cb3 100644 --- a/src/core/matchers/toHaveSize.js +++ b/src/core/matchers/toHaveSize.js @@ -16,7 +16,7 @@ getJasmineRequireObj().toHaveSize = function(j$) { pass: false }; - if (actual instanceof WeakSet || actual instanceof WeakMap || actual instanceof DataView) { + if (j$.isA_('WeakSet', actual) || j$.isA_('WeakMap', actual) || j$.isA_('DataView', actual)) { throw new Error('Cannot get size of ' + actual + '.'); } From bcc28d7063971cd04cad89a1bcee2c96726abe97 Mon Sep 17 00:00:00 2001 From: Maksym Kobieliev Date: Thu, 2 Apr 2020 21:31:17 +0300 Subject: [PATCH 13/57] Output a diff if there was only one call, but with wrong parameters --- .../matchers/toHaveBeenCalledOnceWithSpec.js | 2 +- src/core/matchers/toHaveBeenCalledOnceWith.js | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js index b3678bfb..97fdaf9c 100644 --- a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js +++ b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js @@ -49,7 +49,7 @@ describe("toHaveBeenCalledOnceWith", function () { result = matcher.compare(calledSpy, 'a', 'b'); expect(result.pass).toBe(false); - expect(result.message).toEqual("Expected spy called-spy to have been called only once, and with given args:\n [ 'a', 'b' ]\nBut the actual calls were:\n [ 'a', 'c' ].\n\n"); + expect(result.message).toEqual("Expected spy called-spy to have been called only once, and with given args:\n [ 'a', 'b' ]\nBut the actual call was:\n [ 'a', 'c' ].\nExpected $[1] = 'c' to equal 'b'.\n\n"); }); it("fails when the actual was called multiple times with expected parameters", function () { diff --git a/src/core/matchers/toHaveBeenCalledOnceWith.js b/src/core/matchers/toHaveBeenCalledOnceWith.js index ccd707c7..035848b0 100644 --- a/src/core/matchers/toHaveBeenCalledOnceWith.js +++ b/src/core/matchers/toHaveBeenCalledOnceWith.js @@ -36,10 +36,23 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { }; } + function getDiffs() { + return actual.calls.allArgs().map(function (argsForCall, callIx) { + var diffBuilder = new j$.DiffBuilder(); + util.equals(argsForCall, expectedArgs, customEqualityTesters, diffBuilder); + return diffBuilder.getMessage(); + }); + } + function butString() { - return actual.calls.count() !== 0 - ? 'But the actual calls were:\n' + prettyPrintedCalls.join(',\n') + '.\n\n' - : 'But it was never called.\n\n'; + switch (actual.calls.count()) { + case 0: + return 'But it was never called.\n\n'; + case 1: + return 'But the actual call was:\n' + prettyPrintedCalls.join(',\n') + '.\n' + getDiffs().join('\n') + '\n\n'; + default: + return 'But the actual calls were:\n' + prettyPrintedCalls.join(',\n') + '.\n\n'; + } } return { From ec9904bf52e7e4c45045742c54595b6af5341aad Mon Sep 17 00:00:00 2001 From: Maksym Kobieliev Date: Thu, 2 Apr 2020 21:38:54 +0300 Subject: [PATCH 14/57] Fix test --- spec/core/matchers/toHaveBeenCalledOnceWithSpec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js index 97fdaf9c..722a05f1 100644 --- a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js +++ b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js @@ -15,7 +15,8 @@ describe("toHaveBeenCalledOnceWith", function () { it("passes through the custom equality testers", function () { var util = { - contains: jasmine.createSpy('delegated-contains').and.returnValue(false) + contains: jasmine.createSpy('delegated-contains').and.returnValue(false), + equals: jasmineUnderTest.matchersUtil.equals }, customEqualityTesters = [function () { return true; }], matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util, customEqualityTesters), From 9a7dfb15d2a52a80930445091e6ecba49a894f82 Mon Sep 17 00:00:00 2001 From: Alex Parloti Date: Thu, 2 Apr 2020 21:01:56 +0200 Subject: [PATCH 15/57] fix #26 fix #26 Returning false will cause 'zone.js' to invoke e.preventDefault(), preventing the page from reloading. --- src/html/HtmlReporter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index 1c6478cf..24d3a404 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -321,9 +321,11 @@ jasmineRequire.HtmlReporter = function(j$) { find('.jasmine-failures-menu').onclick = function() { setMenuModeTo('jasmine-failure-list'); + return false; }; find('.jasmine-spec-list-menu').onclick = function() { setMenuModeTo('jasmine-spec-list'); + return false; }; setMenuModeTo('jasmine-failure-list'); From 6b213a958d0edb187e255286dead7828b7752d05 Mon Sep 17 00:00:00 2001 From: DCtheTall Date: Thu, 9 Apr 2020 15:13:33 -0400 Subject: [PATCH 16/57] Add expectAsync().toBePending() --- spec/core/matchers/async/toBePendingSpec.js | 51 +++++++++++++++++++++ src/core/matchers/async/toBePending.js | 25 ++++++++++ src/core/matchers/requireAsyncMatchers.js | 1 + 3 files changed, 77 insertions(+) create mode 100644 spec/core/matchers/async/toBePendingSpec.js create mode 100644 src/core/matchers/async/toBePending.js diff --git a/spec/core/matchers/async/toBePendingSpec.js b/spec/core/matchers/async/toBePendingSpec.js new file mode 100644 index 00000000..5aa4f428 --- /dev/null +++ b/spec/core/matchers/async/toBePendingSpec.js @@ -0,0 +1,51 @@ +describe('toBePending', function() { + it('passes if the actual promise is pending', function() { + jasmine.getEnv().requirePromises(); + + var matchersUtil = new jasmineUnderTest.MatchersUtil(), + matcher = jasmineUnderTest.asyncMatchers.toBePending(matchersUtil), + actual = new Promise(function() {}); + + return matcher.compare(actual).then(function(result) { + expect(result).toEqual(jasmine.objectContaining({pass: true})); + }); + }); + + it('fails if the actual promise is resolved', function() { + jasmine.getEnv().requirePromises(); + + var matchersUtil = new jasmineUnderTest.MatchersUtil(), + matcher = jasmineUnderTest.asyncMatchers.toBePending(matchersUtil), + actual = Promise.resolve(); + + return matcher.compare(actual).then(function(result) { + expect(result).toEqual(jasmine.objectContaining({pass: false})); + }); + }); + + it('fails if the actual promise is rejected', function() { + jasmine.getEnv().requirePromises(); + + var matchersUtil = new jasmineUnderTest.MatchersUtil(), + matcher = jasmineUnderTest.asyncMatchers.toBePending(matchersUtil), + actual = Promise.reject(new Error('promise was rejected')); + + return matcher.compare(actual).then(function(result) { + expect(result).toEqual(jasmine.objectContaining({pass: false})); + }); + }); + + it('fails if actual is not a promise', function() { + var matchersUtil = new jasmineUnderTest.MatchersUtil(), + matcher = jasmineUnderTest.asyncMatchers.toBePending(matchersUtil), + actual = 'not a promise'; + + function f() { + return matcher.compare(actual); + } + + expect(f).toThrowError( + 'Expected toBePending to be called on a promise.' + ); + }); +}); \ No newline at end of file diff --git a/src/core/matchers/async/toBePending.js b/src/core/matchers/async/toBePending.js new file mode 100644 index 00000000..31059084 --- /dev/null +++ b/src/core/matchers/async/toBePending.js @@ -0,0 +1,25 @@ +getJasmineRequireObj().toBePending = function(j$) { + /** + * Expect a promise to be pending, ie. the promise is neither resolved nor rejected. + * @function + * @async + * @name async-matchers#toBePending + * @since 3.5.1 (should this be the next version or the version when it was added?) + * @example + * await expectAsync(aPromise).toBePending(); + */ + return function toBePending() { + return { + compare: function(actual) { + if (!j$.isPromiseLike(actual)) { + throw new Error('Expected toBePending to be called on a promise.'); + } + var want = {}; + return Promise.race([actual, Promise.resolve(want)]).then( + function(got) { return {pass: want === got}; }, + function() { return {pass: false}; } + ); + } + }; + }; +}; \ No newline at end of file diff --git a/src/core/matchers/requireAsyncMatchers.js b/src/core/matchers/requireAsyncMatchers.js index faa91c02..abe9b8ef 100644 --- a/src/core/matchers/requireAsyncMatchers.js +++ b/src/core/matchers/requireAsyncMatchers.js @@ -1,5 +1,6 @@ getJasmineRequireObj().requireAsyncMatchers = function(jRequire, j$) { var availableMatchers = [ + 'toBePending', 'toBeResolved', 'toBeRejected', 'toBeResolvedTo', From 76a99aef86ff1bf029851b56194cd16cb7facc2c Mon Sep 17 00:00:00 2001 From: DCtheTall Date: Thu, 9 Apr 2020 15:19:47 -0400 Subject: [PATCH 17/57] add missing trailing newline --- src/core/matchers/async/toBePending.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/matchers/async/toBePending.js b/src/core/matchers/async/toBePending.js index 31059084..7ea12df9 100644 --- a/src/core/matchers/async/toBePending.js +++ b/src/core/matchers/async/toBePending.js @@ -22,4 +22,4 @@ getJasmineRequireObj().toBePending = function(j$) { } }; }; -}; \ No newline at end of file +}; From 08779f2657cbd088b8b37e3c17e9363ac8406c46 Mon Sep 17 00:00:00 2001 From: DCtheTall Date: Thu, 9 Apr 2020 15:20:23 -0400 Subject: [PATCH 18/57] add missing trailing newline --- spec/core/matchers/async/toBePendingSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/core/matchers/async/toBePendingSpec.js b/spec/core/matchers/async/toBePendingSpec.js index 5aa4f428..318e22b7 100644 --- a/spec/core/matchers/async/toBePendingSpec.js +++ b/spec/core/matchers/async/toBePendingSpec.js @@ -48,4 +48,4 @@ describe('toBePending', function() { 'Expected toBePending to be called on a promise.' ); }); -}); \ No newline at end of file +}); From 78c3a007ad8cb29834b1ed957599804272a6b578 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 11 Apr 2020 12:08:49 -0700 Subject: [PATCH 19/57] Fixed test failure in Firefox 74 --- spec/html/PrettyPrintHtmlSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/html/PrettyPrintHtmlSpec.js b/spec/html/PrettyPrintHtmlSpec.js index fd364d9e..738753ba 100644 --- a/spec/html/PrettyPrintHtmlSpec.js +++ b/spec/html/PrettyPrintHtmlSpec.js @@ -31,7 +31,7 @@ describe('PrettyPrinter (HTML Dependent)', function() { } // Different versions of FF produce different error messages. expect(pp(err)).toMatch( - /Not enough arguments|CustomEvent requires at least 1 argument, but only 0 were passed/ + /Not enough arguments|CustomEvent.*only 0.*passed/ ); } }); From 8991b1bba39b5b7e89fc5eeb07ae271a684cb1a4 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sun, 12 Apr 2020 13:43:44 -0700 Subject: [PATCH 20/57] Fixed toHaveSize matcher on IE 10 & 11 --- lib/jasmine-core/jasmine.js | 22 ++++++++++++++++++++-- spec/core/baseSpec.js | 11 +++++++++++ spec/core/matchers/toHaveSizeSpec.js | 6 ++++-- spec/helpers/checkForMap.js | 6 ++++++ spec/helpers/checkForSet.js | 6 ++++++ src/core/base.js | 18 ++++++++++++++++++ src/core/matchers/toHaveSize.js | 4 ++-- 7 files changed, 67 insertions(+), 6 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 9f4413c3..1701fd73 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -314,6 +314,24 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { obj.constructor === jasmineGlobal.Set ); }; + + j$.isWeakMap = function(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + typeof jasmineGlobal.WeakMap !== 'undefined' && + obj.constructor === jasmineGlobal.WeakMap + ); + }; + + j$.isDataView = function(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + typeof jasmineGlobal.DataView !== 'undefined' && + obj.constructor === jasmineGlobal.DataView + ); + }; j$.isPromise = function(obj) { return ( @@ -5908,11 +5926,11 @@ getJasmineRequireObj().toHaveSize = function(j$) { pass: false }; - if (j$.isA_('WeakSet', actual) || j$.isA_('WeakMap', actual) || j$.isA_('DataView', actual)) { + if (j$.isA_('WeakSet', actual) || j$.isWeakMap(actual) || j$.isDataView(actual)) { throw new Error('Cannot get size of ' + actual + '.'); } - if (actual instanceof Set || actual instanceof Map) { + if (j$.isSet(actual) || j$.isMap(actual)) { result.pass = actual.size === expected; } else if (isLength(actual.length)) { result.pass = actual.length === expected; diff --git a/spec/core/baseSpec.js b/spec/core/baseSpec.js index 4fce2254..b85721b9 100644 --- a/spec/core/baseSpec.js +++ b/spec/core/baseSpec.js @@ -51,4 +51,15 @@ describe('base helpers', function() { expect(jasmineUnderTest.isAsymmetricEqualityTester_(obj)).toBe(true); }); }); + + describe('isSet', function() { + it('returns true when the object is a Set', function() { + jasmine.getEnv().requireFunctioningSets(); + expect(jasmineUnderTest.isSet(new Set())).toBe(true); + }); + + it('returns false when the object is not a Set', function() { + expect(jasmineUnderTest.isSet({})).toBe(false); + }); + }); }); diff --git a/spec/core/matchers/toHaveSizeSpec.js b/spec/core/matchers/toHaveSizeSpec.js index a1b4cccb..a14a24e5 100644 --- a/spec/core/matchers/toHaveSizeSpec.js +++ b/spec/core/matchers/toHaveSizeSpec.js @@ -110,6 +110,7 @@ describe('toHaveSize', function() { }); it('throws an error for WeakSet', function() { + jasmine.getEnv().requireWeakSets(); var matcher = jasmineUnderTest.matchers.toHaveSize(); expect(function() { @@ -118,11 +119,12 @@ describe('toHaveSize', function() { }); it('throws an error for WeakMap', function() { + jasmine.getEnv().requireWeakMaps(); var matcher = jasmineUnderTest.matchers.toHaveSize(); expect(function() { matcher.compare(new WeakMap(), 2); - }).toThrowError('Cannot get size of [object WeakMap].'); + }).toThrowError(/Cannot get size of \[object (WeakMap|Object)\]\./); }); it('throws an error for DataView', function() { @@ -130,6 +132,6 @@ describe('toHaveSize', function() { expect(function() { matcher.compare(new DataView(new ArrayBuffer(128)), 2); - }).toThrowError('Cannot get size of [object DataView].'); + }).toThrowError(/Cannot get size of \[object (DataView|Object)\]\./); }); }); diff --git a/spec/helpers/checkForMap.js b/spec/helpers/checkForMap.js index 46e346a8..77fa1233 100644 --- a/spec/helpers/checkForMap.js +++ b/spec/helpers/checkForMap.js @@ -43,4 +43,10 @@ env.pending('Browser has incomplete or missing support for Maps'); } }; + + env.requireWeakMaps = function() { + if (typeof WeakMap === 'undefined') { + env.pending('Browser does not have support for WeakMap'); + } + }; })(jasmine.getEnv()); diff --git a/spec/helpers/checkForSet.js b/spec/helpers/checkForSet.js index dacb06aa..8656342d 100644 --- a/spec/helpers/checkForSet.js +++ b/spec/helpers/checkForSet.js @@ -47,4 +47,10 @@ env.pending('Browser has incomplete or missing support for Sets'); } }; + + env.requireWeakSets = function() { + if (typeof WeakSet === 'undefined') { + env.pending('Browser does not have support for WeakSet'); + } + }; })(jasmine.getEnv()); diff --git a/src/core/base.js b/src/core/base.js index e86a12c8..121ff614 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -148,6 +148,24 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { ); }; + j$.isWeakMap = function(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + typeof jasmineGlobal.WeakMap !== 'undefined' && + obj.constructor === jasmineGlobal.WeakMap + ); + }; + + j$.isDataView = function(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + typeof jasmineGlobal.DataView !== 'undefined' && + obj.constructor === jasmineGlobal.DataView + ); + }; + j$.isPromise = function(obj) { return ( typeof jasmineGlobal.Promise !== 'undefined' && diff --git a/src/core/matchers/toHaveSize.js b/src/core/matchers/toHaveSize.js index c0e84cb3..4f6ace0c 100644 --- a/src/core/matchers/toHaveSize.js +++ b/src/core/matchers/toHaveSize.js @@ -16,11 +16,11 @@ getJasmineRequireObj().toHaveSize = function(j$) { pass: false }; - if (j$.isA_('WeakSet', actual) || j$.isA_('WeakMap', actual) || j$.isA_('DataView', actual)) { + if (j$.isA_('WeakSet', actual) || j$.isWeakMap(actual) || j$.isDataView(actual)) { throw new Error('Cannot get size of ' + actual + '.'); } - if (actual instanceof Set || actual instanceof Map) { + if (j$.isSet(actual) || j$.isMap(actual)) { result.pass = actual.size === expected; } else if (isLength(actual.length)) { result.pass = actual.length === expected; From f90d9943fec94bd71b28509761f53d4ed537039d Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Tue, 29 Oct 2019 17:17:27 -0700 Subject: [PATCH 21/57] feat(env): setSpecProperty/setSuiteProperty(key, value) to attach data to tests Use setSpecProperty to attach key/value pairs to spec results that can be picked up in specialized jasmine reporters. Example use-cases include: * Tagging specs with URLs or string-tokens referencing test-plan docs. * Recording performance information for blocks of JS. Similarly setSuiteProperty attaches key/value pairs to suite results --- spec/core/SpecSpec.js | 20 ++++++++- spec/core/integration/EnvSpec.js | 71 ++++++++++++++++++++++++++++++++ src/core/Env.js | 18 ++++++++ src/core/Spec.js | 9 +++- src/core/Suite.js | 9 +++- 5 files changed, 124 insertions(+), 3 deletions(-) diff --git a/spec/core/SpecSpec.js b/spec/core/SpecSpec.js index 38a8e780..fa530049 100644 --- a/spec/core/SpecSpec.js +++ b/spec/core/SpecSpec.js @@ -227,7 +227,8 @@ describe('Spec', function() { passedExpectations: [], deprecationWarnings: [], pendingReason: '', - duration: jasmine.any(Number) + duration: jasmine.any(Number), + properties: null }, 'things' ); @@ -299,6 +300,23 @@ describe('Spec', function() { expect(duration).toBe(77000); }); + it('should report properties set during the test', function() { + var done = jasmine.createSpy('done callback'), + spec = new jasmineUnderTest.Spec({ + queueableFn: { fn: jasmine.createSpy('spec body') }, + catchExceptions: function() { + return false; + }, + resultCallback: function() {}, + queueRunnerFactory: function(attrs) { + attrs.onComplete(); + } + }); + spec.setSpecProperty('a', 4); + spec.execute(done); + expect(spec.result.properties).toEqual({ a: 4 }); + }); + it('#status returns passing by default', function() { var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: jasmine.createSpy('spec body') } diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 8c5c1941..247744d3 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -1971,6 +1971,77 @@ describe("Env integration", function() { env.execute(); }); + it('reports test properties on specs', function(done) { + var env = new jasmineUnderTest.Env(), + reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); + + reporter.specDone.and.callFake(function(e) { + expect(e.properties).toEqual({a: 'Bee'}); + done(); + }); + + env.addReporter(reporter); + env.it('calls setSpecProperty', function() { + env.setSpecProperty('a', 'Bee') + }); + env.execute(); + }); + + it('throws an exception if you try to setSpecProperty outside of a spec', function (done) { + var env = new jasmineUnderTest.Env(), + exception; + + env.describe("a suite", function () { + try { + env.setSpecProperty('a prop', 'val'); + } catch(e) { + exception = e; + } + }); + + var assertions = function() { + expect(exception.message).toBe(`'setSpecProperty' was used when there was no current spec`); + done(); + }; + + env.addReporter({jasmineDone: assertions}); + + env.execute(); + }); + + it('reports test properties on suites', function(done) { + var env = new jasmineUnderTest.Env(), + reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); + + reporter.suiteDone.and.callFake(function(e) { + expect(e.properties).toEqual({b: 'Sweet'}); + done(); + }); + + env.addReporter(reporter); + env.describe('calls setSuiteProperty', function() { + env.beforeEach(() => { + env.setSuiteProperty('b', 'Sweet'); + }); + env.it('a passing spec', () => { + expect.nothing(); + }); + }); + + env.execute(); + }); + + it('throws an exception if you try to setSuiteProperty outside of a suite', function (done) { + var env = new jasmineUnderTest.Env(); + + try { + env.setSuiteProperty('a', 'Bee'); + } catch(e) { + expect(e.message).toBe(`'setSuiteProperty' was used when there was no current suite`); + done(); + } + }); + it("should associate errors thrown from async code with the correct runnable", function(done) { var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone','specDone']); diff --git a/src/core/Env.js b/src/core/Env.js index 47915c0a..1135aee7 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -1124,6 +1124,24 @@ getJasmineRequireObj().Env = function(j$) { return spec; }; + this.setSpecProperty = function(key, value) { + if (!currentRunnable() || currentRunnable() == currentSuite()) { + throw new Error( + "'setSpecProperty' was used when there was no current spec" + ); + } + currentRunnable().setSpecProperty(key, value); + }; + + this.setSuiteProperty = function(key, value) { + if (!currentSuite()) { + throw new Error( + "'setSuiteProperty' was used when there was no current suite" + ); + } + currentSuite().setSuiteProperty(key, value); + }; + this.expect = function(actual) { if (!currentRunnable()) { throw new Error( diff --git a/src/core/Spec.js b/src/core/Spec.js index db35de64..f369ac7a 100644 --- a/src/core/Spec.js +++ b/src/core/Spec.js @@ -48,6 +48,7 @@ getJasmineRequireObj().Spec = function(j$) { * @property {String} pendingReason - If the spec is {@link pending}, this will be the reason. * @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec. * @property {number} duration - The time in ms used by the spec execution, including any before/afterEach. + * @property {Object} properties - user-supplied key-value pairs. */ this.result = { id: this.id, @@ -57,7 +58,8 @@ getJasmineRequireObj().Spec = function(j$) { passedExpectations: [], deprecationWarnings: [], pendingReason: '', - duration: null + duration: null, + properties: null }; } @@ -74,6 +76,11 @@ getJasmineRequireObj().Spec = function(j$) { } }; + Spec.prototype.setSpecProperty = function(key, value) { + this.result.properties = this.result.properties || {}; + this.result.properties[key] = value; + }; + Spec.prototype.expect = function(actual) { return this.expectationFactory(actual, this); }; diff --git a/src/core/Suite.js b/src/core/Suite.js index 4d33ceaa..5cbb9555 100644 --- a/src/core/Suite.js +++ b/src/core/Suite.js @@ -27,6 +27,7 @@ getJasmineRequireObj().Suite = function(j$) { * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite. * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite. * @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach. + * @property {Object} properties - user-supplied key-value pairs. */ this.result = { id: this.id, @@ -34,10 +35,16 @@ getJasmineRequireObj().Suite = function(j$) { fullName: this.getFullName(), failedExpectations: [], deprecationWarnings: [], - duration: null + duration: null, + properties: null }; } + Suite.prototype.setSuiteProperty = function(key, value) { + this.result.properties = this.result.properties || {}; + this.result.properties[key] = value; + }; + Suite.prototype.expect = function(actual) { return this.expectationFactory(actual, this); }; From e94e6c5b7525ea705cf369def76985f279567f01 Mon Sep 17 00:00:00 2001 From: Maksym Kobieliev Date: Tue, 14 Apr 2020 22:01:56 +0300 Subject: [PATCH 22/57] Fix failing unit test --- spec/core/matchers/toHaveBeenCalledOnceWithSpec.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js index 722a05f1..d5bdab43 100644 --- a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js +++ b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js @@ -14,11 +14,10 @@ describe("toHaveBeenCalledOnceWith", function () { }); it("passes through the custom equality testers", function () { - var util = { - contains: jasmine.createSpy('delegated-contains').and.returnValue(false), - equals: jasmineUnderTest.matchersUtil.equals - }, - customEqualityTesters = [function () { return true; }], + var util = jasmineUnderTest.matchersUtil; + spyOn(util, 'contains').and.returnValue(false); + + var customEqualityTesters = [function () { return true; }], matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util, customEqualityTesters), calledSpy = new jasmineUnderTest.Spy('called-spy'); From 8a731e17a7e4d97c73ba8428911c4f6d3a004c23 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Tue, 5 May 2020 17:58:16 -0700 Subject: [PATCH 23/57] Improved jsdocs for user-specified spec/suite properties --- lib/jasmine-core/jasmine.js | 20 ++++++++++++++++++-- src/core/Env.js | 16 ++++++++++++++++ src/core/Spec.js | 2 +- src/core/Suite.js | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 63fa4b59..ace5df87 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -716,7 +716,7 @@ getJasmineRequireObj().Spec = function(j$) { * @property {String} pendingReason - If the spec is {@link pending}, this will be the reason. * @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec. * @property {number} duration - The time in ms used by the spec execution, including any before/afterEach. - * @property {Object} properties - user-supplied key-value pairs. + * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty} */ this.result = { id: this.id, @@ -2075,6 +2075,14 @@ getJasmineRequireObj().Env = function(j$) { return spec; }; + /** + * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} + * @name Env#setSpecProperty + * @since 3.6.0 + * @function + * @param {String} key The name of the property + * @param {*} value The value of the property + */ this.setSpecProperty = function(key, value) { if (!currentRunnable() || currentRunnable() == currentSuite()) { throw new Error( @@ -2084,6 +2092,14 @@ getJasmineRequireObj().Env = function(j$) { currentRunnable().setSpecProperty(key, value); }; + /** + * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} + * @name Env#setSuiteProperty + * @since 3.6.0 + * @function + * @param {String} key The name of the property + * @param {*} value The value of the property + */ this.setSuiteProperty = function(key, value) { if (!currentSuite()) { throw new Error( @@ -8373,7 +8389,7 @@ getJasmineRequireObj().Suite = function(j$) { * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite. * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite. * @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach. - * @property {Object} properties - user-supplied key-value pairs. + * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty} */ this.result = { id: this.id, diff --git a/src/core/Env.js b/src/core/Env.js index 1135aee7..60025850 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -1124,6 +1124,14 @@ getJasmineRequireObj().Env = function(j$) { return spec; }; + /** + * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} + * @name Env#setSpecProperty + * @since 3.6.0 + * @function + * @param {String} key The name of the property + * @param {*} value The value of the property + */ this.setSpecProperty = function(key, value) { if (!currentRunnable() || currentRunnable() == currentSuite()) { throw new Error( @@ -1133,6 +1141,14 @@ getJasmineRequireObj().Env = function(j$) { currentRunnable().setSpecProperty(key, value); }; + /** + * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} + * @name Env#setSuiteProperty + * @since 3.6.0 + * @function + * @param {String} key The name of the property + * @param {*} value The value of the property + */ this.setSuiteProperty = function(key, value) { if (!currentSuite()) { throw new Error( diff --git a/src/core/Spec.js b/src/core/Spec.js index f369ac7a..83d389d4 100644 --- a/src/core/Spec.js +++ b/src/core/Spec.js @@ -48,7 +48,7 @@ getJasmineRequireObj().Spec = function(j$) { * @property {String} pendingReason - If the spec is {@link pending}, this will be the reason. * @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec. * @property {number} duration - The time in ms used by the spec execution, including any before/afterEach. - * @property {Object} properties - user-supplied key-value pairs. + * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty} */ this.result = { id: this.id, diff --git a/src/core/Suite.js b/src/core/Suite.js index 5cbb9555..e660d1f1 100644 --- a/src/core/Suite.js +++ b/src/core/Suite.js @@ -27,7 +27,7 @@ getJasmineRequireObj().Suite = function(j$) { * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite. * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite. * @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach. - * @property {Object} properties - user-supplied key-value pairs. + * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty} */ this.result = { id: this.id, From 0cb304131f4e7f3816ecb1bfca98fbd571d4cb54 Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Tue, 26 May 2020 14:50:01 -0700 Subject: [PATCH 24/57] fix(env): expose setSpec/SuiteProperty on interface --- src/core/requireInterface.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/core/requireInterface.js b/src/core/requireInterface.js index 15a13cd1..adc503f8 100644 --- a/src/core/requireInterface.js +++ b/src/core/requireInterface.js @@ -168,6 +168,30 @@ getJasmineRequireObj().interface = function(jasmine, env) { return env.afterAll.apply(env, arguments); }, + /** + * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} + * @name Env#setSpecProperty + * @since 3.6.0 + * @function + * @param {String} key The name of the property + * @param {*} value The value of the property + */ + setSpecProperty: function(key, value) { + return env.setSpecProperty(key, value); + }, + + /** + * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} + * @name Env#setSuiteProperty + * @since 3.6.0 + * @function + * @param {String} key The name of the property + * @param {*} value The value of the property + */ + setSuiteProperty: function(key, value) { + return env.setSuiteProperty(key, value); + }, + /** * Create an expectation for a spec. * @name expect From 45ad7fd13cb110aa59e027abde1914f6b04eeee4 Mon Sep 17 00:00:00 2001 From: Dirk Puge <67125647+dirkpuge@users.noreply.github.com> Date: Sun, 21 Jun 2020 11:48:05 -0400 Subject: [PATCH 25/57] Added missing periods --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c6a5ff36..caa0533f 100644 --- a/README.md +++ b/README.md @@ -9,35 +9,35 @@ Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run. Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/) -For a quick start guide of Jasmine, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html) +For a quick start guide of Jasmine, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html). Upgrading from Jasmine 2.x? Check out the [3.0 release notes](https://github.com/jasmine/jasmine/blob/v3.0.0/release_notes/3.0.md) for a list of what's new (including breaking changes). ## Contributing -Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/master/.github/CONTRIBUTING.md) +Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/master/.github/CONTRIBUTING.md). ## Installation For the Jasmine NPM module:
-[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm) +[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm). For the Jasmine Ruby Gem:
-[https://github.com/jasmine/jasmine-gem](https://github.com/jasmine/jasmine-gem) +[https://github.com/jasmine/jasmine-gem](https://github.com/jasmine/jasmine-gem). For the Jasmine Python Egg:
-[https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py) +[https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py). For the Jasmine headless browser gulp plugin:
-[https://github.com/jasmine/gulp-jasmine-browser](https://github.com/jasmine/gulp-jasmine-browser) +[https://github.com/jasmine/gulp-jasmine-browser](https://github.com/jasmine/gulp-jasmine-browser). To install Jasmine standalone on your local box (where **_{#.#.#}_** below is substituted by the release number downloaded): -* Download the standalone distribution for your desired release from the [releases page](https://github.com/jasmine/jasmine/releases) -* Create a Jasmine directory in your project - `mkdir my-project/jasmine` -* Move the dist to your project directory - `mv jasmine/dist/jasmine-standalone-{#.#.#}.zip my-project/jasmine` -* Change directory - `cd my-project/jasmine` -* Unzip the dist - `unzip jasmine-standalone-{#.#.#}.zip` +* Download the standalone distribution for your desired release from the [releases page](https://github.com/jasmine/jasmine/releases). +* Create a Jasmine directory in your project. - `mkdir my-project/jasmine` +* Move the dist to your project directory. - `mv jasmine/dist/jasmine-standalone-{#.#.#}.zip my-project/jasmine` +* Change directory. - `cd my-project/jasmine` +* Unzip the dist. - `unzip jasmine-standalone-{#.#.#}.zip` Add the following to your HTML file: @@ -52,16 +52,16 @@ Add the following to your HTML file: ## Supported environments -Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml) +Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml). [![Sauce Test Status](https://saucelabs.com/browser-matrix/jasmine-js.svg)](https://saucelabs.com/u/jasmine-js) ## Support -* Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js) -* Send an email to the list: [jasmine-js@googlegroups.com](mailto:jasmine-js@googlegroups.com) -* View the project backlog at Pivotal Tracker: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606) -* Follow us on Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD) +* Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js). +* Send an email to the list: [jasmine-js@googlegroups.com](mailto:jasmine-js@googlegroups.com). +* View the project backlog at Pivotal Tracker: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606). +* Follow us on Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD). ## Maintainers From 17eda7a2de269cdc400aa517ca159ae6291c182b Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 24 Jun 2020 17:49:11 -0700 Subject: [PATCH 26/57] Depend on head of jasmine-browser This should fix CI, and can be reverted once a new version of jasmine-browser that contains 33bd0fcb0ba990102dcd846e673d07b11041dd44 has been published. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8db8eace..3632bcbe 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "grunt-css-url-embed": "^1.11.1", "grunt-sass": "^3.0.2", "jasmine": "^3.4.0", - "jasmine-browser-runner": "0.3.0", + "jasmine-browser-runner": "github:jasmine/jasmine-browser", "jsdom": "^15.0.0", "load-grunt-tasks": "^4.0.0", "node-sass": "^4.11.0", From ce2161ca32f829cd7c403fe28a98ad774bc7f5b8 Mon Sep 17 00:00:00 2001 From: Tobias Schweizer Date: Thu, 25 Jun 2020 09:41:39 +0200 Subject: [PATCH 27/57] Add additional test for equals matcher --- spec/core/matchers/matchersUtilSpec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index 4894fefa..81874302 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -109,6 +109,11 @@ describe("matchersUtil", function() { expect(matchersUtil.equals(123, 456)).toBe(false); }); + it("fails for a Number and a String that have equivalent values", function() { + var matchersUtil = new jasmineUnderTest.MatchersUtil(); + expect(matchersUtil.equals(123, "123")).toBe(false); + }); + it("passes for Dates that are equivalent", function() { var matchersUtil = new jasmineUnderTest.MatchersUtil(); expect(matchersUtil.equals(new Date("Jan 1, 1970"), new Date("Jan 1, 1970"))).toBe(true); From f4753ac0a44bdc578626db63b56c84bda0058d77 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 25 Jun 2020 07:36:06 -0700 Subject: [PATCH 28/57] Fixed syntax errors in IE 10 --- spec/core/integration/EnvSpec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 247744d3..c811c9bf 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -2000,7 +2000,7 @@ describe("Env integration", function() { }); var assertions = function() { - expect(exception.message).toBe(`'setSpecProperty' was used when there was no current spec`); + expect(exception.message).toBe("'setSpecProperty' was used when there was no current spec"); done(); }; @@ -2020,10 +2020,10 @@ describe("Env integration", function() { env.addReporter(reporter); env.describe('calls setSuiteProperty', function() { - env.beforeEach(() => { + env.beforeEach(function() { env.setSuiteProperty('b', 'Sweet'); }); - env.it('a passing spec', () => { + env.it('a passing spec', function() { expect.nothing(); }); }); @@ -2037,7 +2037,7 @@ describe("Env integration", function() { try { env.setSuiteProperty('a', 'Bee'); } catch(e) { - expect(e.message).toBe(`'setSuiteProperty' was used when there was no current suite`); + expect(e.message).toBe("'setSuiteProperty' was used when there was no current suite"); done(); } }); From 3943cc2ddbba17b50b706a79d7406340b4641b53 Mon Sep 17 00:00:00 2001 From: "Terence D. Honles" Date: Tue, 2 Jun 2020 10:35:27 -0700 Subject: [PATCH 29/57] allow spy throwError to throw an Object When using the following code to simulate a node error: spyOn(process, 'kill').and.throwError({code: 'ESRCH'}) The object passed in will be converted to a string by the Error constructor and result in '[object Object]' which is not very useful. This PR changes the ``throwError`` spy strategy to only convert strings into an Error object, but any other objects which are passed in will be thrown as is. This means the spy strategy can never emulate throwing a bare string ``throw 'error'``, but this would be a backward incompatible change. --- spec/core/SpyStrategySpec.js | 14 +++++++++++++- src/core/SpyStrategy.js | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index 5e454b64..76a3a1e2 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -70,7 +70,7 @@ describe('SpyStrategy', function() { expect(originalFn).not.toHaveBeenCalled(); }); - it('allows a non-Error to be thrown, wrapping it into an exception when executed', function() { + it('allows a string to be thrown, wrapping it into an exception when executed', function() { var originalFn = jasmine.createSpy('original'), spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }); @@ -82,6 +82,18 @@ describe('SpyStrategy', function() { expect(originalFn).not.toHaveBeenCalled(); }); + it('allows a non-Error to be thrown when executed', function() { + var originalFn = jasmine.createSpy('original'), + spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }); + + spyStrategy.throwError({ code: 'ESRCH' }); + + expect(function() { + spyStrategy.exec(); + }).toThrow({ code: 'ESRCH' }); + expect(originalFn).not.toHaveBeenCalled(); + }); + it('allows a fake function to be called instead', function() { var originalFn = jasmine.createSpy('original'), fakeFn = jasmine.createSpy('fake').and.returnValue(67), diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index 7e86abd6..41aa9258 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -150,10 +150,10 @@ getJasmineRequireObj().SpyStrategy = function(j$) { * @name SpyStrategy#throwError * @since 2.0.0 * @function - * @param {Error|String} something Thing to throw + * @param {Error|Object|String} something Thing to throw */ SpyStrategy.prototype.throwError = function(something) { - var error = something instanceof Error ? something : new Error(something); + var error = j$.isString_(something) ? new Error(something) : something; this.plan = function() { throw error; }; From b3ab9fad9d62ef72fa4851b690b56c06d86025c2 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Fri, 26 Jun 2020 15:14:02 -0700 Subject: [PATCH 30/57] Updated toHaveBeenCalledOnceWith for new matcher interface --- lib/jasmine-core/jasmine.js | 6 +++--- .../matchers/toHaveBeenCalledOnceWithSpec.js | 17 ++++++++--------- src/core/matchers/toHaveBeenCalledOnceWith.js | 6 +++--- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 1f079a35..f618cced 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -5816,7 +5816,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { * @example * expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar', 2); */ - function toHaveBeenCalledOnceWith(util, customEqualityTesters) { + function toHaveBeenCalledOnceWith(util) { return { compare: function () { var args = Array.prototype.slice.call(arguments, 0), @@ -5831,7 +5831,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { return ' ' + j$.pp(argsForCall); }); - if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs)) { return { pass: true, message: 'Expected spy ' + actual.and.identity + ' to have been called 0 times, multiple times, or once, but with arguments different from:\n' @@ -5844,7 +5844,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { function getDiffs() { return actual.calls.allArgs().map(function (argsForCall, callIx) { var diffBuilder = new j$.DiffBuilder(); - util.equals(argsForCall, expectedArgs, customEqualityTesters, diffBuilder); + util.equals(argsForCall, expectedArgs, diffBuilder); return diffBuilder.getMessage(); }); } diff --git a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js index d5bdab43..be0e95bc 100644 --- a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js +++ b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js @@ -13,18 +13,17 @@ describe("toHaveBeenCalledOnceWith", function () { expect(result.message).toEqual("Expected spy called-spy to have been called 0 times, multiple times, or once, but with arguments different from:\n [ 'a', 'b' ]\nBut the actual call was:\n [ 'a', 'b' ].\n\n"); }); - it("passes through the custom equality testers", function () { - var util = jasmineUnderTest.matchersUtil; - spyOn(util, 'contains').and.returnValue(false); - - var customEqualityTesters = [function () { return true; }], - matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util, customEqualityTesters), - calledSpy = new jasmineUnderTest.Spy('called-spy'); + it("supports custom equality testers", function () { + var customEqualityTesters = [function() { return true; }], + matchersUtil = new jasmineUnderTest.MatchersUtil({customTesters: customEqualityTesters}), + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(matchersUtil), + calledSpy = new jasmineUnderTest.Spy('called-spy'), + result; calledSpy('a', 'b'); - matcher.compare(calledSpy, 'a', 'b'); + result = matcher.compare(calledSpy, 'a', 'a'); - expect(util.contains).toHaveBeenCalledWith([['a', 'b']], ['a', 'b'], customEqualityTesters); + expect(result.pass).toBe(true); }); it("fails when the actual was never called", function () { diff --git a/src/core/matchers/toHaveBeenCalledOnceWith.js b/src/core/matchers/toHaveBeenCalledOnceWith.js index 035848b0..d7be3782 100644 --- a/src/core/matchers/toHaveBeenCalledOnceWith.js +++ b/src/core/matchers/toHaveBeenCalledOnceWith.js @@ -11,7 +11,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { * @example * expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar', 2); */ - function toHaveBeenCalledOnceWith(util, customEqualityTesters) { + function toHaveBeenCalledOnceWith(util) { return { compare: function () { var args = Array.prototype.slice.call(arguments, 0), @@ -26,7 +26,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { return ' ' + j$.pp(argsForCall); }); - if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs)) { return { pass: true, message: 'Expected spy ' + actual.and.identity + ' to have been called 0 times, multiple times, or once, but with arguments different from:\n' @@ -39,7 +39,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { function getDiffs() { return actual.calls.allArgs().map(function (argsForCall, callIx) { var diffBuilder = new j$.DiffBuilder(); - util.equals(argsForCall, expectedArgs, customEqualityTesters, diffBuilder); + util.equals(argsForCall, expectedArgs, diffBuilder); return diffBuilder.getMessage(); }); } From 11b63e4e3ed4cdd21dd091b8133ce2bbc61eb0a0 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Mon, 29 Jun 2020 14:36:00 -0700 Subject: [PATCH 31/57] Fixed references to master in docs --- .github/CONTRIBUTING.md | 4 ++-- README.md | 8 ++++---- RELEASE.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 686c71de..3a23f9a5 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -17,7 +17,7 @@ git clone git@github.com:yourUserName/jasmine.git # Clone your fork cd jasmine # Change directory git remote add upstream https://github.com/jasmine/jasmine.git # Assign original repository to a remote named 'upstream' git fetch upstream # Fetch changes not present in your local repository -git merge upstream/master # Sync local master with upstream repository +git merge upstream/main # Sync local main with upstream repository git checkout -b my-new-feature # Create your feature branch git commit -am 'Add some feature' # Commit your changes git push origin my-new-feature # Push to the branch @@ -121,7 +121,7 @@ The easiest way to run the tests in **Internet Explorer** is to run a VM that ha 1. Build `jasmine.js` with `npm run build` and run all specs again - this ensures that your changes self-test well 1. Revert your changes to `jasmine.js` and `jasmine-html.js` * We do this because `jasmine.js` and `jasmine-html.js` are auto-generated (as you've seen in the previous steps) and accepting multiple pull requests when this auto-generated file changes causes lots of headaches - * When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into master + * When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into main Note that we use Travis for Continuous Integration. We only accept green pull requests. diff --git a/README.md b/README.md index caa0533f..062885f5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -[](http://jasmine.github.io) +[](http://jasmine.github.io) -[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine) +[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=main)](https://travis-ci.org/jasmine/jasmine) [![Open Source Helpers](https://www.codetriage.com/jasmine/jasmine/badges/users.svg)](https://www.codetriage.com/jasmine/jasmine) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_shield) @@ -15,7 +15,7 @@ Upgrading from Jasmine 2.x? Check out the [3.0 release notes](https://github.com ## Contributing -Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/master/.github/CONTRIBUTING.md). +Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/main/.github/CONTRIBUTING.md). ## Installation @@ -52,7 +52,7 @@ Add the following to your HTML file: ## Supported environments -Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml). +Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/main/.travis.yml). [![Sauce Test Status](https://saucelabs.com/browser-matrix/jasmine-js.svg)](https://saucelabs.com/u/jasmine-js) diff --git a/RELEASE.md b/RELEASE.md index 20790a52..61ffbadc 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -7,7 +7,7 @@ Follow the instructions in `CONTRIBUTING.md` during development. ### Git Rules -Please attempt to keep commits to `master` small, but cohesive. If a feature is contained in a bunch of small commits (e.g., it has several wip commits or small work), please squash them when pushing to `master`. +Please attempt to keep commits to `main` small, but cohesive. If a feature is contained in a bunch of small commits (e.g., it has several wip commits or small work), please squash them when pushing to `main`. ### Version From 8cd4873e4859e0f0177c1cbd9910e923bac60092 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Mon, 29 Jun 2020 14:37:08 -0700 Subject: [PATCH 32/57] Removed broken Sauce status image --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 062885f5..94ee7162 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,6 @@ Add the following to your HTML file: Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/main/.travis.yml). -[![Sauce Test Status](https://saucelabs.com/browser-matrix/jasmine-js.svg)](https://saucelabs.com/u/jasmine-js) - ## Support * Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js). From fb2327736771833b089e1d00b8a96592714f3d22 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 1 Jul 2020 12:30:24 -0700 Subject: [PATCH 33/57] Removed IE from Travis build matrix We still support IE 10 and 11, but the Node selenium-webdriver has serious problems with it. Until that's fixed or worked around, IE builds won't pass. This gets us otherwise green so we can easily see if anything else is broken. --- .travis.yml | 8 -------- README.md | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a2cb0db..bfeccecd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,14 +19,6 @@ env: matrix: include: - - env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=11 SAUCE_OS="Windows 8.1" - if: type != pull_request - addons: - sauce_connect: true - - env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=10 SAUCE_OS="Windows 8" - if: type != pull_request - addons: - sauce_connect: true - env: JASMINE_BROWSER="firefox" SAUCE_BROWSER_VERSION='' SAUCE_OS="Windows 10" if: type != pull_request addons: diff --git a/README.md b/README.md index 94ee7162..e8b7fd53 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,20 @@ Add the following to your HTML file: ## Supported environments -Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/main/.travis.yml). +Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and Internet Explorer) as well as nodejs. + +| Environment | Supported versions | +|-------------------|--------------------| +| Node | 8, 10, 12 | +| Safari | 8-13 | +| Chrome | Evergreen | +| Firefox | Evergreen, 68 | +| Edge | Evergreen | +| Internet Explorer | 10, 11 | + +For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us +at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work. +However, Jasmine isn't tested against them and they aren't actively supported. ## Support From ba2aae63bed536ed632fed8ed82cc0f31bd24104 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 1 Jul 2020 16:05:02 -0700 Subject: [PATCH 34/57] Run eslint against all files --- package.json | 8 ++------ spec/.eslintrc.js | 13 +++++++++++++ spec/core/matchers/matchersUtilSpec.js | 4 ++-- src/core/matchers/DiffBuilder.js | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 spec/.eslintrc.js diff --git a/package.json b/package.json index 3632bcbe..fb1d215d 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "bdd" ], "scripts": { - "posttest": "eslint src/**/*.js spec/**/*.js && prettier --check src/**/*.js spec/**/*.js", + "posttest": "eslint \"src/**/*.js\" \"spec/**/*.js\" && prettier --check src/**/*.js spec/**/*.js", "test": "grunt --stack execSpecsInNode", "cleanup": "prettier --write src/**/*.js spec/**/*.js", "build": "grunt buildDistribution", @@ -28,7 +28,7 @@ "devDependencies": { "acorn": "^6.0.0", "ejs": "^2.5.5", - "eslint": "^5.16.0", + "eslint": "7.3.1", "express": "^4.16.4", "fast-check": "^1.21.0", "fast-glob": "^2.2.6", @@ -67,10 +67,6 @@ } ], "block-spacing": "error", - "comma-dangle": [ - "error", - "never" - ], "func-call-spacing": [ "error", "never" diff --git a/spec/.eslintrc.js b/spec/.eslintrc.js new file mode 100644 index 00000000..969a4efd --- /dev/null +++ b/spec/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + rules: { + // Relax rules for now to allow for the quirks of the test suite + // TODO: We should probably remove these & fix the resulting errors + "quotes": "off", + "semi": "off", + "key-spacing": "off", + "space-before-blocks": "off", + "no-unused-vars": "off", + "no-trailing-spaces": "off", + "block-spacing": "off", + } +} diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index 81874302..10bd0ec0 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -821,7 +821,7 @@ describe("matchersUtil", function() { expect(diffBuilder.setRoots).toHaveBeenCalledWith(actual, expected); expect(diffBuilder.withPath).toHaveBeenCalledWith('x', jasmine.any(Function)); - expect(diffBuilder.recordMismatch). toHaveBeenCalledWith(); + expect(diffBuilder.recordMismatch).toHaveBeenCalledWith(); }); it("records both objects when the tester does not implement valuesForDiff", function() { @@ -836,7 +836,7 @@ describe("matchersUtil", function() { expect(diffBuilder.setRoots).toHaveBeenCalledWith(actual, expected); expect(diffBuilder.withPath).toHaveBeenCalledWith('x', jasmine.any(Function)); - expect(diffBuilder.recordMismatch). toHaveBeenCalledWith(); + expect(diffBuilder.recordMismatch).toHaveBeenCalledWith(); }); }); diff --git a/src/core/matchers/DiffBuilder.js b/src/core/matchers/DiffBuilder.js index 4e43aeaa..83333d8a 100644 --- a/src/core/matchers/DiffBuilder.js +++ b/src/core/matchers/DiffBuilder.js @@ -72,7 +72,7 @@ getJasmineRequireObj().DiffBuilder = function (j$) { }; function dereferencePath(objectPath, actual, expected, pp) { - var i, asymmetricResult + var i, asymmetricResult; for (i = 0; i < objectPath.components.length; i++) { actual = actual[objectPath.components[i]]; From 4e2f703615eacecf5054dd2b1f20a9da69f14f38 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 1 Jul 2020 17:28:45 -0700 Subject: [PATCH 35/57] Check for syntax and standard library objects that don't work in IE --- package.json | 17 +++- spec/.eslintrc.js | 4 + spec/core/AsyncExpectationSpec.js | 1 + spec/core/PrettyPrintSpec.js | 8 +- spec/core/UtilSpec.js | 2 +- spec/core/asymmetric_equality/AnySpec.js | 12 +-- spec/core/asymmetric_equality/AnythingSpec.js | 8 +- spec/core/asymmetric_equality/EmptySpec.js | 12 +-- .../asymmetric_equality/MapContainingSpec.js | 1 + spec/core/asymmetric_equality/NotEmptySpec.js | 12 +-- .../asymmetric_equality/SetContainingSpec.js | 1 + spec/core/baseSpec.js | 2 +- .../integration/CustomAsyncMatchersSpec.js | 1 + spec/core/integration/EnvSpec.js | 10 +-- spec/core/integration/MatchersSpec.js | 26 +++--- spec/core/matchers/async/toBePendingSpec.js | 1 + spec/core/matchers/async/toBeRejectedSpec.js | 1 + .../async/toBeRejectedWithErrorSpec.js | 1 + .../matchers/async/toBeRejectedWithSpec.js | 1 + spec/core/matchers/async/toBeResolvedSpec.js | 1 + .../core/matchers/async/toBeResolvedToSpec.js | 1 + spec/core/matchers/matchersUtilSpec.js | 69 ++++++++-------- spec/core/matchers/toEqualSpec.js | 80 +++++++++---------- spec/core/matchers/toHaveSizeSpec.js | 1 + spec/helpers/checkForMap.js | 1 + spec/helpers/checkForSet.js | 1 + spec/helpers/checkForSymbol.js | 1 + spec/helpers/checkForTypedArrays.js | 1 + .../asymmetricEqualityTesterArgCompatShim.js | 2 +- src/core/matchers/async/toBePending.js | 3 +- src/core/matchers/toHaveSize.js | 2 +- 31 files changed, 159 insertions(+), 125 deletions(-) diff --git a/package.json b/package.json index fb1d215d..a7d89f70 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "acorn": "^6.0.0", "ejs": "^2.5.5", "eslint": "7.3.1", + "eslint-plugin-compat": "^3.8.0", "express": "^4.16.4", "fast-check": "^1.21.0", "fast-glob": "^2.2.6", @@ -52,6 +53,12 @@ "singleQuote": true }, "eslintConfig": { + "extends": [ + "plugin:compat/recommended" + ], + "parserOptions": { + "ecmaVersion": 5 + }, "rules": { "quotes": [ "error", @@ -81,5 +88,13 @@ ], "space-before-blocks": "error" } - } + }, + "browserslist": [ + "Safari >= 8", + "last 2 Chrome versions", + "last 2 Firefox versions", + "Firefox 68", + "last 2 Edge versions", + "IE >= 10" + ] } diff --git a/spec/.eslintrc.js b/spec/.eslintrc.js index 969a4efd..bfbec213 100644 --- a/spec/.eslintrc.js +++ b/spec/.eslintrc.js @@ -1,4 +1,8 @@ module.exports = { + "ignorePatterns": [ + "support/ci.js", + "support/jasmine-browser.js" + ], rules: { // Relax rules for now to allow for the quirks of the test suite // TODO: We should probably remove these & fix the resulting errors diff --git a/spec/core/AsyncExpectationSpec.js b/spec/core/AsyncExpectationSpec.js index 40f63731..94e2438c 100644 --- a/spec/core/AsyncExpectationSpec.js +++ b/spec/core/AsyncExpectationSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('AsyncExpectation', function() { beforeEach(function() { jasmineUnderTest.Expectation.addAsyncCoreMatchers( diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 6c43cbd4..de6a11d6 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -19,7 +19,7 @@ describe('PrettyPrinter', function() { describe('stringify sets', function() { it('should stringify sets properly', function() { jasmine.getEnv().requireFunctioningSets(); - var set = new Set(); + var set = new Set(); // eslint-disable-line compat/compat set.add(1); set.add(2); var pp = jasmineUnderTest.makePrettyPrinter(); @@ -32,7 +32,7 @@ describe('PrettyPrinter', function() { try { jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2; - var set = new Set(); + var set = new Set(); // eslint-disable-line compat/compat set.add('a'); set.add('b'); set.add('c'); @@ -47,7 +47,7 @@ describe('PrettyPrinter', function() { describe('stringify maps', function() { it('should stringify maps properly', function() { jasmine.getEnv().requireFunctioningMaps(); - var map = new Map(); + var map = new Map(); // eslint-disable-line compat/compat map.set(1, 2); var pp = jasmineUnderTest.makePrettyPrinter(); expect(pp(map)).toEqual('Map( [ 1, 2 ] )'); @@ -59,7 +59,7 @@ describe('PrettyPrinter', function() { try { jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2; - var map = new Map(); + var map = new Map(); // eslint-disable-line compat/compat map.set('a', 1); map.set('b', 2); map.set('c', 3); diff --git a/spec/core/UtilSpec.js b/spec/core/UtilSpec.js index 759ef8ce..8e05c6ab 100644 --- a/spec/core/UtilSpec.js +++ b/spec/core/UtilSpec.js @@ -40,7 +40,7 @@ describe('jasmineUnderTest.util', function() { beforeEach(function() { jasmine.getEnv().requirePromises(); - mockNativePromise = new Promise(function(res, rej) {}); + mockNativePromise = new Promise(function(res, rej) {}); // eslint-disable-line compat/compat mockPromiseLikeObject = new mockPromiseLike(); }); diff --git a/spec/core/asymmetric_equality/AnySpec.js b/spec/core/asymmetric_equality/AnySpec.js index 1739ae6f..8e28c306 100644 --- a/spec/core/asymmetric_equality/AnySpec.js +++ b/spec/core/asymmetric_equality/AnySpec.js @@ -34,7 +34,7 @@ describe("Any", function() { var any = new jasmineUnderTest.Any(Map); - expect(any.asymmetricMatch(new Map())).toBe(true); + expect(any.asymmetricMatch(new Map())).toBe(true); // eslint-disable-line compat/compat }); it("matches a Set", function() { @@ -42,23 +42,23 @@ describe("Any", function() { var any = new jasmineUnderTest.Any(Set); - expect(any.asymmetricMatch(new Set())).toBe(true); + expect(any.asymmetricMatch(new Set())).toBe(true); // eslint-disable-line compat/compat }); it("matches a TypedArray", function() { jasmine.getEnv().requireFunctioningTypedArrays(); - var any = new jasmineUnderTest.Any(Uint32Array); + var any = new jasmineUnderTest.Any(Uint32Array); // eslint-disable-line compat/compat - expect(any.asymmetricMatch(new Uint32Array([]))).toBe(true); + expect(any.asymmetricMatch(new Uint32Array([]))).toBe(true); // eslint-disable-line compat/compat }); it("matches a Symbol", function() { jasmine.getEnv().requireFunctioningSymbols(); - var any = new jasmineUnderTest.Any(Symbol); + var any = new jasmineUnderTest.Any(Symbol); // eslint-disable-line compat/compat - expect(any.asymmetricMatch(Symbol())).toBe(true); + expect(any.asymmetricMatch(Symbol())).toBe(true); // eslint-disable-line compat/compat }); it("matches another constructed object", function() { diff --git a/spec/core/asymmetric_equality/AnythingSpec.js b/spec/core/asymmetric_equality/AnythingSpec.js index 216757eb..4e251b91 100644 --- a/spec/core/asymmetric_equality/AnythingSpec.js +++ b/spec/core/asymmetric_equality/AnythingSpec.js @@ -28,7 +28,7 @@ describe("Anything", function() { var anything = new jasmineUnderTest.Anything(); - expect(anything.asymmetricMatch(new Map())).toBe(true); + expect(anything.asymmetricMatch(new Map())).toBe(true); // eslint-disable-line compat/compat }); it("matches a Set", function() { @@ -36,7 +36,7 @@ describe("Anything", function() { var anything = new jasmineUnderTest.Anything(); - expect(anything.asymmetricMatch(new Set())).toBe(true); + expect(anything.asymmetricMatch(new Set())).toBe(true); // eslint-disable-line compat/compat }); it("matches a TypedArray", function() { @@ -44,7 +44,7 @@ describe("Anything", function() { var anything = new jasmineUnderTest.Anything(); - expect(anything.asymmetricMatch(new Uint32Array([]))).toBe(true); + expect(anything.asymmetricMatch(new Uint32Array([]))).toBe(true); // eslint-disable-line compat/compat }); it("matches a Symbol", function() { @@ -52,7 +52,7 @@ describe("Anything", function() { var anything = new jasmineUnderTest.Anything(); - expect(anything.asymmetricMatch(Symbol())).toBe(true); + expect(anything.asymmetricMatch(Symbol())).toBe(true); // eslint-disable-line compat/compat }); it("doesn't match undefined", function() { diff --git a/spec/core/asymmetric_equality/EmptySpec.js b/spec/core/asymmetric_equality/EmptySpec.js index 902b5001..48271ce5 100644 --- a/spec/core/asymmetric_equality/EmptySpec.js +++ b/spec/core/asymmetric_equality/EmptySpec.js @@ -24,20 +24,20 @@ describe("Empty", function () { it("matches an empty map", function () { jasmine.getEnv().requireFunctioningMaps(); var empty = new jasmineUnderTest.Empty(); - var fullMap = new Map(); + var fullMap = new Map(); // eslint-disable-line compat/compat fullMap.set('thing', 2); - expect(empty.asymmetricMatch(new Map())).toBe(true); + expect(empty.asymmetricMatch(new Map())).toBe(true); // eslint-disable-line compat/compat expect(empty.asymmetricMatch(fullMap)).toBe(false); }); it("matches an empty set", function () { jasmine.getEnv().requireFunctioningSets(); var empty = new jasmineUnderTest.Empty(); - var fullSet = new Set(); + var fullSet = new Set(); // eslint-disable-line compat/compat fullSet.add(3); - expect(empty.asymmetricMatch(new Set())).toBe(true); + expect(empty.asymmetricMatch(new Set())).toBe(true); // eslint-disable-line compat/compat expect(empty.asymmetricMatch(fullSet)).toBe(false); }); @@ -45,7 +45,7 @@ describe("Empty", function () { jasmine.getEnv().requireFunctioningTypedArrays(); var empty = new jasmineUnderTest.Empty(); - expect(empty.asymmetricMatch(new Int16Array())).toBe(true); - expect(empty.asymmetricMatch(new Int16Array([1,2]))).toBe(false); + expect(empty.asymmetricMatch(new Int16Array())).toBe(true); // eslint-disable-line compat/compat + expect(empty.asymmetricMatch(new Int16Array([1,2]))).toBe(false); // eslint-disable-line compat/compat }); }); diff --git a/spec/core/asymmetric_equality/MapContainingSpec.js b/spec/core/asymmetric_equality/MapContainingSpec.js index c9ea83a6..dc89218d 100644 --- a/spec/core/asymmetric_equality/MapContainingSpec.js +++ b/spec/core/asymmetric_equality/MapContainingSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('MapContaining', function() { function MapI(iterable) { // for IE11 var map = new Map(); diff --git a/spec/core/asymmetric_equality/NotEmptySpec.js b/spec/core/asymmetric_equality/NotEmptySpec.js index 04c05966..d00ee013 100644 --- a/spec/core/asymmetric_equality/NotEmptySpec.js +++ b/spec/core/asymmetric_equality/NotEmptySpec.js @@ -24,9 +24,9 @@ describe("NotEmpty", function () { it("matches a non empty map", function () { jasmine.getEnv().requireFunctioningMaps(); var notEmpty = new jasmineUnderTest.NotEmpty(); - var fullMap = new Map(); + var fullMap = new Map(); // eslint-disable-line compat/compat fullMap.set('one', 1); - var emptyMap = new Map(); + var emptyMap = new Map(); // eslint-disable-line compat/compat expect(notEmpty.asymmetricMatch(fullMap)).toBe(true); expect(notEmpty.asymmetricMatch(emptyMap)).toBe(false); @@ -35,9 +35,9 @@ describe("NotEmpty", function () { it("matches a non empty set", function () { jasmine.getEnv().requireFunctioningSets(); var notEmpty = new jasmineUnderTest.NotEmpty(); - var filledSet = new Set(); + var filledSet = new Set(); // eslint-disable-line compat/compat filledSet.add(1); - var emptySet = new Set(); + var emptySet = new Set(); // eslint-disable-line compat/compat expect(notEmpty.asymmetricMatch(filledSet)).toBe(true); expect(notEmpty.asymmetricMatch(emptySet)).toBe(false); @@ -47,7 +47,7 @@ describe("NotEmpty", function () { jasmine.getEnv().requireFunctioningTypedArrays(); var notEmpty = new jasmineUnderTest.NotEmpty(); - expect(notEmpty.asymmetricMatch(new Int16Array([1,2,3]))).toBe(true); - expect(notEmpty.asymmetricMatch(new Int16Array())).toBe(false); + expect(notEmpty.asymmetricMatch(new Int16Array([1,2,3]))).toBe(true); // eslint-disable-line compat/compat + expect(notEmpty.asymmetricMatch(new Int16Array())).toBe(false); // eslint-disable-line compat/compat }); }); diff --git a/spec/core/asymmetric_equality/SetContainingSpec.js b/spec/core/asymmetric_equality/SetContainingSpec.js index 50ee9d5b..3f7b1b16 100644 --- a/spec/core/asymmetric_equality/SetContainingSpec.js +++ b/spec/core/asymmetric_equality/SetContainingSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('SetContaining', function() { function SetI(iterable) { // for IE11 var set = new Set(); diff --git a/spec/core/baseSpec.js b/spec/core/baseSpec.js index b85721b9..fbdf9d9d 100644 --- a/spec/core/baseSpec.js +++ b/spec/core/baseSpec.js @@ -55,7 +55,7 @@ describe('base helpers', function() { describe('isSet', function() { it('returns true when the object is a Set', function() { jasmine.getEnv().requireFunctioningSets(); - expect(jasmineUnderTest.isSet(new Set())).toBe(true); + expect(jasmineUnderTest.isSet(new Set())).toBe(true); // eslint-disable-line compat/compat }); it('returns false when the object is not a Set', function() { diff --git a/spec/core/integration/CustomAsyncMatchersSpec.js b/spec/core/integration/CustomAsyncMatchersSpec.js index e1a8286c..1b60bb45 100644 --- a/spec/core/integration/CustomAsyncMatchersSpec.js +++ b/spec/core/integration/CustomAsyncMatchersSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('Custom Async Matchers (Integration)', function() { var env; diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index c811c9bf..090bb54c 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -2581,7 +2581,7 @@ describe("Env integration", function() { function fail(innerDone) { var resolve; - var p = new Promise(function(res, rej) { resolve = res }); + var p = new Promise(function(res, rej) { resolve = res }); // eslint-disable-line compat/compat env.expectAsync(p).toBeRejected().then(innerDone); resolve(); } @@ -2613,7 +2613,7 @@ describe("Env integration", function() { env.it('has an async failure', function() { env.addCustomEqualityTester(function() { return true; }); - var p = Promise.resolve('something'); + var p = Promise.resolve('something'); // eslint-disable-line compat/compat return env.expectAsync(p).toBeResolvedTo('something else'); }); @@ -2639,7 +2639,7 @@ describe("Env integration", function() { env.it('has an async failure', function() { env.addCustomEqualityTester(function() { return true; }); - var p = Promise.resolve(); + var p = Promise.resolve(); // eslint-disable-line compat/compat return env.expectAsync(p).toBeRejected(); }); @@ -2650,7 +2650,7 @@ describe("Env integration", function() { jasmine.getEnv().requirePromises(); var resolve, - promise = new Promise(function(res) { resolve = res; }); + promise = new Promise(function(res) { resolve = res; }); // eslint-disable-line compat/compat env.describe('a suite', function() { env.it('does not wait', function() { @@ -2698,7 +2698,7 @@ describe("Env integration", function() { jasmine.getEnv().requirePromises(); var resolve, - promise = new Promise(function(res) { resolve = res; }); + promise = new Promise(function(res) { resolve = res; }); // eslint-disable-line compat/compat env.describe('a suite', function() { env.afterAll(function() { diff --git a/spec/core/integration/MatchersSpec.js b/spec/core/integration/MatchersSpec.js index 5e253e08..92b7307f 100644 --- a/spec/core/integration/MatchersSpec.js +++ b/spec/core/integration/MatchersSpec.js @@ -335,11 +335,11 @@ describe('Matchers (Integration)', function() { describe('toBeResolved', function() { verifyPassesAsync(function(env) { - return env.expectAsync(Promise.resolve()).toBeResolved(); + return env.expectAsync(Promise.resolve()).toBeResolved(); // eslint-disable-line compat/compat }); verifyFailsAsync(function(env) { - return env.expectAsync(Promise.reject()).toBeResolved(); + return env.expectAsync(Promise.reject()).toBeResolved(); // eslint-disable-line compat/compat }); }); @@ -348,11 +348,11 @@ describe('Matchers (Integration)', function() { env.addCustomEqualityTester(function(a, b) { return a.toString() === b.toString(); }); - return env.expectAsync(Promise.resolve('5')).toBeResolvedTo(5); + return env.expectAsync(Promise.resolve('5')).toBeResolvedTo(5); // eslint-disable-line compat/compat }); verifyFailsAsync(function(env) { - return env.expectAsync(Promise.resolve('foo')).toBeResolvedTo('bar'); + return env.expectAsync(Promise.resolve('foo')).toBeResolvedTo('bar'); // eslint-disable-line compat/compat }); verifyFailsWithCustomObjectFormattersAsync({ @@ -360,7 +360,7 @@ describe('Matchers (Integration)', function() { return '|' + val + '|'; }, expectations: function(env) { - return env.expectAsync(Promise.resolve('x')).toBeResolvedTo('y'); + return env.expectAsync(Promise.resolve('x')).toBeResolvedTo('y'); // eslint-disable-line compat/compat }, expectedMessage: 'Expected a promise to be resolved to |y| ' + 'but it was resolved to |x|.' @@ -369,11 +369,11 @@ describe('Matchers (Integration)', function() { describe('toBeRejected', function() { verifyPassesAsync(function(env) { - return env.expectAsync(Promise.reject('nope')).toBeRejected(); + return env.expectAsync(Promise.reject('nope')).toBeRejected(); // eslint-disable-line compat/compat }); verifyFailsAsync(function(env) { - return env.expectAsync(Promise.resolve()).toBeRejected(); + return env.expectAsync(Promise.resolve()).toBeRejected(); // eslint-disable-line compat/compat }); }); @@ -382,11 +382,11 @@ describe('Matchers (Integration)', function() { env.addCustomEqualityTester(function(a, b) { return a.toString() === b.toString(); }); - return env.expectAsync(Promise.reject('5')).toBeRejectedWith(5); + return env.expectAsync(Promise.reject('5')).toBeRejectedWith(5); // eslint-disable-line compat/compat }); verifyFailsAsync(function(env) { - return env.expectAsync(Promise.resolve()).toBeRejectedWith('nope'); + return env.expectAsync(Promise.resolve()).toBeRejectedWith('nope'); // eslint-disable-line compat/compat }); verifyFailsWithCustomObjectFormattersAsync({ @@ -394,7 +394,7 @@ describe('Matchers (Integration)', function() { return '|' + val + '|'; }, expectations: function(env) { - return env.expectAsync(Promise.reject('x')).toBeRejectedWith('y'); + return env.expectAsync(Promise.reject('x')).toBeRejectedWith('y'); // eslint-disable-line compat/compat }, expectedMessage: 'Expected a promise to be rejected with |y| ' + 'but it was rejected with |x|.' @@ -403,11 +403,11 @@ describe('Matchers (Integration)', function() { describe('toBeRejectedWithError', function() { verifyPassesAsync(function(env) { - return env.expectAsync(Promise.reject(new Error())).toBeRejectedWithError(Error); + return env.expectAsync(Promise.reject(new Error())).toBeRejectedWithError(Error); // eslint-disable-line compat/compat }); verifyFailsAsync(function(env) { - return env.expectAsync(Promise.resolve()).toBeRejectedWithError(Error); + return env.expectAsync(Promise.resolve()).toBeRejectedWithError(Error); // eslint-disable-line compat/compat }); verifyFailsWithCustomObjectFormattersAsync({ @@ -415,7 +415,7 @@ describe('Matchers (Integration)', function() { return '|' + val + '|'; }, expectations: function(env) { - return env.expectAsync(Promise.reject('foo')).toBeRejectedWithError('foo'); + return env.expectAsync(Promise.reject('foo')).toBeRejectedWithError('foo'); // eslint-disable-line compat/compat }, expectedMessage: 'Expected a promise to be rejected with Error: |foo| ' + 'but it was rejected with |foo|.' diff --git a/spec/core/matchers/async/toBePendingSpec.js b/spec/core/matchers/async/toBePendingSpec.js index 318e22b7..285414f1 100644 --- a/spec/core/matchers/async/toBePendingSpec.js +++ b/spec/core/matchers/async/toBePendingSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('toBePending', function() { it('passes if the actual promise is pending', function() { jasmine.getEnv().requirePromises(); diff --git a/spec/core/matchers/async/toBeRejectedSpec.js b/spec/core/matchers/async/toBeRejectedSpec.js index 61bd2a5a..6ecf9ebc 100644 --- a/spec/core/matchers/async/toBeRejectedSpec.js +++ b/spec/core/matchers/async/toBeRejectedSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('toBeRejected', function() { it('passes if the actual is rejected', function() { jasmine.getEnv().requirePromises(); diff --git a/spec/core/matchers/async/toBeRejectedWithErrorSpec.js b/spec/core/matchers/async/toBeRejectedWithErrorSpec.js index 71c53d55..d09a05fd 100644 --- a/spec/core/matchers/async/toBeRejectedWithErrorSpec.js +++ b/spec/core/matchers/async/toBeRejectedWithErrorSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('#toBeRejectedWithError', function () { it('passes when Error type matches', function () { jasmine.getEnv().requirePromises(); diff --git a/spec/core/matchers/async/toBeRejectedWithSpec.js b/spec/core/matchers/async/toBeRejectedWithSpec.js index 2c02a03a..69003c59 100644 --- a/spec/core/matchers/async/toBeRejectedWithSpec.js +++ b/spec/core/matchers/async/toBeRejectedWithSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('#toBeRejectedWith', function () { it('should return true if the promise is rejected with the expected value', function () { jasmine.getEnv().requirePromises(); diff --git a/spec/core/matchers/async/toBeResolvedSpec.js b/spec/core/matchers/async/toBeResolvedSpec.js index a6ab25ba..8dbff1c9 100644 --- a/spec/core/matchers/async/toBeResolvedSpec.js +++ b/spec/core/matchers/async/toBeResolvedSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('toBeResolved', function() { it('passes if the actual is resolved', function() { jasmine.getEnv().requirePromises(); diff --git a/spec/core/matchers/async/toBeResolvedToSpec.js b/spec/core/matchers/async/toBeResolvedToSpec.js index b721c89e..ee57abe1 100644 --- a/spec/core/matchers/async/toBeResolvedToSpec.js +++ b/spec/core/matchers/async/toBeResolvedToSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('#toBeResolvedTo', function() { it('passes if the promise is resolved to the expected value', function() { jasmine.getEnv().requirePromises(); diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index 10bd0ec0..e3ee9e8c 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -282,8 +282,8 @@ describe("matchersUtil", function() { it("passes for equivalent Promises (GitHub issue #1314)", function() { if (typeof Promise === 'undefined') { return; } - var p1 = new Promise(function () {}), - p2 = new Promise(function () {}), + var p1 = new Promise(function () {}), // eslint-disable-line compat/compat + p2 = new Promise(function () {}), // eslint-disable-line compat/compat matchersUtil = new jasmineUnderTest.MatchersUtil(); expect(matchersUtil.equals(p1, p1)).toBe(true); @@ -418,10 +418,10 @@ describe("matchersUtil", function() { jasmine.getEnv().requireFunctioningMaps(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var obj = new Map(); + var obj = new Map(); // eslint-disable-line compat/compat obj.set(1, 2); obj.set('foo', 'bar'); - var containing = new jasmineUnderTest.MapContaining(new Map()); + var containing = new jasmineUnderTest.MapContaining(new Map()); // eslint-disable-line compat/compat containing.sample.set('foo', 'bar'); expect(matchersUtil.equals(obj, containing)).toBe(true); @@ -432,10 +432,10 @@ describe("matchersUtil", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var obj = new Set(); + var obj = new Set(); // eslint-disable-line compat/compat obj.add(1); obj.add('foo'); - var containing = new jasmineUnderTest.SetContaining(new Set()); + var containing = new jasmineUnderTest.SetContaining(new Set()); // eslint-disable-line compat/compat containing.sample.add(1); expect(matchersUtil.equals(obj, containing)).toBe(true); @@ -603,17 +603,17 @@ describe("matchersUtil", function() { it("passes when comparing two empty sets", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - expect(matchersUtil.equals(new Set(), new Set())).toBe(true); + expect(matchersUtil.equals(new Set(), new Set())).toBe(true); // eslint-disable-line compat/compat }); it("passes when comparing identical sets", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var setA = new Set(); + var setA = new Set(); // eslint-disable-line compat/compat setA.add(6); setA.add(5); - var setB = new Set(); + var setB = new Set(); // eslint-disable-line compat/compat setB.add(6); setB.add(5); @@ -624,10 +624,10 @@ describe("matchersUtil", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var setA = new Set(); + var setA = new Set(); // eslint-disable-line compat/compat setA.add(3); setA.add(6); - var setB = new Set(); + var setB = new Set(); // eslint-disable-line compat/compat setB.add(6); setB.add(3); @@ -638,24 +638,23 @@ describe("matchersUtil", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var setA1 = new Set(); + var setA1 = new Set(); // eslint-disable-line compat/compat setA1.add(['a',3]); setA1.add([6,1]); - var setA2 = new Set(); + var setA2 = new Set(); // eslint-disable-line compat/compat setA1.add(['y',3]); setA1.add([6,1]); - var setA = new Set(); + var setA = new Set(); // eslint-disable-line compat/compat setA.add(setA1); setA.add(setA2); - - var setB1 = new Set(); + var setB1 = new Set(); // eslint-disable-line compat/compat setB1.add([6,1]); setB1.add(['a',3]); - var setB2 = new Set(); + var setB2 = new Set(); // eslint-disable-line compat/compat setB1.add([6,1]); setB1.add(['y',3]); - var setB = new Set(); + var setB = new Set(); // eslint-disable-line compat/compat setB.add(setB1); setB.add(setB2); @@ -666,10 +665,10 @@ describe("matchersUtil", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var setA = new Set(); + var setA = new Set(); // eslint-disable-line compat/compat setA.add([[1,2], [3,4]]); setA.add([[5,6], [7,8]]); - var setB = new Set(); + var setB = new Set(); // eslint-disable-line compat/compat setB.add([[5,6], [7,8]]); setB.add([[1,2], [3,4]]); @@ -679,11 +678,11 @@ describe("matchersUtil", function() { it("fails for sets with different elements", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var setA = new Set(); + var setA = new Set(); // eslint-disable-line compat/compat setA.add(6); setA.add(3); setA.add(5); - var setB = new Set(); + var setB = new Set(); // eslint-disable-line compat/compat setB.add(6); setB.add(4); setB.add(5); @@ -694,10 +693,10 @@ describe("matchersUtil", function() { it("fails for sets of different size", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var setA = new Set(); + var setA = new Set(); // eslint-disable-line compat/compat setA.add(6); setA.add(3); - var setB = new Set(); + var setB = new Set(); // eslint-disable-line compat/compat setB.add(6); setB.add(4); setB.add(5); @@ -708,15 +707,15 @@ describe("matchersUtil", function() { it("passes when comparing two empty maps", function() { jasmine.getEnv().requireFunctioningMaps(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - expect(matchersUtil.equals(new Map(), new Map())).toBe(true); + expect(matchersUtil.equals(new Map(), new Map())).toBe(true); // eslint-disable-line compat/compat }); it("passes when comparing identical maps", function() { jasmine.getEnv().requireFunctioningMaps(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var mapA = new Map(); + var mapA = new Map(); // eslint-disable-line compat/compat mapA.set(6, 5); - var mapB = new Map(); + var mapB = new Map(); // eslint-disable-line compat/compat mapB.set(6, 5); expect(matchersUtil.equals(mapA, mapB)).toBe(true); }); @@ -724,10 +723,10 @@ describe("matchersUtil", function() { it("passes when comparing identical maps with different insertion order", function() { jasmine.getEnv().requireFunctioningMaps(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var mapA = new Map(); + var mapA = new Map(); // eslint-disable-line compat/compat mapA.set("a", 3); mapA.set(6, 1); - var mapB = new Map(); + var mapB = new Map(); // eslint-disable-line compat/compat mapB.set(6, 1); mapB.set("a", 3); expect(matchersUtil.equals(mapA, mapB)).toBe(true); @@ -736,10 +735,10 @@ describe("matchersUtil", function() { it("fails for maps with different elements", function() { jasmine.getEnv().requireFunctioningMaps(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var mapA = new Map(); + var mapA = new Map(); // eslint-disable-line compat/compat mapA.set(6, 3); mapA.set(5, 1); - var mapB = new Map(); + var mapB = new Map(); // eslint-disable-line compat/compat mapB.set(6, 4); mapB.set(5, 1); @@ -749,9 +748,9 @@ describe("matchersUtil", function() { it("fails for maps of different size", function() { jasmine.getEnv().requireFunctioningMaps(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var mapA = new Map(); + var mapA = new Map(); // eslint-disable-line compat/compat mapA.set(6, 3); - var mapB = new Map(); + var mapB = new Map(); // eslint-disable-line compat/compat mapB.set(6, 4); mapB.set(5, 1); expect(matchersUtil.equals(mapA, mapB)).toBe(false); @@ -937,7 +936,7 @@ describe("matchersUtil", function() { var matchersUtil = new jasmineUnderTest.MatchersUtil(); var setItem = {'foo': 'bar'}; - var set = new Set(); + var set = new Set(); // eslint-disable-line compat/compat set.add(setItem); expect(matchersUtil.contains(set, setItem)).toBe(true); @@ -948,7 +947,7 @@ describe("matchersUtil", function() { jasmine.getEnv().requireFunctioningSets(); var matchersUtil = new jasmineUnderTest.MatchersUtil(); - var set = new Set(); + var set = new Set(); // eslint-disable-line compat/compat set.add({'foo': 'bar'}); expect(matchersUtil.contains(set, {'foo': 'bar'})).toBe(false); diff --git a/spec/core/matchers/toEqualSpec.js b/spec/core/matchers/toEqualSpec.js index 3a249364..081329d9 100644 --- a/spec/core/matchers/toEqualSpec.js +++ b/spec/core/matchers/toEqualSpec.js @@ -261,8 +261,8 @@ describe("toEqual", function() { it("reports mismatches between arrays of different types", function() { jasmine.getEnv().requireFunctioningTypedArrays(); - var actual = new Uint32Array([1, 2, 3]), - expected = new Uint16Array([1, 2, 3]), + var actual = new Uint32Array([1, 2, 3]), // eslint-disable-line compat/compat + expected = new Uint16Array([1, 2, 3]), // eslint-disable-line compat/compat message = "Expected Uint32Array [ 1, 2, 3 ] to equal Uint16Array [ 1, 2, 3 ]."; expect(compareEquals(actual, expected).message).toEqual(message); @@ -448,9 +448,9 @@ describe("toEqual", function() { it("reports mismatches between Sets", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = new Set(); + var actual = new Set(); // eslint-disable-line compat/compat actual.add(1); - var expected = new Set(); + var expected = new Set(); // eslint-disable-line compat/compat expected.add(2); var message = 'Expected Set( 1 ) to equal Set( 2 ).'; @@ -460,9 +460,9 @@ describe("toEqual", function() { it("reports deep mismatches within Sets", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = new Set(); + var actual = new Set(); // eslint-disable-line compat/compat actual.add({x: 1}); - var expected = new Set(); + var expected = new Set(); // eslint-disable-line compat/compat expected.add({x: 2}); var message = 'Expected Set( Object({ x: 1 }) ) to equal Set( Object({ x: 2 }) ).'; @@ -472,9 +472,9 @@ describe("toEqual", function() { it("reports mismatches between Sets nested in objects", function() { jasmine.getEnv().requireFunctioningSets(); - var actualSet = new Set(); + var actualSet = new Set(); // eslint-disable-line compat/compat actualSet.add(1); - var expectedSet = new Set(); + var expectedSet = new Set(); // eslint-disable-line compat/compat expectedSet.add(2); var actual = { sets: [actualSet] }; @@ -487,10 +487,10 @@ describe("toEqual", function() { it("reports mismatches between Sets of different lengths", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = new Set(); + var actual = new Set(); // eslint-disable-line compat/compat actual.add(1); actual.add(2); - var expected = new Set(); + var expected = new Set(); // eslint-disable-line compat/compat expected.add(2); var message = 'Expected Set( 1, 2 ) to equal Set( 2 ).'; @@ -501,10 +501,10 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningSets(); // Use 'duplicate' object in actual so sizes match - var actual = new Set(); + var actual = new Set(); // eslint-disable-line compat/compat actual.add({x: 1}); actual.add({x: 1}); - var expected = new Set(); + var expected = new Set(); // eslint-disable-line compat/compat expected.add({x: 1}); expected.add({x: 2}); var message = 'Expected Set( Object({ x: 1 }), Object({ x: 1 }) ) to equal Set( Object({ x: 1 }), Object({ x: 2 }) ).'; @@ -516,10 +516,10 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningSets(); // Use 'duplicate' object in expected so sizes match - var actual = new Set(); + var actual = new Set(); // eslint-disable-line compat/compat actual.add({x: 1}); actual.add({x: 2}); - var expected = new Set(); + var expected = new Set(); // eslint-disable-line compat/compat expected.add({x: 1}); expected.add({x: 1}); var message = 'Expected Set( Object({ x: 1 }), Object({ x: 2 }) ) to equal Set( Object({ x: 1 }), Object({ x: 1 }) ).'; @@ -533,9 +533,9 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningMaps(); // values are the same but with different object identity - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set('a',{x:1}); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set('a',{x:1}); expect(compareEquals(actual, expected).pass).toBe(true); @@ -544,9 +544,9 @@ describe("toEqual", function() { it("reports deep mismatches within Maps", function() { jasmine.getEnv().requireFunctioningMaps(); - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set('a',{x:1}); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set('a',{x:2}); var message = "Expected Map( [ 'a', Object({ x: 1 }) ] ) to equal Map( [ 'a', Object({ x: 2 }) ] )."; @@ -556,9 +556,9 @@ describe("toEqual", function() { it("reports mismatches between Maps nested in objects", function() { jasmine.getEnv().requireFunctioningMaps(); - var actual = {Maps:[new Map()]}; + var actual = {Maps:[new Map()]}; // eslint-disable-line compat/compat actual.Maps[0].set('a',1); - var expected = {Maps:[new Map()]}; + var expected = {Maps:[new Map()]}; // eslint-disable-line compat/compat expected.Maps[0].set('a',2); var message = "Expected $.Maps[0] = Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ] )."; @@ -569,9 +569,9 @@ describe("toEqual", function() { it("reports mismatches between Maps of different lengths", function() { jasmine.getEnv().requireFunctioningMaps(); - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set('a',1); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set('a',2); expected.set('b',1); var message = "Expected Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ], [ 'b', 1 ] )."; @@ -582,9 +582,9 @@ describe("toEqual", function() { it("reports mismatches between Maps with equal values but differing keys", function() { jasmine.getEnv().requireFunctioningMaps(); - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set('a',1); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set('b',1); var message = "Expected Map( [ 'a', 1 ] ) to equal Map( [ 'b', 1 ] )."; @@ -594,9 +594,9 @@ describe("toEqual", function() { it("does not report mismatches between Maps with keys with same object identity", function() { jasmine.getEnv().requireFunctioningMaps(); var key = {x: 1}; - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set(key,2); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set(key,2); expect(compareEquals(actual, expected).pass).toBe(true); @@ -605,9 +605,9 @@ describe("toEqual", function() { it("reports mismatches between Maps with identical keys with different object identity", function() { jasmine.getEnv().requireFunctioningMaps(); - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set({x:1},2); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set({x:1},2); var message = "Expected Map( [ Object({ x: 1 }), 2 ] ) to equal Map( [ Object({ x: 1 }), 2 ] )."; @@ -617,9 +617,9 @@ describe("toEqual", function() { it("does not report mismatches when comparing Map key to jasmine.anything()", function() { jasmine.getEnv().requireFunctioningMaps(); - var actual = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat actual.set('a',1); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set(jasmineUnderTest.anything(),1); expect(compareEquals(actual, expected).pass).toBe(true); @@ -629,10 +629,10 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningMaps(); jasmine.getEnv().requireFunctioningSymbols(); - var key = Symbol(); - var actual = new Map(); + var key = Symbol(); // eslint-disable-line compat/compat + var actual = new Map(); // eslint-disable-line compat/compat actual.set(key,1); - var expected = new Map(); + var expected = new Map(); // eslint-disable-line compat/compat expected.set(key,1); expect(compareEquals(actual, expected).pass).toBe(true); @@ -642,10 +642,10 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningMaps(); jasmine.getEnv().requireFunctioningSymbols(); - var actual = new Map(); - actual.set(Symbol(),1); - var expected = new Map(); - expected.set(Symbol(),1); + var actual = new Map(); // eslint-disable-line compat/compat + actual.set(Symbol(),1); // eslint-disable-line compat/compat + var expected = new Map(); // eslint-disable-line compat/compat + expected.set(Symbol(),1); // eslint-disable-line compat/compat var message = "Expected Map( [ Symbol(), 1 ] ) to equal Map( [ Symbol(), 1 ] )."; expect(compareEquals(actual, expected).message).toBe(message); @@ -655,9 +655,9 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningMaps(); jasmine.getEnv().requireFunctioningSymbols(); - var actual = new Map(); - actual.set(Symbol(),1); - var expected = new Map(); + var actual = new Map(); // eslint-disable-line compat/compat + actual.set(Symbol(),1); // eslint-disable-line compat/compat + var expected = new Map(); // eslint-disable-line compat/compat expected.set(jasmineUnderTest.anything(),1); expect(compareEquals(actual, expected).pass).toBe(true); diff --git a/spec/core/matchers/toHaveSizeSpec.js b/spec/core/matchers/toHaveSizeSpec.js index a14a24e5..d25e39e7 100644 --- a/spec/core/matchers/toHaveSizeSpec.js +++ b/spec/core/matchers/toHaveSizeSpec.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ describe('toHaveSize', function() { 'use strict'; diff --git a/spec/helpers/checkForMap.js b/spec/helpers/checkForMap.js index 77fa1233..b8bdacd3 100644 --- a/spec/helpers/checkForMap.js +++ b/spec/helpers/checkForMap.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ (function(env) { env.hasFunctioningMaps = function() { if (typeof Map === 'undefined') { diff --git a/spec/helpers/checkForSet.js b/spec/helpers/checkForSet.js index 8656342d..cae95db7 100644 --- a/spec/helpers/checkForSet.js +++ b/spec/helpers/checkForSet.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ (function(env) { env.hasFunctioningSets = function() { if (typeof Set === 'undefined') { diff --git a/spec/helpers/checkForSymbol.js b/spec/helpers/checkForSymbol.js index c1ed5415..8b5e4b1e 100644 --- a/spec/helpers/checkForSymbol.js +++ b/spec/helpers/checkForSymbol.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ (function(env) { function hasFunctioningSymbols() { if (typeof Symbol === 'undefined') { diff --git a/spec/helpers/checkForTypedArrays.js b/spec/helpers/checkForTypedArrays.js index 3b5d6b35..6902120b 100644 --- a/spec/helpers/checkForTypedArrays.js +++ b/spec/helpers/checkForTypedArrays.js @@ -1,3 +1,4 @@ +/* eslint-disable compat/compat */ (function(env) { function hasFunctioningTypedArrays() { if (typeof Uint32Array === 'undefined') { diff --git a/src/core/asymmetricEqualityTesterArgCompatShim.js b/src/core/asymmetricEqualityTesterArgCompatShim.js index faa4bf79..162d9651 100644 --- a/src/core/asymmetricEqualityTesterArgCompatShim.js +++ b/src/core/asymmetricEqualityTesterArgCompatShim.js @@ -91,7 +91,7 @@ getJasmineRequireObj().asymmetricEqualityTesterArgCompatShim = function(j$) { }); } - props = Object.getOwnPropertyDescriptors(Array.prototype); + props = Object.getOwnPropertyDescriptors(Array.prototype); // eslint-disable-line compat/compat a = []; for (k in props) { diff --git a/src/core/matchers/async/toBePending.js b/src/core/matchers/async/toBePending.js index 7ea12df9..758eb99e 100644 --- a/src/core/matchers/async/toBePending.js +++ b/src/core/matchers/async/toBePending.js @@ -1,10 +1,11 @@ +/* eslint-disable compat/compat */ getJasmineRequireObj().toBePending = function(j$) { /** * Expect a promise to be pending, ie. the promise is neither resolved nor rejected. * @function * @async * @name async-matchers#toBePending - * @since 3.5.1 (should this be the next version or the version when it was added?) + * @since 3.6 * @example * await expectAsync(aPromise).toBePending(); */ diff --git a/src/core/matchers/toHaveSize.js b/src/core/matchers/toHaveSize.js index 4f6ace0c..680e5144 100644 --- a/src/core/matchers/toHaveSize.js +++ b/src/core/matchers/toHaveSize.js @@ -33,7 +33,7 @@ getJasmineRequireObj().toHaveSize = function(j$) { }; } - var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; // eslint-disable-line compat/compat function isLength(value) { return (typeof value == 'number') && value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER; } From db6aa8f3f83838c327751d074dda5352e5bccc9d Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 2 Jul 2020 08:49:23 -0700 Subject: [PATCH 36/57] Use a version of eslint that works on Node 8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a7d89f70..74dd08c1 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "devDependencies": { "acorn": "^6.0.0", "ejs": "^2.5.5", - "eslint": "7.3.1", + "eslint": "^6.8.0", "eslint-plugin-compat": "^3.8.0", "express": "^4.16.4", "fast-check": "^1.21.0", From f8ae3eaeaaa7d9224b3f52a85270ffe761fec715 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 8 Jul 2020 16:53:53 -0700 Subject: [PATCH 37/57] Built distribution --- lib/jasmine-core/jasmine.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index f618cced..26125ea1 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2831,7 +2831,7 @@ getJasmineRequireObj().asymmetricEqualityTesterArgCompatShim = function(j$) { }); } - props = Object.getOwnPropertyDescriptors(Array.prototype); + props = Object.getOwnPropertyDescriptors(Array.prototype); // eslint-disable-line compat/compat a = []; for (k in props) { @@ -4114,13 +4114,14 @@ getJasmineRequireObj().GlobalErrors = function(j$) { return GlobalErrors; }; +/* eslint-disable compat/compat */ getJasmineRequireObj().toBePending = function(j$) { /** * Expect a promise to be pending, ie. the promise is neither resolved nor rejected. * @function * @async * @name async-matchers#toBePending - * @since 3.5.1 (should this be the next version or the version when it was added?) + * @since 3.6 * @example * await expectAsync(aPromise).toBePending(); */ @@ -4471,7 +4472,7 @@ getJasmineRequireObj().DiffBuilder = function (j$) { }; function dereferencePath(objectPath, actual, expected, pp) { - var i, asymmetricResult + var i, asymmetricResult; for (i = 0; i < objectPath.components.length; i++) { actual = actual[objectPath.components[i]]; @@ -6055,7 +6056,7 @@ getJasmineRequireObj().toHaveSize = function(j$) { }; } - var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; // eslint-disable-line compat/compat function isLength(value) { return (typeof value == 'number') && value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER; } From aa6cc31057ccbef9c2d6fe38c114b90e057dd1e6 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 8 Jul 2020 17:02:11 -0700 Subject: [PATCH 38/57] Show diffs involving root-level asymmetric equality testers * Fixes #1831 --- lib/jasmine-core/jasmine.js | 16 ++++--- .../ObjectContainingSpec.js | 2 +- spec/core/matchers/DiffBuilderSpec.js | 46 +++++++++++++++++++ spec/core/matchers/toEqualSpec.js | 27 ++++++++--- src/core/matchers/DiffBuilder.js | 16 ++++--- 5 files changed, 87 insertions(+), 20 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 26125ea1..edab42b4 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -4472,12 +4472,7 @@ getJasmineRequireObj().DiffBuilder = function (j$) { }; function dereferencePath(objectPath, actual, expected, pp) { - var i, asymmetricResult; - - for (i = 0; i < objectPath.components.length; i++) { - actual = actual[objectPath.components[i]]; - expected = expected[objectPath.components[i]]; - + function handleAsymmetricExpected() { if (j$.isAsymmetricEqualityTester_(expected) && j$.isFunction_(expected.valuesForDiff_)) { var asymmetricResult = expected.valuesForDiff_(actual, pp); expected = asymmetricResult.self; @@ -4485,6 +4480,15 @@ getJasmineRequireObj().DiffBuilder = function (j$) { } } + var i; + handleAsymmetricExpected(); + + for (i = 0; i < objectPath.components.length; i++) { + actual = actual[objectPath.components[i]]; + expected = expected[objectPath.components[i]]; + handleAsymmetricExpected(); + } + return {actual: actual, expected: expected}; } diff --git a/spec/core/asymmetric_equality/ObjectContainingSpec.js b/spec/core/asymmetric_equality/ObjectContainingSpec.js index 8cad948d..97df2555 100644 --- a/spec/core/asymmetric_equality/ObjectContainingSpec.js +++ b/spec/core/asymmetric_equality/ObjectContainingSpec.js @@ -149,7 +149,7 @@ describe("ObjectContaining", function() { }); }); - it("includes keys that are present in only sample", function() { + it("includes keys that are present only in sample", function() { var sample = {a: 1, b: 2}, other = {a: 3}, containing = new jasmineUnderTest.ObjectContaining(sample), diff --git a/spec/core/matchers/DiffBuilderSpec.js b/spec/core/matchers/DiffBuilderSpec.js index 6d82c3f8..01220ce0 100644 --- a/spec/core/matchers/DiffBuilderSpec.js +++ b/spec/core/matchers/DiffBuilderSpec.js @@ -133,4 +133,50 @@ describe("DiffBuilder", function () { expect(diffBuilder.getMessage()).toEqual(expectedMsg); }); + + it('builds diffs involving asymmetric equality testers that implement valuesForDiff_ at the root', function() { + var prettyPrinter = jasmineUnderTest.makePrettyPrinter([]), + diffBuilder = new jasmineUnderTest.DiffBuilder({prettyPrinter: prettyPrinter}), + expectedMsg = 'Expected $.foo = 1 to equal 2.\n' + + "Expected $.baz = undefined to equal 3."; + + + diffBuilder.setRoots( + {foo: 1, bar: 2}, + jasmine.objectContaining({foo: 2, baz: 3}) + ); + + diffBuilder.withPath('foo', function() { + diffBuilder.recordMismatch(); + }); + diffBuilder.withPath('baz', function() { + diffBuilder.recordMismatch(); + }); + + expect(diffBuilder.getMessage()).toEqual(expectedMsg); + }); + + it('builds diffs involving asymmetric equality testers that implement valuesForDiff_ below the root', function() { + var prettyPrinter = jasmineUnderTest.makePrettyPrinter([]), + diffBuilder = new jasmineUnderTest.DiffBuilder({prettyPrinter: prettyPrinter}), + expectedMsg = 'Expected $.x.foo = 1 to equal 2.\n' + + "Expected $.x.baz = undefined to equal 3."; + + + diffBuilder.setRoots( + {x: {foo: 1, bar: 2}}, + {x: jasmine.objectContaining({foo: 2, baz: 3})} + ); + + diffBuilder.withPath('x', function() { + diffBuilder.withPath('foo', function () { + diffBuilder.recordMismatch(); + }); + diffBuilder.withPath('baz', function () { + diffBuilder.recordMismatch(); + }); + }); + + expect(diffBuilder.getMessage()).toEqual(expectedMsg); + }); }); diff --git a/spec/core/matchers/toEqualSpec.js b/spec/core/matchers/toEqualSpec.js index 081329d9..db7f3ffb 100644 --- a/spec/core/matchers/toEqualSpec.js +++ b/spec/core/matchers/toEqualSpec.js @@ -429,17 +429,30 @@ describe("toEqual", function() { expect(compareEquals(actual, expected).message).toEqual(message); }); - it("reports mismatches involving objectContaining and an object", function() { - var actual = {x: {a: 1, b: 4, c: 3, extra: 'ignored'}}; - var expected = {x: jasmineUnderTest.objectContaining({a: 1, b: 2, c: 3})}; - expect(compareEquals(actual, expected).message).toEqual('Expected $.x.b = 4 to equal 2.'); + it('reports mismatches between an object and objectContaining', function() { + var actual = {a: 1, b: 4, c: 3, extra: 'ignored'}; + var expected = jasmineUnderTest.objectContaining({a: 1, b: 2, c: 3, d: 4}); + expect(compareEquals(actual, expected).message) + .toEqual( + 'Expected $.b = 4 to equal 2.\n' + + 'Expected $.d = undefined to equal 4.' + ); }); it("reports mismatches between a non-object and objectContaining", function() { - var actual = {x: 1}; - var expected = {x: jasmineUnderTest.objectContaining({a: 1})}; + var actual = 1; + var expected = jasmineUnderTest.objectContaining({a: 1}); expect(compareEquals(actual, expected).message).toEqual( - "Expected $.x = 1 to equal ''." + "Expected 1 to equal ''." + ); + }); + + it("reports mismatches involving a nested objectContaining", function() { + var actual = {x: {a: 1, b: 4, c: 3, extra: 'ignored'}}; + var expected = {x: jasmineUnderTest.objectContaining({a: 1, b: 2, c: 3, d: 4})}; + expect(compareEquals(actual, expected).message).toEqual( + 'Expected $.x.b = 4 to equal 2.\n' + + 'Expected $.x.d = undefined to equal 4.' ); }); diff --git a/src/core/matchers/DiffBuilder.js b/src/core/matchers/DiffBuilder.js index 83333d8a..70b52ea7 100644 --- a/src/core/matchers/DiffBuilder.js +++ b/src/core/matchers/DiffBuilder.js @@ -72,12 +72,7 @@ getJasmineRequireObj().DiffBuilder = function (j$) { }; function dereferencePath(objectPath, actual, expected, pp) { - var i, asymmetricResult; - - for (i = 0; i < objectPath.components.length; i++) { - actual = actual[objectPath.components[i]]; - expected = expected[objectPath.components[i]]; - + function handleAsymmetricExpected() { if (j$.isAsymmetricEqualityTester_(expected) && j$.isFunction_(expected.valuesForDiff_)) { var asymmetricResult = expected.valuesForDiff_(actual, pp); expected = asymmetricResult.self; @@ -85,6 +80,15 @@ getJasmineRequireObj().DiffBuilder = function (j$) { } } + var i; + handleAsymmetricExpected(); + + for (i = 0; i < objectPath.components.length; i++) { + actual = actual[objectPath.components[i]]; + expected = expected[objectPath.components[i]]; + handleAsymmetricExpected(); + } + return {actual: actual, expected: expected}; } From 226d3ba939217570d5d5e89a7d71982d14e370a9 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 9 Jul 2020 11:25:54 -0700 Subject: [PATCH 39/57] Added IE back to the Travis matrix Now that jasmine-browser works correctly with IE, we can resume testing against it. --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index bfeccecd..3a2cb0db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,14 @@ env: matrix: include: + - env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=11 SAUCE_OS="Windows 8.1" + if: type != pull_request + addons: + sauce_connect: true + - env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=10 SAUCE_OS="Windows 8" + if: type != pull_request + addons: + sauce_connect: true - env: JASMINE_BROWSER="firefox" SAUCE_BROWSER_VERSION='' SAUCE_OS="Windows 10" if: type != pull_request addons: From 70c416d5c9a755a7240e8c902866ece652654642 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Fri, 10 Jul 2020 15:41:02 -0700 Subject: [PATCH 40/57] Fixed jsdocs for recent additions --- lib/jasmine-core/jasmine.js | 14 +++++++------- src/core/Env.js | 4 ++-- src/core/matchers/toHaveSize.js | 2 +- src/core/requireInterface.js | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index edab42b4..dd1b255b 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2077,7 +2077,7 @@ getJasmineRequireObj().Env = function(j$) { }; /** - * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SpecResult} * @name Env#setSpecProperty * @since 3.6.0 * @function @@ -2094,7 +2094,7 @@ getJasmineRequireObj().Env = function(j$) { }; /** - * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SuiteResult} * @name Env#setSuiteProperty * @since 3.6.0 * @function @@ -6030,7 +6030,7 @@ getJasmineRequireObj().toHaveSize = function(j$) { * {@link expect} the actual size to be equal to the expected, using array-like length or object keys size. * @function * @name matchers#toHaveSize - * @since 3.5.1 + * @since 3.6.0 * @param {Object} expected - Expected size * @example * array = [1,2]; @@ -7370,8 +7370,8 @@ getJasmineRequireObj().interface = function(jasmine, env) { }, /** - * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} - * @name Env#setSpecProperty + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SpecResult} + * @name setSpecProperty * @since 3.6.0 * @function * @param {String} key The name of the property @@ -7382,8 +7382,8 @@ getJasmineRequireObj().interface = function(jasmine, env) { }, /** - * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} - * @name Env#setSuiteProperty + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SuiteResult} + * @name setSuiteProperty * @since 3.6.0 * @function * @param {String} key The name of the property diff --git a/src/core/Env.js b/src/core/Env.js index 60025850..d7fdd4c0 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -1125,7 +1125,7 @@ getJasmineRequireObj().Env = function(j$) { }; /** - * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SpecResult} * @name Env#setSpecProperty * @since 3.6.0 * @function @@ -1142,7 +1142,7 @@ getJasmineRequireObj().Env = function(j$) { }; /** - * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SuiteResult} * @name Env#setSuiteProperty * @since 3.6.0 * @function diff --git a/src/core/matchers/toHaveSize.js b/src/core/matchers/toHaveSize.js index 680e5144..03c8d431 100644 --- a/src/core/matchers/toHaveSize.js +++ b/src/core/matchers/toHaveSize.js @@ -3,7 +3,7 @@ getJasmineRequireObj().toHaveSize = function(j$) { * {@link expect} the actual size to be equal to the expected, using array-like length or object keys size. * @function * @name matchers#toHaveSize - * @since 3.5.1 + * @since 3.6.0 * @param {Object} expected - Expected size * @example * array = [1,2]; diff --git a/src/core/requireInterface.js b/src/core/requireInterface.js index adc503f8..a468d880 100644 --- a/src/core/requireInterface.js +++ b/src/core/requireInterface.js @@ -169,8 +169,8 @@ getJasmineRequireObj().interface = function(jasmine, env) { }, /** - * Sets a user-defined property that will be provided to reporters as part of {@link SpecResult#properties} - * @name Env#setSpecProperty + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SpecResult} + * @name setSpecProperty * @since 3.6.0 * @function * @param {String} key The name of the property @@ -181,8 +181,8 @@ getJasmineRequireObj().interface = function(jasmine, env) { }, /** - * Sets a user-defined property that will be provided to reporters as part of {@link SuiteResult#properties} - * @name Env#setSuiteProperty + * Sets a user-defined property that will be provided to reporters as part of the properties field of {@link SuiteResult} + * @name setSuiteProperty * @since 3.6.0 * @function * @param {String} key The name of the property From 6f3e85f755554c4b52b2449a6d2d66bb1327ac4e Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 16 Jul 2020 12:42:05 -0700 Subject: [PATCH 41/57] Only run long property tests once on CI --- .travis.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a2cb0db..dadd8965 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,5 @@ language: node_js -node_js: - - "10" - - "8" - - "12" +node_js: 10 script: $TEST_COMMAND @@ -10,15 +7,17 @@ env: global: - USE_SAUCE=true - TEST_COMMAND="bash travis-core-script.sh" - - JASMINE_LONG_PROPERTY_TESTS="y" - secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo= - secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g= - matrix: - - TEST_COMMAND="npm test" - matrix: include: + - node_js: "10" + env: JASMINE_LONG_PROPERTY_TESTS="y" TEST_COMMAND="npm test" + - node_js: "12" + env: TEST_COMMAND="npm test" + - node_js: "8" + env: TEST_COMMAND="npm test" - env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=11 SAUCE_OS="Windows 8.1" if: type != pull_request addons: From d51da1880870ed07b2c898a261e96524e99ecc49 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 23 Jul 2020 16:02:30 -0700 Subject: [PATCH 42/57] Bump version to 3.6.0 --- lib/jasmine-core/jasmine.js | 2 +- lib/jasmine-core/version.rb | 2 +- package.json | 2 +- release_notes/3.6.0.md | 146 ++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 release_notes/3.6.0.md diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index dd1b255b..a68f1b20 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -8961,5 +8961,5 @@ getJasmineRequireObj().UserContext = function(j$) { }; getJasmineRequireObj().version = function() { - return '3.5.1'; + return '3.6.0'; }; diff --git a/lib/jasmine-core/version.rb b/lib/jasmine-core/version.rb index b757b251..5dd3e13b 100644 --- a/lib/jasmine-core/version.rb +++ b/lib/jasmine-core/version.rb @@ -4,6 +4,6 @@ # module Jasmine module Core - VERSION = "3.5.0" + VERSION = "3.6.0" end end diff --git a/package.json b/package.json index 74dd08c1..7ed0c766 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jasmine-core", "license": "MIT", - "version": "3.5.1", + "version": "3.6.0", "repository": { "type": "git", "url": "https://github.com/jasmine/jasmine.git" diff --git a/release_notes/3.6.0.md b/release_notes/3.6.0.md new file mode 100644 index 00000000..cfa8628d --- /dev/null +++ b/release_notes/3.6.0.md @@ -0,0 +1,146 @@ +# Jasmine Core 3.6 Release Notes + +## Summary + +This is a maintenance release of Jasmine with a number of new features and fixes. + +## Highlights + +* Added support for custom object formatters + * Allows customizing how an object is stringified in matcher failure messages + * [Tutorial](https://jasmine.github.io/tutorials/custom_object_formatter) + * [API reference](https://jasmine.github.io/api/3.6/jasmine.html#.addCustomObjectFormatter) + +* Don't require matchers and asymmetric equality testers to pass custom object formatters back to Jasmine + - Supports custom object formatters. + - Makes it easier to write high quality matchers and asymmetric equality testers. + - The old API will still work until 4.0. + +* Properly import jasmineRequire object before using + - Improves compatibility with Webpack + - Merges [#1766](https://github.com/jasmine/jasmine/pull/1766) from @amilligan + +* Added a toHaveBeenCalledOnceWith matcher + - Merges [#1801](https://github.com/jasmine/jasmine/pull/1801) from @Maximaximum + - Fixes [#1717](https://github.com/jasmine/jasmine/issues/1717) + +* Added a toHaveSize matcher + - Merges [#1796](https://github.com/jasmine/jasmine/pull/1796) from @wokier + +* Added a toBePending async matcher + - Merges [#1808](https://github.com/jasmine/jasmine/pull/1808) from @DCtheTall + - Fixes [#1803](https://github.com/jasmine/jasmine/issues/1803) + +* Added support for user-defined spec/suite properties + - Allows specs/suites to pass data to custom reporters + - Merges [#1763](https://github.com/jasmine/jasmine/pull/1763) from @johnjbarton + +* Route unhandled promise rejections to onerror + - Merges [#1778](https://github.com/jasmine/jasmine/pull/1778) from @johnjbarton + - Fixes [#1777](https://github.com/jasmine/jasmine/issues/1777) + + +## Internal notes + +* Use a version of eslint that works on Node 8 + +* Check for syntax and standard library objects that don't work in IE + +* Run eslint against all files + +* Add Additional Test for equals Matcher + - Merges [#1829](https://github.com/jasmine/jasmine/pull/1829) from @tobiasschweizer + - Fixes [#1821](https://github.com/jasmine/jasmine/issues/1821) + +* Depend on head of jasmine-browser to fix IE failures in CI + +* Fixed test failure in Firefox 74 + +* Added test for resolveTo/rejectWith with empty parameters + - Merges [#1802](https://github.com/jasmine/jasmine/pull/1802) from @chivesrs + +* Removed unnecessary uses of new in tests + +* Realigned the browser testing matrix to match current reality + - Use Windows instead of Linux so we can get current browsers from Sauce. + - Test against the version of Firefox that corresponds to ESR as well as + latest. + - Test the latest Edge rather than a specific older version. + - Test Safari 8 and 13 instead of 8, 9 and 10. What works in those versions + is likely to work in the ones in between. + +* Don't leak global error handlers between Jasmine's own tests + +* Added basic property tests for matchersUtil.equals + +* Added integration tests for existing matcher interfaces + +* Added integration tests for asymmetric equality testers + +* Test IE before other browsers on Travis + + +## Other Changes + +* Show diffs involving root-level asymmetric equality testers + - Fixes [#1831](https://github.com/jasmine/jasmine/issues/1831) + +* Fixed references to master in docs + +* Allow spy throwError to throw an Object + - Merges [#1822](https://github.com/jasmine/jasmine/pull/1822) from @terencehonles + +* Added missing periods to README + - Merges [#1828](https://github.com/jasmine/jasmine/pull/1828) from @dirkpuge + + +* Expose setSpec/SuiteProperty on interface + - Merges [#1820](https://github.com/jasmine/jasmine/pull/1820) from @johnjbarton + +* Prevent undesired reloads when karma-jasmine-html-reporter is used + - Merges [#1807](https://github.com/jasmine/jasmine/pull/1807) from @parloti + - Fixes [#1775](https://github.com/jasmine/jasmine/issues/1775) + +* Correctly report spec and suite duration + - Fixes [#1676](https://github.com/jasmine/jasmine/issues/1676). + +* Added jsdocs for MatchersUtil + +* Allow the .callThrough spy strategy to call constructor functions without errors + - Merges [#1782](https://github.com/jasmine/jasmine/pull/1782) from @enelson + - Fixes [#1760](https://github.com/jasmine/jasmine/issues/1760) + +* Inject a per-runable pretty printer into MatchersUtil + - Supports custom object formatters + +* Include stack traces in unhandled promise rejection messages + +* Describe the naming for the function it + - Merges [#1772](https://github.com/jasmine/jasmine/pull/1772) from @johnlinp + +* Correctly extract error messages from stack traces that don't start with `Error` + - Merges [#1776](https://github.com/jasmine/jasmine/pull/1776) from @vhermannitk + - Fixes [#1771](https://github.com/jasmine/jasmine/issues/1771) + +* Fixed objectContaining to not match when the expected is the empty object and the actual is a non-object + +* Fixed toEqual(0, Number.MIN_VALUE) to fail instead of passing + - Merges [#1764](https://github.com/jasmine/jasmine/pull/1764) from @dubzzz + +* Fixed comparison between ObjectContaining and non-objects on IE + +* Provide better diffs for object graphs that include `objectContaining` + +* Indent multiline failure messages in the output of `withContext` + * This makes it easier to see where each failure message begins and ends. + +* Report async expectations that complete after the runable completes + - See [#1752](https://github.com/jasmine/jasmine/issues/1752). + +* Treat NodeJS assertion failures as expectation failures + - Merges [#1678](https://github.com/jasmine/jasmine/pull/1678) from @apla + + +------ + +_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_ From 0cfeb0b9c39663dadefdce74d18e7ff783a2ed7b Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 23 Jul 2020 16:35:36 -0700 Subject: [PATCH 43/57] Fixed link to custom object formatter tutorial --- lib/jasmine-core/jasmine.js | 2 +- src/core/requireInterface.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index a68f1b20..6fb31080 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -7552,7 +7552,7 @@ getJasmineRequireObj().interface = function(jasmine, env) { * @since 3.6.0 * @function * @param {Function} formatter - A function which takes a value to format and returns a string if it knows how to format it, and `undefined` otherwise. - * @see custom_object_formatter + * @see custom_object_formatters */ jasmine.addCustomObjectFormatter = function(formatter) { return env.addCustomObjectFormatter(formatter); diff --git a/src/core/requireInterface.js b/src/core/requireInterface.js index a468d880..6473ffaa 100644 --- a/src/core/requireInterface.js +++ b/src/core/requireInterface.js @@ -351,7 +351,7 @@ getJasmineRequireObj().interface = function(jasmine, env) { * @since 3.6.0 * @function * @param {Function} formatter - A function which takes a value to format and returns a string if it knows how to format it, and `undefined` otherwise. - * @see custom_object_formatter + * @see custom_object_formatters */ jasmine.addCustomObjectFormatter = function(formatter) { return env.addCustomObjectFormatter(formatter); From c4e65e4a9a004b4df720f24833322007d59f6722 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 23 Jul 2020 16:50:54 -0700 Subject: [PATCH 44/57] wip --- RELEASE.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 61ffbadc..00fda1b0 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -60,8 +60,10 @@ Install [twine](https://github.com/pypa/twine) Probably only need to do this when releasing a minor version, and not a patch version. -1. `cp -R edge ${version}` to copy the current edge docs to the new version -1. Add a link to the new version in `index.html` +1. `rake update_edge_jasmine` +1. `npm run jsdoc` +1. `rake release[${version}]` to copy the current edge docs to the new version +1. Commit and push. ### Finally From 1f68ed836e0c4e2ced39f5daa05dfc5d13d489f3 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 23 Jul 2020 17:26:43 -0700 Subject: [PATCH 45/57] Updated the release docs --- RELEASE.md | 59 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 00fda1b0..b388cf85 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -29,29 +29,32 @@ When jasmine-core revs its major or minor version, the binding libraries should When ready to release - specs are all green and the stories are done: 1. Update the release notes in `release_notes` - use the Anchorman gem to generate the markdown file and edit accordingly -1. Update the version in `package.json` to a release candidate -1. Update any links or top-level landing page for the Github Pages +1. Update the version in `package.json` +1. Copy version to the Ruby gem with `grunt build:copyVersionToGem` + +### Commit and push core changes + +1. Commit release notes and version changes (jasmine.js, version.rb, package.json) +1. Push +1. Wait for Travis to go green ### Build standalone distribution 1. Build the standalone distribution with `grunt buildStandaloneDist` -### Release the Python egg +### Release the core Ruby gem + +1. __NOTE__: You will likely need to push a new jasmine gem with a dependent version right after this release. See below. +1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org. In order to release you will have to ensure you have rubygems creds locally. + +### Release the core Python egg Install [twine](https://github.com/pypa/twine) 1. `python setup.py sdist` 1. `twine upload dist/jasmine-core-.tar.gz` You will need pypi credentials to upload the egg. -### Release the Ruby gem - -1. Copy version to the Ruby gem with `grunt build:copyVersionToGem` -1. __NOTE__: You will likely need to point to a local jasmine gem in order to run tests locally. _Do not_ push this version of the Gemfile. -1. __NOTE__: You will likely need to push a new jasmine gem with a dependent version right after this release. -1. Push these changes to GitHub and verify that this SHA is green -1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org. In order to release you will have to ensure you have rubygems creds locally. - -### Release the NPM +### Release the core NPM module 1. `npm adduser` to save your credentials locally 1. `npm publish .` to publish what's in `package.json` @@ -65,12 +68,30 @@ Probably only need to do this when releasing a minor version, and not a patch ve 1. `rake release[${version}]` to copy the current edge docs to the new version 1. Commit and push. +### Release the binding libraries + +#### NPM + +1. Create release notes using Anchorman as above +1. In `package.json`, update both the package version and the jasmine-core dependency version +1. Commit and push. +1. Wait for Travis to go green again. +1. `grunt release ` +1. `npm publish .` + +#### Gem + +1. Create release notes using Anchorman as above +1. Update the version number in `lib/jasmine/version.rb`. +1. Update the jasmine-core dependency version in `jasmine.gemspec`. +1. Commit and push. +1. Wait for Travis to go green again. +1. `rake release` + ### Finally -1. Visit the [Releases page for Jasmine](https://github.com/jasmine/jasmine/releases), find the tag just pushed. - 1. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes. - 1. If it is a pre-release, mark it as such. - 1. Attach the standalone zipfile - - -There should be a post to Pivotal Labs blog and a tweet to that link. +For each of the above GitHub repos: +1. Visit the releases page and find the tag just published. +1. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes. +1. If it is a pre-release, mark it as such. +1. For core, attach the standalone zipfile. From e5bb89847f09856512f00934319fbdab28b5af46 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Thu, 23 Jul 2020 17:28:38 -0700 Subject: [PATCH 46/57] Use jasmine-browser from npm The current released version now works with IE, so we no longer need to depend on main. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ed0c766..0ef7ddd8 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "grunt-css-url-embed": "^1.11.1", "grunt-sass": "^3.0.2", "jasmine": "^3.4.0", - "jasmine-browser-runner": "github:jasmine/jasmine-browser", + "jasmine-browser-runner": "^0.4.0", "jsdom": "^15.0.0", "load-grunt-tasks": "^4.0.0", "node-sass": "^4.11.0", From dfdcfc5be561b9c929b1318d525853703eef7392 Mon Sep 17 00:00:00 2001 From: snowman Date: Sat, 25 Jul 2020 13:27:00 +0800 Subject: [PATCH 47/57] Update README.md Remove extra "jasmine/" directory in code example --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e8b7fd53..c7189c1d 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,12 @@ To install Jasmine standalone on your local box (where **_{#.#.#}_** below is su Add the following to your HTML file: ```html - - + + - - - + + + ``` ## Supported environments From 6b9739030ddabdfc7aee679d99d4307b5fc9fa3b Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sun, 2 Aug 2020 12:57:28 -0700 Subject: [PATCH 48/57] Fixed future deprecations --- lib/jasmine-core/jasmine.js | 8 ++++---- spec/core/integration/EnvSpec.js | 1 + .../matchers/toHaveBeenCalledOnceWithSpec.js | 19 +++++++++++++------ src/core/matchers/toHaveBeenCalledOnceWith.js | 8 ++++---- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 6fb31080..eb2b160d 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -5829,18 +5829,18 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { expectedArgs = args.slice(1); if (!j$.isSpy(actual)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); + throw new Error(getErrorMsg('Expected a spy, but got ' + util.pp(actual) + '.')); } var prettyPrintedCalls = actual.calls.allArgs().map(function (argsForCall) { - return ' ' + j$.pp(argsForCall); + return ' ' + util.pp(argsForCall); }); if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs)) { return { pass: true, message: 'Expected spy ' + actual.and.identity + ' to have been called 0 times, multiple times, or once, but with arguments different from:\n' - + ' ' + j$.pp(expectedArgs) + '\n' + + ' ' + util.pp(expectedArgs) + '\n' + 'But the actual call was:\n' + prettyPrintedCalls.join(',\n') + '.\n\n' }; @@ -5868,7 +5868,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { return { pass: false, message: 'Expected spy ' + actual.and.identity + ' to have been called only once, and with given args:\n' - + ' ' + j$.pp(expectedArgs) + '\n' + + ' ' + util.pp(expectedArgs) + '\n' + butString() }; } diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 090bb54c..ae7cd0d6 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -1992,6 +1992,7 @@ describe("Env integration", function() { exception; env.describe("a suite", function () { + env.it('a spec'); try { env.setSpecProperty('a prop', 'val'); } catch(e) { diff --git a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js index be0e95bc..d79711a5 100644 --- a/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js +++ b/spec/core/matchers/toHaveBeenCalledOnceWithSpec.js @@ -1,7 +1,8 @@ describe("toHaveBeenCalledOnceWith", function () { it("passes when the actual was called only once and with matching parameters", function () { - var util = jasmineUnderTest.matchersUtil, + var pp = jasmineUnderTest.makePrettyPrinter(), + util = new jasmineUnderTest.MatchersUtil({ pp: pp }), matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), calledSpy = new jasmineUnderTest.Spy('called-spy'), result; @@ -27,7 +28,8 @@ describe("toHaveBeenCalledOnceWith", function () { }); it("fails when the actual was never called", function () { - var util = jasmineUnderTest.matchersUtil, + var pp = jasmineUnderTest.makePrettyPrinter(), + util = new jasmineUnderTest.MatchersUtil({ pp: pp }), matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), calledSpy = new jasmineUnderTest.Spy('called-spy'), result; @@ -39,7 +41,8 @@ describe("toHaveBeenCalledOnceWith", function () { }); it("fails when the actual was called once with different parameters", function () { - var util = jasmineUnderTest.matchersUtil, + var pp = jasmineUnderTest.makePrettyPrinter(), + util = new jasmineUnderTest.MatchersUtil({ pp: pp }), matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), calledSpy = new jasmineUnderTest.Spy('called-spy'), result; @@ -52,7 +55,8 @@ describe("toHaveBeenCalledOnceWith", function () { }); it("fails when the actual was called multiple times with expected parameters", function () { - var util = jasmineUnderTest.matchersUtil, + var pp = jasmineUnderTest.makePrettyPrinter(), + util = new jasmineUnderTest.MatchersUtil({ pp: pp }), matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), calledSpy = new jasmineUnderTest.Spy('called-spy'), result; @@ -66,7 +70,8 @@ describe("toHaveBeenCalledOnceWith", function () { }); it("fails when the actual was called multiple times (one of them - with expected parameters)", function () { - var util = jasmineUnderTest.matchersUtil, + var pp = jasmineUnderTest.makePrettyPrinter(), + util = new jasmineUnderTest.MatchersUtil({ pp: pp }), matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), calledSpy = new jasmineUnderTest.Spy('called-spy'), result; @@ -80,7 +85,9 @@ describe("toHaveBeenCalledOnceWith", function () { }); it("throws an exception when the actual is not a spy", function () { - var matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(), + var pp = jasmineUnderTest.makePrettyPrinter(), + util = new jasmineUnderTest.MatchersUtil({ pp: pp }), + matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util), fn = function () { }; expect(function () { matcher.compare(fn) }).toThrowError(/Expected a spy, but got Function./); diff --git a/src/core/matchers/toHaveBeenCalledOnceWith.js b/src/core/matchers/toHaveBeenCalledOnceWith.js index d7be3782..2cd607f8 100644 --- a/src/core/matchers/toHaveBeenCalledOnceWith.js +++ b/src/core/matchers/toHaveBeenCalledOnceWith.js @@ -19,18 +19,18 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { expectedArgs = args.slice(1); if (!j$.isSpy(actual)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); + throw new Error(getErrorMsg('Expected a spy, but got ' + util.pp(actual) + '.')); } var prettyPrintedCalls = actual.calls.allArgs().map(function (argsForCall) { - return ' ' + j$.pp(argsForCall); + return ' ' + util.pp(argsForCall); }); if (actual.calls.count() === 1 && util.contains(actual.calls.allArgs(), expectedArgs)) { return { pass: true, message: 'Expected spy ' + actual.and.identity + ' to have been called 0 times, multiple times, or once, but with arguments different from:\n' - + ' ' + j$.pp(expectedArgs) + '\n' + + ' ' + util.pp(expectedArgs) + '\n' + 'But the actual call was:\n' + prettyPrintedCalls.join(',\n') + '.\n\n' }; @@ -58,7 +58,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function (j$) { return { pass: false, message: 'Expected spy ' + actual.and.identity + ' to have been called only once, and with given args:\n' - + ' ' + j$.pp(expectedArgs) + '\n' + + ' ' + util.pp(expectedArgs) + '\n' + butString() }; } From 627704621349987c7317fe3c3e25a48ba1cf790d Mon Sep 17 00:00:00 2001 From: Aaron Snailwood Date: Thu, 20 Aug 2020 10:07:35 -0700 Subject: [PATCH 49/57] fix typo in asyncMatcher toBePending comment --- src/core/matchers/async/toBePending.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/matchers/async/toBePending.js b/src/core/matchers/async/toBePending.js index 758eb99e..c73aa3d3 100644 --- a/src/core/matchers/async/toBePending.js +++ b/src/core/matchers/async/toBePending.js @@ -1,7 +1,7 @@ /* eslint-disable compat/compat */ getJasmineRequireObj().toBePending = function(j$) { /** - * Expect a promise to be pending, ie. the promise is neither resolved nor rejected. + * Expect a promise to be pending, i.e. the promise is neither resolved nor rejected. * @function * @async * @name async-matchers#toBePending From 53d8073707d90da6941ed15cb97e3fbf87b77de3 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 29 Aug 2020 13:05:57 -0700 Subject: [PATCH 50/57] Allow generator functions to be passed to `.and.callFake` Fixes #1848. --- lib/jasmine-core/jasmine.js | 12 +++++++++++- spec/core/SpyStrategySpec.js | 11 +++++++++++ spec/helpers/generator.js | 22 ++++++++++++++++++++++ spec/support/jasmine-browser.js | 1 + spec/support/jasmine.json | 1 + src/core/SpyStrategy.js | 8 +++++++- src/core/base.js | 4 ++++ 7 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 spec/helpers/generator.js diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 2a50a3cf..197929cb 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -244,6 +244,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return j$.isA_('AsyncFunction', value); }; + j$.isGeneratorFunction_ = function(value) { + return j$.isA_('GeneratorFunction', value); + }; + j$.isTypedArray_ = function(value) { return ( j$.isA_('Float32Array', value) || @@ -8308,7 +8312,13 @@ getJasmineRequireObj().SpyStrategy = function(j$) { * @param {Function} fn The function to invoke with the passed parameters. */ SpyStrategy.prototype.callFake = function(fn) { - if (!(j$.isFunction_(fn) || j$.isAsyncFunction_(fn))) { + if ( + !( + j$.isFunction_(fn) || + j$.isAsyncFunction_(fn) || + j$.isGeneratorFunction_(fn) + ) + ) { throw new Error( 'Argument passed to callFake should be a function, got ' + fn ); diff --git a/spec/core/SpyStrategySpec.js b/spec/core/SpyStrategySpec.js index 76a3a1e2..85624083 100644 --- a/spec/core/SpyStrategySpec.js +++ b/spec/core/SpyStrategySpec.js @@ -334,6 +334,17 @@ describe('SpyStrategy', function() { }).toThrowError(/^Argument passed to callFake should be a function, got/); }); + it('allows generator functions to be passed to callFake strategy', function() { + jasmine.getEnv().requireGeneratorFunctions(); + + var generator = jasmine.getEnv().makeGeneratorFunction('yield "ok";'), + spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: function() {} }); + + spyStrategy.callFake(generator); + + expect(spyStrategy.exec().next().value).toEqual('ok'); + }); + it('allows a return to plan stubbing after another strategy', function() { var originalFn = jasmine.createSpy('original'), fakeFn = jasmine.createSpy('fake').and.returnValue(67), diff --git a/spec/helpers/generator.js b/spec/helpers/generator.js new file mode 100644 index 00000000..b62f5acd --- /dev/null +++ b/spec/helpers/generator.js @@ -0,0 +1,22 @@ +(function(env) { + function getGeneratorFuncCtor() { + try { + eval('var func = function*() {}'); + } catch (e) { + return null; + } + + return Object.getPrototypeOf(func).constructor; + } + + env.makeGeneratorFunction = function(text) { + var GeneratorFunction = getGeneratorFuncCtor(); + return new GeneratorFunction(text || ''); + }; + + env.requireGeneratorFunctions = function() { + if (!getGeneratorFuncCtor()) { + env.pending('Environment does not support generator functions'); + } + }; +})(jasmine.getEnv()); diff --git a/spec/support/jasmine-browser.js b/spec/support/jasmine-browser.js index 61076dbb..2f5f7146 100644 --- a/spec/support/jasmine-browser.js +++ b/spec/support/jasmine-browser.js @@ -18,6 +18,7 @@ module.exports = { specFiles: ['**/*[Ss]pec.js', '!npmPackage/**/*'], helpers: [ 'helpers/asyncAwait.js', + 'helpers/generator.js', 'helpers/BrowserFlags.js', 'helpers/checkForMap.js', 'helpers/checkForSet.js', diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json index b48efde5..0276ca92 100644 --- a/spec/support/jasmine.json +++ b/spec/support/jasmine.json @@ -6,6 +6,7 @@ ], "helpers": [ "helpers/asyncAwait.js", + "helpers/generator.js", "helpers/checkForMap.js", "helpers/checkForSet.js", "helpers/checkForSymbol.js", diff --git a/src/core/SpyStrategy.js b/src/core/SpyStrategy.js index 41aa9258..382164b6 100644 --- a/src/core/SpyStrategy.js +++ b/src/core/SpyStrategy.js @@ -168,7 +168,13 @@ getJasmineRequireObj().SpyStrategy = function(j$) { * @param {Function} fn The function to invoke with the passed parameters. */ SpyStrategy.prototype.callFake = function(fn) { - if (!(j$.isFunction_(fn) || j$.isAsyncFunction_(fn))) { + if ( + !( + j$.isFunction_(fn) || + j$.isAsyncFunction_(fn) || + j$.isGeneratorFunction_(fn) + ) + ) { throw new Error( 'Argument passed to callFake should be a function, got ' + fn ); diff --git a/src/core/base.js b/src/core/base.js index 121ff614..d02606d5 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -76,6 +76,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return j$.isA_('AsyncFunction', value); }; + j$.isGeneratorFunction_ = function(value) { + return j$.isA_('GeneratorFunction', value); + }; + j$.isTypedArray_ = function(value) { return ( j$.isA_('Float32Array', value) || From 8cb44582bcbbb812a0140ce39212efed740815e3 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Tue, 1 Sep 2020 15:18:53 -0700 Subject: [PATCH 51/57] Don't overwrite MatchersUtil methods with ones that were added to Array.prototype, esp. contains Fixes #1849. --- lib/jasmine-core/jasmine.js | 4 +- ...ymmetricEqualityTesterArgCompatShimSpec.js | 48 +++++++++++++++++-- .../asymmetricEqualityTesterArgCompatShim.js | 4 +- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 197929cb..5a8e11b4 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2810,7 +2810,9 @@ getJasmineRequireObj().asymmetricEqualityTesterArgCompatShim = function(j$) { for (i = 0; i < props.length; i++) { k = props[i]; - if (k !== 'length') { + // Skip length (dealt with above), and anything that collides with + // MatchesUtil e.g. an Array.prototype.contains method added by user code + if (k !== 'length' && !self[k]) { copy(self, Array.prototype, k); } } diff --git a/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js b/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js index c7c4d9b6..7a9a039c 100644 --- a/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js +++ b/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js @@ -36,7 +36,6 @@ describe('asymmetricEqualityTesterArgCompatShim', function() { it('provides properties of Array.prototype', function() { var keys = [ 'concat', - 'constructor', 'every', 'filter', 'forEach', @@ -55,8 +54,6 @@ describe('asymmetricEqualityTesterArgCompatShim', function() { 'some', 'sort', 'splice', - 'toLocaleString', - 'toString', 'unshift' ], optionalKeys = [ @@ -98,4 +95,49 @@ describe('asymmetricEqualityTesterArgCompatShim', function() { } } }); + + describe('When Array.prototype additions collide with MatchersUtil methods', function() { + function keys() { + return [ + 'contains', + 'buildFailureMessage', + 'asymmetricDiff_', + 'asymmetricMatch_', + 'equals', + 'eq_' + ]; + } + + beforeEach(function() { + keys().forEach(function(k) { + if (Array.prototype[k]) { + console.log(Array.prototype[k].toString()); + } + expect(Array.prototype[k]) + .withContext('Array.prototype already had ' + k) + .toBeUndefined(); + Array.prototype[k] = function() {}; + }); + }); + + afterEach(function() { + keys().forEach(function(k) { + delete Array.prototype[k]; + }); + }); + + it('uses the MatchersUtil methods', function() { + var matchersUtil = new jasmineUnderTest.MatchersUtil({}), + shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim( + matchersUtil, + [] + ); + + keys().forEach(function(k) { + expect(shim[k]) + .withContext(k + ' was overwritten') + .toBe(jasmineUnderTest.MatchersUtil.prototype[k]); + }); + }); + }); }); diff --git a/src/core/asymmetricEqualityTesterArgCompatShim.js b/src/core/asymmetricEqualityTesterArgCompatShim.js index 162d9651..e487f3df 100644 --- a/src/core/asymmetricEqualityTesterArgCompatShim.js +++ b/src/core/asymmetricEqualityTesterArgCompatShim.js @@ -66,7 +66,9 @@ getJasmineRequireObj().asymmetricEqualityTesterArgCompatShim = function(j$) { for (i = 0; i < props.length; i++) { k = props[i]; - if (k !== 'length') { + // Skip length (dealt with above), and anything that collides with + // MatchesUtil e.g. an Array.prototype.contains method added by user code + if (k !== 'length' && !self[k]) { copy(self, Array.prototype, k); } } From 5a715aecee30eb7d553703ae194735d629ba0e05 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Tue, 1 Sep 2020 15:25:44 -0700 Subject: [PATCH 52/57] Removed unnecessary console.log --- spec/core/asymmetricEqualityTesterArgCompatShimSpec.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js b/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js index 7a9a039c..34186c12 100644 --- a/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js +++ b/spec/core/asymmetricEqualityTesterArgCompatShimSpec.js @@ -110,9 +110,6 @@ describe('asymmetricEqualityTesterArgCompatShim', function() { beforeEach(function() { keys().forEach(function(k) { - if (Array.prototype[k]) { - console.log(Array.prototype[k].toString()); - } expect(Array.prototype[k]) .withContext('Array.prototype already had ' + k) .toBeUndefined(); From 00feef8632a8b59ee44eb12aa28d9c9810b72c86 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 2 Sep 2020 09:31:35 -0700 Subject: [PATCH 53/57] Fixed global error handler stack corruption in Jasmine's own tests --- lib/jasmine-core/jasmine.js | 12 +- spec/core/EnvSpec.js | 44 +- spec/core/ExceptionsSpec.js | 6 +- .../AsymmetricEqualityTestersSpec.js | 8 +- .../integration/CustomAsyncMatchersSpec.js | 20 +- spec/core/integration/CustomMatchersSpec.js | 40 +- .../integration/CustomObjectFormatterSpec.js | 8 +- .../integration/CustomSpyStrategiesSpec.js | 27 +- .../integration/DefaultSpyStrategySpec.js | 12 +- spec/core/integration/EnvSpec.js | 1387 ++++++++--------- spec/core/integration/MatchersSpec.js | 24 +- spec/core/integration/SpecRunningSpec.js | 218 +-- src/core/Env.js | 9 +- src/core/QueueRunner.js | 3 + 14 files changed, 833 insertions(+), 985 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 5a8e11b4..8b449d97 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1661,7 +1661,8 @@ getJasmineRequireObj().Env = function(j$) { queueRunnerFactory ); - this.execute = function(runnablesToRun) { + // Both params are optional. + this.execute = function(runnablesToRun, onComplete) { installGlobalErrors(); if (!runnablesToRun) { @@ -1769,7 +1770,11 @@ getJasmineRequireObj().Env = function(j$) { failedExpectations: topSuite.result.failedExpectations, deprecationWarnings: topSuite.result.deprecationWarnings }, - function() {} + function() { + if (onComplete) { + onComplete(); + } + } ); }); } @@ -6917,6 +6922,8 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) { }; getJasmineRequireObj().QueueRunner = function(j$) { + var nextid = 1; + function StopExecutionError() {} StopExecutionError.prototype = new Error(); j$.StopExecutionError = StopExecutionError; @@ -6936,6 +6943,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { function emptyFn() {} function QueueRunner(attrs) { + this.id_ = nextid++; var queueableFns = attrs.queueableFns || []; this.queueableFns = queueableFns.concat(attrs.cleanupFns || []); this.firstCleanupIx = queueableFns.length; diff --git a/spec/core/EnvSpec.js b/spec/core/EnvSpec.js index e32d8eda..77ae38a2 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -334,20 +334,16 @@ describe('Env', function() { expectationFactory('actual', specInstance); }); - env.addReporter({ - jasmineDone: function() { - expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([ - customObjectFormatter - ]); - expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({ - customTesters: [customEqualityTester], - pp: prettyPrinter - }); - done(); - } + env.execute(null, function() { + expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([ + customObjectFormatter + ]); + expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({ + customTesters: [customEqualityTester], + pp: prettyPrinter + }); + done(); }); - - env.execute(); }); it('creates an asyncExpectationFactory that uses the current custom equality testers and object formatters', function(done) { @@ -371,19 +367,15 @@ describe('Env', function() { asyncExpectationFactory('actual', specInstance); }); - env.addReporter({ - jasmineDone: function() { - expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([ - customObjectFormatter - ]); - expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({ - customTesters: [customEqualityTester], - pp: prettyPrinter - }); - done(); - } + env.execute(null, function() { + expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([ + customObjectFormatter + ]); + expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({ + customTesters: [customEqualityTester], + pp: prettyPrinter + }); + done(); }); - - env.execute(); }); }); diff --git a/spec/core/ExceptionsSpec.js b/spec/core/ExceptionsSpec.js index c5e65754..d950d2e2 100644 --- a/spec/core/ExceptionsSpec.js +++ b/spec/core/ExceptionsSpec.js @@ -29,8 +29,7 @@ describe('Exceptions:', function() { done(); }; - env.addReporter({ jasmineDone: expectations }); - env.execute(); + env.execute(null, expectations); }); it('should handle exceptions thrown directly in top-level describe blocks and continue', function(done) { @@ -49,7 +48,6 @@ describe('Exceptions:', function() { done(); }; - env.addReporter({ jasmineDone: expectations }); - env.execute(); + env.execute(null, expectations); }); }); diff --git a/spec/core/integration/AsymmetricEqualityTestersSpec.js b/spec/core/integration/AsymmetricEqualityTestersSpec.js index 1ccf2801..518c5bde 100644 --- a/spec/core/integration/AsymmetricEqualityTestersSpec.js +++ b/spec/core/integration/AsymmetricEqualityTestersSpec.js @@ -19,8 +19,8 @@ describe('Asymmetric equality testers (Integration)', function () { .toBeUndefined(); }; - env.addReporter({specDone: specExpectations, jasmineDone: done}); - env.execute(); + env.addReporter({specDone: specExpectations}); + env.execute(null, done); }); } @@ -43,8 +43,8 @@ describe('Asymmetric equality testers (Integration)', function () { .not.toEqual(''); }; - env.addReporter({specDone: specExpectations, jasmineDone: done}); - env.execute(); + env.addReporter({specDone: specExpectations}); + env.execute(null, done); }); } diff --git a/spec/core/integration/CustomAsyncMatchersSpec.js b/spec/core/integration/CustomAsyncMatchersSpec.js index 1b60bb45..4e97185f 100644 --- a/spec/core/integration/CustomAsyncMatchersSpec.js +++ b/spec/core/integration/CustomAsyncMatchersSpec.js @@ -28,8 +28,8 @@ describe('Custom Async Matchers (Integration)', function() { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it('uses the negative compare function for a negative comparison, if provided', function(done) { @@ -52,8 +52,8 @@ describe('Custom Async Matchers (Integration)', function() { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it('generates messages with the same rules as built in matchers absent a custom message', function(done) { @@ -77,8 +77,8 @@ describe('Custom Async Matchers (Integration)', function() { expect(result.failedExpectations[0].message).toEqual("Expected 'a' to be real."); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); // TODO: remove this in the next major release. @@ -113,8 +113,8 @@ describe('Custom Async Matchers (Integration)', function() { ); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("provides custom equality testers to the matcher factory via matchersUtil", function(done) { @@ -145,7 +145,7 @@ describe('Custom Async Matchers (Integration)', function() { expect(result.failedExpectations).toEqual([]); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); }); diff --git a/spec/core/integration/CustomMatchersSpec.js b/spec/core/integration/CustomMatchersSpec.js index c9812949..c299c6ac 100644 --- a/spec/core/integration/CustomMatchersSpec.js +++ b/spec/core/integration/CustomMatchersSpec.js @@ -37,9 +37,9 @@ describe("Custom Matchers (Integration)", function () { expect(firstSpecResult.failedExpectations[0].message).toEqual("matcherForSpec: actual: zzz; expected: yyy"); done(); }; - env.addReporter({ specDone:specDoneSpy, jasmineDone: expectations}); + env.addReporter({ specDone:specDoneSpy }); - env.execute(); + env.execute(null, expectations); }); it("passes the spec if the custom matcher passes", function(done) { @@ -57,8 +57,8 @@ describe("Custom Matchers (Integration)", function () { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("passes the spec if the custom equality matcher passes for types nested inside asymmetric equality testers", function(done) { @@ -81,8 +81,8 @@ describe("Custom Matchers (Integration)", function () { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("supports asymmetric equality testers that take a list of custom equality testers", function(done) { @@ -111,8 +111,8 @@ describe("Custom Matchers (Integration)", function () { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("displays an appropriate failure message if a custom equality matcher fails", function(done) { @@ -135,8 +135,8 @@ describe("Custom Matchers (Integration)", function () { ); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("uses the negative compare function for a negative comparison, if provided", function(done) { @@ -157,8 +157,8 @@ describe("Custom Matchers (Integration)", function () { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("generates messages with the same rules as built in matchers absent a custom message", function(done) { @@ -180,8 +180,8 @@ describe("Custom Matchers (Integration)", function () { expect(result.failedExpectations[0].message).toEqual("Expected 'a' to be real."); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("passes the expected and actual arguments to the comparison function", function(done) { @@ -205,8 +205,8 @@ describe("Custom Matchers (Integration)", function () { expect(argumentSpy).toHaveBeenCalledWith(true, "arg1", "arg2"); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); // TODO: remove this in the next major release. @@ -232,8 +232,8 @@ describe("Custom Matchers (Integration)", function () { ); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); it("provides custom equality testers to the matcher factory via matchersUtil", function (done) { @@ -262,7 +262,7 @@ describe("Custom Matchers (Integration)", function () { expect(result.failedExpectations).toEqual([]); }; - env.addReporter({specDone: specExpectations, jasmineDone: done}); - env.execute(); + env.addReporter({specDone: specExpectations}); + env.execute(null, done); }); }); diff --git a/spec/core/integration/CustomObjectFormatterSpec.js b/spec/core/integration/CustomObjectFormatterSpec.js index 10ed4d71..3337f452 100644 --- a/spec/core/integration/CustomObjectFormatterSpec.js +++ b/spec/core/integration/CustomObjectFormatterSpec.js @@ -25,9 +25,9 @@ describe("Custom object formatters", function() { expect(specResults[1].failedExpectations[0].message).toEqual("Expected 42 to be undefined."); done(); }; - env.addReporter({ specDone:specDone, jasmineDone: expectations}); + env.addReporter({ specDone:specDone }); - env.execute(); + env.execute(null, expectations); }); it("scopes custom object formatters to a suite", function(done) { @@ -54,9 +54,9 @@ describe("Custom object formatters", function() { expect(specResults[1].failedExpectations[0].message).toEqual("Expected custom(42) to be undefined."); done(); }; - env.addReporter({ specDone:specDone, jasmineDone: expectations}); + env.addReporter({ specDone:specDone }); - env.execute(); + env.execute(null, expectations); }); it("throws an exception if you try to add a custom object formatter outside a runable", function() { diff --git a/spec/core/integration/CustomSpyStrategiesSpec.js b/spec/core/integration/CustomSpyStrategiesSpec.js index 7ab4d28d..e05b0773 100644 --- a/spec/core/integration/CustomSpyStrategiesSpec.js +++ b/spec/core/integration/CustomSpyStrategiesSpec.js @@ -15,6 +15,7 @@ describe('Custom Spy Strategies (Integration)', function() { .and.returnValue(42); var strategy = jasmine.createSpy('custom strategy') .and.returnValue(plan); + var jasmineDone = jasmine.createSpy('jasmineDone'); env.describe('suite defining a custom spy strategy', function() { env.beforeEach(function() { @@ -33,13 +34,14 @@ describe('Custom Spy Strategies (Integration)', function() { expect(env.createSpy('something').and.frobnicate).toBeUndefined(); }); - function jasmineDone(result) { + function expectations() { + var result = jasmineDone.calls.argsFor(0)[0]; expect(result.overallStatus).toEqual('passed'); done(); } env.addReporter({ jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, expectations); }); it('allows adding more strategies local to a spec', function(done) { @@ -47,6 +49,7 @@ describe('Custom Spy Strategies (Integration)', function() { .and.returnValue(42); var strategy = jasmine.createSpy('custom strategy') .and.returnValue(plan); + var jasmineDone = jasmine.createSpy('jasmineDone'); env.it('spec defining a custom spy strategy', function() { env.addSpyStrategy('frobnicate', strategy); @@ -60,13 +63,14 @@ describe('Custom Spy Strategies (Integration)', function() { expect(env.createSpy('something').and.frobnicate).toBeUndefined(); }); - function jasmineDone(result) { + function expectations() { + var result = jasmineDone.calls.argsFor(0)[0]; expect(result.overallStatus).toEqual('passed'); done(); } env.addReporter({ jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, expectations); }); it('allows using custom strategies on a per-argument basis', function(done) { @@ -74,6 +78,7 @@ describe('Custom Spy Strategies (Integration)', function() { .and.returnValue(42); var strategy = jasmine.createSpy('custom strategy') .and.returnValue(plan); + var jasmineDone = jasmine.createSpy('jasmineDone'); env.it('spec defining a custom spy strategy', function() { env.addSpyStrategy('frobnicate', strategy); @@ -91,13 +96,14 @@ describe('Custom Spy Strategies (Integration)', function() { expect(env.createSpy('something').and.frobnicate).toBeUndefined(); }); - function jasmineDone(result) { + function expectations() { + var result = jasmineDone.calls.argsFor(0)[0]; expect(result.overallStatus).toEqual('passed'); done(); } env.addReporter({ jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, expectations); }); it('allows multiple custom strategies to be used', function(done) { @@ -105,7 +111,9 @@ describe('Custom Spy Strategies (Integration)', function() { strategy1 = jasmine.createSpy('strat 1').and.returnValue(plan1), plan2 = jasmine.createSpy('plan 2').and.returnValue(24), strategy2 = jasmine.createSpy('strat 2').and.returnValue(plan2), - specDone = jasmine.createSpy('specDone'); + specDone = jasmine.createSpy('specDone'), + jasmineDone = jasmine.createSpy('jasmineDone'); + env.beforeEach(function() { env.addSpyStrategy('frobnicate', strategy1); @@ -130,13 +138,14 @@ describe('Custom Spy Strategies (Integration)', function() { expect(plan2).toHaveBeenCalled(); }); - function jasmineDone(result) { + function expectations() { + var result = jasmineDone.calls.argsFor(0)[0]; expect(result.overallStatus).toEqual('passed'); expect(specDone.calls.count()).toBe(2); done(); } env.addReporter({ jasmineDone: jasmineDone, specDone: specDone }); - env.execute(); + env.execute(null, expectations); }); }); diff --git a/spec/core/integration/DefaultSpyStrategySpec.js b/spec/core/integration/DefaultSpyStrategySpec.js index 584b25b2..50a11544 100644 --- a/spec/core/integration/DefaultSpyStrategySpec.js +++ b/spec/core/integration/DefaultSpyStrategySpec.js @@ -29,13 +29,15 @@ describe('Default Spy Strategy (Integration)', function() { expect(spy()).toBeUndefined(); }); - function jasmineDone(result) { + function expectations() { + var result = jasmineDone.calls.argsFor(0)[0]; expect(result.overallStatus).toEqual('passed'); done(); } + var jasmineDone = jasmine.createSpy('jasmineDone'); env.addReporter({ jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, expectations); }); it('uses the default spy strategy defined when the spy is created', function (done) { @@ -61,12 +63,14 @@ describe('Default Spy Strategy (Integration)', function() { expect(d.and.isConfigured()).toBe(false); }); - function jasmineDone(result) { + function expectations() { + var result = jasmineDone.calls.argsFor(0)[0]; expect(result.overallStatus).toEqual('passed'); done(); } + var jasmineDone = jasmine.createSpy('jasmineDone'); env.addReporter({ jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, expectations); }); }); diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index ae7cd0d6..cf1e997d 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -22,7 +22,6 @@ describe("Env integration", function() { done(); }; - env.addReporter({ jasmineDone: assertions}); env.configure({random: false}); env.describe("A Suite", function() { @@ -34,7 +33,7 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("Nested Suites execute as expected", function(done) { @@ -50,7 +49,6 @@ describe("Env integration", function() { done(); }; - env.addReporter({ jasmineDone: assertions }); env.configure({random: false}); env.describe("Outer suite", function() { @@ -67,7 +65,7 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("Multiple top-level Suites execute as expected", function(done) { @@ -84,7 +82,6 @@ describe("Env integration", function() { done(); }; - env.addReporter({ jasmineDone: assertions }); env.configure({random: false}); @@ -108,57 +105,13 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it('explicitly fails a spec', function(done) { var specDone = jasmine.createSpy('specDone'); - env.addReporter({ - specDone: specDone, - jasmineDone: function() { - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'has a default message', - failedExpectations: [jasmine.objectContaining({ - message: 'Failed' - })] - })); - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'specifies a message', - failedExpectations: [jasmine.objectContaining({ - message: 'Failed: messy message' - })] - })); - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'has a message and stack trace from an Error', - failedExpectations: [jasmine.objectContaining({ - message: 'Failed: error message', - stack: { - asymmetricMatch: function(other) { - if (!other) { - // IE doesn't give us a stacktrace so just ignore it. - return true; - } - var split = other.split('\n'), - firstLine = split[0]; - if (firstLine.indexOf('error message') >= 0) { - // Chrome inserts the message and a newline before the first stacktrace line. - firstLine = split[1]; - } - return firstLine.indexOf('EnvSpec') >= 0; - } - } - })] - })); - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'pretty prints objects', - failedExpectations: [jasmine.objectContaining({ - message: 'Failed: Object({ prop: \'value\', arr: [ \'works\', true ] })' - })] - })); - done(); - } - }); + env.addReporter({specDone: specDone}); env.describe('failing', function() { env.it('has a default message', function() { @@ -178,15 +131,51 @@ describe("Env integration", function() { }) }); - env.execute(); + env.execute(null, function() { + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'has a default message', + failedExpectations: [jasmine.objectContaining({ + message: 'Failed' + })] + })); + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'specifies a message', + failedExpectations: [jasmine.objectContaining({ + message: 'Failed: messy message' + })] + })); + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'has a message and stack trace from an Error', + failedExpectations: [jasmine.objectContaining({ + message: 'Failed: error message', + stack: { + asymmetricMatch: function(other) { + if (!other) { + // IE doesn't give us a stacktrace so just ignore it. + return true; + } + var split = other.split('\n'), + firstLine = split[0]; + if (firstLine.indexOf('error message') >= 0) { + // Chrome inserts the message and a newline before the first stacktrace line. + firstLine = split[1]; + } + return firstLine.indexOf('EnvSpec') >= 0; + } + } + })] + })); + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'pretty prints objects', + failedExpectations: [jasmine.objectContaining({ + message: 'Failed: Object({ prop: \'value\', arr: [ \'works\', true ] })' + })] + })); + done(); + }); }); it("produces an understandable error message when 'fail' is used outside of a current spec", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']); - - reporter.jasmineDone.and.callFake(done); - env.addReporter(reporter); - env.describe("A Suite", function() { env.it("an async spec that is actually synchronous", function(underTestCallback) { underTestCallback(); @@ -194,12 +183,11 @@ describe("Env integration", function() { expect(function() { env.fail(); }).toThrowError(/'fail' was used when there was no current spec/); }); - env.execute(); + env.execute(null, done); }); it("calls associated befores/specs/afters with the same 'this'", function(done) { - env.addReporter({jasmineDone: done}); env.configure({random: false}); env.describe("tests", function() { var firstTimeThrough = true, firstSpecContext, secondSpecContext; @@ -231,12 +219,10 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, done); }); it("calls associated befores/its/afters with the same 'this' for an async spec", function(done) { - env.addReporter({jasmineDone: done}); - env.describe("with an async spec", function() { var specContext; @@ -255,22 +241,13 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, done); }); it("calls associated beforeAlls/afterAlls only once per suite", function(done) { var before = jasmine.createSpy('beforeAll'), after = jasmine.createSpy('afterAll'); - env.addReporter({ - jasmineDone: function() { - expect(after).toHaveBeenCalled(); - expect(after.calls.count()).toBe(1); - expect(before.calls.count()).toBe(1); - done(); - } - }); - env.describe("with beforeAll and afterAll", function() { env.it("spec", function() { expect(before).toHaveBeenCalled(); @@ -286,22 +263,18 @@ describe("Env integration", function() { env.afterAll(after); }); - env.execute(); + env.execute(null, function() { + expect(after).toHaveBeenCalled(); + expect(after.calls.count()).toBe(1); + expect(before.calls.count()).toBe(1); + done(); + }); }); it("calls associated beforeAlls/afterAlls only once per suite for async", function(done) { var before = jasmine.createSpy('beforeAll'), after = jasmine.createSpy('afterAll'); - env.addReporter({ - jasmineDone: function() { - expect(after).toHaveBeenCalled(); - expect(after.calls.count()).toBe(1); - expect(before.calls.count()).toBe(1); - done(); - } - }); - env.describe("with beforeAll and afterAll", function() { env.it("spec", function() { expect(before).toHaveBeenCalled(); @@ -324,12 +297,15 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + expect(after).toHaveBeenCalled(); + expect(after.calls.count()).toBe(1); + expect(before.calls.count()).toBe(1); + done(); + }); }); it("calls associated beforeAlls/afterAlls with the cascaded 'this'", function(done) { - env.addReporter({jasmineDone: done}); - env.describe("with beforeAll and afterAll", function() { env.beforeAll(function() { this.x = 1; @@ -376,14 +352,11 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, done); }); it("tags top-level afterAll failures with a type", function(done) { - env.addReporter({jasmineDone: function(result) { - expect(result.failedExpectations[0].globalErrorType).toEqual('afterAll'); - done(); - }}); + var jasmineDone = jasmine.createSpy('jasmineDone'); env.it('has a spec', function() {}); @@ -391,20 +364,22 @@ describe("Env integration", function() { throw 'nope'; }); - env.execute(); + env.addReporter({ jasmineDone: jasmineDone }); + env.execute(null, function() {{ + var result = jasmineDone.calls.argsFor(0)[0]; + expect(result.failedExpectations[0].globalErrorType).toEqual('afterAll'); + done(); + }}); }); it("does not tag suite afterAll failures with a type", function(done) { var reporter = { - jasmineDone: function() { - expect(reporter.suiteDone).toHaveBeenCalled(); - done(); - }, suiteDone: jasmine.createSpy('suiteDone').and.callFake(function(result) { expect(result.failedExpectations[0].globalErrorType).toBeFalsy(); }) }; + env.addReporter(reporter); env.describe('a suite', function() { @@ -415,20 +390,23 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + expect(reporter.suiteDone).toHaveBeenCalled(); + done(); + }); }); it("when the beforeAll fails, error at suite level", function (done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "suiteDone", "jasmineDone" ]); + var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "suiteDone" ]); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.specDone.calls.count()).toEqual(2); expect(reporter.specDone).toHaveFailedExpectationsForRunnable('A suite spec that will pass', []); expect(reporter.specDone).toHaveFailedExpectationsForRunnable('A suite nesting another spec to pass', []); expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('A suite', ['Expected 1 to be 2.']); done(); - }); + }; env.addReporter(reporter); @@ -446,7 +424,7 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("copes with async failures after done has been called", function(done) { @@ -457,13 +435,13 @@ describe("Env integration", function() { spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global); env.cleanup_(); env = new jasmineUnderTest.Env(); - var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone", "suiteDone" ]); + var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "suiteDone" ]); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.specDone).not.toHaveFailedExpectationsForRunnable('A suite fails', ['fail thrown']); expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('A suite', ['fail thrown']); done(); - }); + }; env.addReporter(reporter); @@ -484,20 +462,20 @@ describe("Env integration", function() { env.it('is not run', function() {}); }); - env.execute(); + env.execute(null, assertions); }); describe('suiteDone reporting', function(){ it("reports when an afterAll fails an expectation", function(done) { - var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']); + var reporter = jasmine.createSpyObj('fakeReport', ['suiteDone']); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('my suite', [ 'Expected 1 to equal 2.', 'Expected 2 to equal 3.' ]); done(); - }); + }; env.addReporter(reporter); @@ -511,19 +489,19 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("if there are no specs, it still reports correctly", function(done) { - var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']); + var reporter = jasmine.createSpyObj('fakeReport', ['suiteDone']); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer suite', [ 'Expected 1 to equal 2.', 'Expected 2 to equal 3.' ]); done(); - }); + }; env.addReporter(reporter); @@ -538,19 +516,19 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("reports when afterAll throws an exception", function(done) { var error = new Error('After All Exception'), - reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']); + reporter = jasmine.createSpyObj('fakeReport', ['suiteDone']); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('my suite', [ (/^Error: After All Exception/) ]); done(); - }); + }; env.addReporter(reporter); @@ -563,18 +541,18 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("reports when an async afterAll fails an expectation", function(done) { - var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']); + var reporter = jasmine.createSpyObj('fakeReport', ['suiteDone']); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('my suite', [ 'Expected 1 to equal 2.' ]); done(); - }); + }; env.addReporter(reporter); @@ -588,20 +566,20 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it("reports when an async afterAll throws an exception", function(done) { var error = new Error('After All Exception'), - reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']); + reporter = jasmine.createSpyObj('fakeReport', ['suiteDone']); - reporter.jasmineDone.and.callFake(function() { + var assertions = function() { expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('my suite', [ (/^Error: After All Exception/) ]); done(); - }); + }; env.addReporter(reporter); @@ -614,7 +592,7 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, assertions); }); it('reports the duration of the suite', function(done) { @@ -624,10 +602,6 @@ describe("Env integration", function() { suiteDone: function(result) { expect(duration).toBeUndefined(); duration = result.duration; - }, - jasmineDone: function() { - expect(duration).toBeGreaterThanOrEqual(10); - done(); } }); @@ -639,7 +613,10 @@ describe("Env integration", function() { }) }); - env.execute(); + env.execute(null, function() { + expect(duration).toBeGreaterThanOrEqual(10); + done(); + }); }); }); @@ -651,10 +628,6 @@ describe("Env integration", function() { specDone: function(result) { expect(duration).toBeUndefined(); duration = result.duration; - }, - jasmineDone: function() { - expect(duration).toBeGreaterThanOrEqual(10); - done(); } }); @@ -666,19 +639,16 @@ describe("Env integration", function() { }) }); - env.execute(); + env.execute(null, function() { + expect(duration).toBeGreaterThanOrEqual(10); + done(); + }); }); }); it('reports expectation failures in global beforeAll', function(done) { var reporter = jasmine.createSpyObj(['specDone', 'jasmineDone']); - reporter.jasmineDone.and.callFake(function(results) { - expect(results.failedExpectations).toEqual([jasmine.objectContaining({ message: 'Expected 1 to be 0.' })]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('is a spec', []); - done(); - }); - env.beforeAll(function() { env.expect(1).toBe(0); }); @@ -689,17 +659,17 @@ describe("Env integration", function() { env.addReporter(reporter); - env.execute(); + env.execute(null, function() { + var results = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(results.failedExpectations).toEqual([jasmine.objectContaining({ message: 'Expected 1 to be 0.' })]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('is a spec', []); + done(); + }); }); it('reports expectation failures in global afterAll', function(done) { var reporter = jasmine.createSpyObj(['jasmineDone']); - reporter.jasmineDone.and.callFake(function(results) { - expect(results.failedExpectations).toEqual([jasmine.objectContaining({ message: 'Expected 1 to be 0.' })]); - done(); - }); - env.afterAll(function() { env.expect(1).toBe(0); }); @@ -710,7 +680,11 @@ describe("Env integration", function() { env.addReporter(reporter); - env.execute(); + env.execute(null, function() { + var results = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(results.failedExpectations).toEqual([jasmine.objectContaining({ message: 'Expected 1 to be 0.' })]); + done(); + }); }); it("Allows specifying which specs and suites to run", function(done) { @@ -719,16 +693,7 @@ describe("Env integration", function() { firstSpec, secondSuite; - var assertions = function() { - expect(calls).toEqual([ - 'third spec', - 'first spec' - ]); - expect(suiteCallback).toHaveBeenCalled(); - done(); - }; - - env.addReporter({jasmineDone: assertions, suiteDone: suiteCallback}); + env.addReporter({ suiteDone: suiteCallback}); env.describe("first suite", function() { firstSpec = env.it("first spec", function() { @@ -745,7 +710,14 @@ describe("Env integration", function() { }); }); - env.execute([secondSuite.id, firstSpec.id]); + env.execute([secondSuite.id, firstSpec.id], function() { + expect(calls).toEqual([ + 'third spec', + 'first spec' + ]); + expect(suiteCallback).toHaveBeenCalled(); + done(); + }); }); it('runs before and after all functions for runnables provided to .execute()', function(done) { @@ -753,18 +725,6 @@ describe("Env integration", function() { first_spec, second_spec; - var assertions = function() { - expect(calls).toEqual([ - "before", - "first spec", - "second spec", - "after" - ]); - done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.describe("first suite", function() { env.beforeAll(function() { calls.push("before"); @@ -780,7 +740,15 @@ describe("Env integration", function() { }); }); - env.execute([first_spec.id, second_spec.id]); + env.execute([first_spec.id, second_spec.id], function() { + expect(calls).toEqual([ + "before", + "first spec", + "second spec", + "after" + ]); + done(); + }); }); it("Allows filtering out specs and suites to run programmatically", function(done) { @@ -789,17 +757,7 @@ describe("Env integration", function() { firstSpec, secondSuite; - var assertions = function() { - expect(calls.length).toEqual(2); - expect(calls).toEqual(jasmine.arrayContaining([ - 'first spec', - 'second spec' - ])); - expect(suiteCallback).toHaveBeenCalled(); - done(); - }; - - env.addReporter({jasmineDone: assertions, suiteDone: suiteCallback}); + env.addReporter({suiteDone: suiteCallback}); env.describe("first suite", function() { env.it("first spec", function() { @@ -822,7 +780,15 @@ describe("Env integration", function() { } }); - env.execute(); + env.execute(null, function() { + expect(calls.length).toEqual(2); + expect(calls).toEqual(jasmine.arrayContaining([ + 'first spec', + 'second spec' + ])); + expect(suiteCallback).toHaveBeenCalled(); + done(); + }); }); it("Functions can be spied on and have their calls tracked", function (done) { @@ -834,8 +800,6 @@ describe("Env integration", function() { } }; - env.addReporter({jasmineDone: done}); - env.it("works with spies", function() { var spy = env.spyOn(subject, 'spiedFunc').and.returnValue("stubbed result"); @@ -885,7 +849,7 @@ describe("Env integration", function() { }).toThrowError('You must use the new keyword.'); }); - env.execute(); + env.execute(null, done); }); it('can be configured to allow respying on functions', function (done) { @@ -896,7 +860,6 @@ describe("Env integration", function() { }; env.allowRespy(true); - env.addReporter({ jasmineDone: done }); env.describe('test suite', function() { env.it('spec 0', function() { @@ -910,7 +873,7 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, done); }); it('removes all spies added in a spec after the spec is complete', function(done) { @@ -929,15 +892,11 @@ describe("Env integration", function() { env.it('spec 1', secondSpec); }); - var assertions = function() { + env.execute(null, function() { expect(firstSpec).toHaveBeenCalled(); expect(secondSpec).toHaveBeenCalled(); done(); - }; - - env.addReporter({ jasmineDone: assertions }); - - env.execute(); + }); }); it('removes all spies added in a suite after the suite is complete', function(done) { @@ -964,9 +923,7 @@ describe("Env integration", function() { }); }); - env.addReporter({ jasmineDone: done }); - - env.execute(); + env.execute(null, done); }); it('removes a spy from the top suite after the run is complete', function(done) { @@ -983,14 +940,10 @@ describe("Env integration", function() { expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(true); }); - env.addReporter({ - jasmineDone: function() { - expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(false); - done(); - } + env.execute(null, function() { + expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(false); + done(); }); - - env.execute(); }); it("Mock clock can be installed and used in tests", function(done) { @@ -1001,14 +954,6 @@ describe("Env integration", function() { env.cleanup_(); env = new jasmineUnderTest.Env({global: { setTimeout: globalSetTimeout, clearTimeout: clearTimeout, setImmediate: function(cb) { setTimeout(cb, 0); } }}); - var assertions = function() { - expect(delayedFunctionForMockClock).toHaveBeenCalled(); - expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100); - - done(); - }; - - env.addReporter({ jasmineDone: assertions }); env.configure({random: false}); env.describe("tests", function() { @@ -1026,17 +971,16 @@ describe("Env integration", function() { expect(globalSetTimeout).not.toHaveBeenCalled(); expect(delayedFunctionForMockClock).not.toHaveBeenCalled(); - env.execute(); + env.execute(null, function() { + expect(delayedFunctionForMockClock).toHaveBeenCalled(); + expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100); + + done(); + }); }); it("should run async specs in order, waiting for them to complete", function(done) { - var reporter = jasmine.createSpyObj('reporter', ['jasmineDone']), - mutatedVar; - - reporter.jasmineDone.and.callFake(function() { - done(); - }); - env.addReporter(reporter); + var mutatedVar; env.describe("tests", function() { env.beforeEach(function() { @@ -1055,7 +999,7 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, done); }); describe("with a mock clock", function() { @@ -1068,9 +1012,9 @@ describe("Env integration", function() { setTimeout: function(cb, t) { var stack = jasmine.util.errorWithStack().stack; if (stack.indexOf('ClearStack') >= 0) { - realSetTimeout(cb, t); + return realSetTimeout(cb, t); } else { - setTimeout(cb, t); + return setTimeout(cb, t); } }, clearTimeout: clearTimeout, @@ -1095,7 +1039,7 @@ describe("Env integration", function() { it("should wait a default interval before failing specs that haven't called done yet", function(done) { createMockedEnv(); - var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]); + var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone" ]); reporter.specDone.and.callFake(function(result) { expect(result).toEqual(jasmine.objectContaining({status: 'failed'})); @@ -1104,12 +1048,6 @@ describe("Env integration", function() { }, 0); }); - reporter.jasmineDone.and.callFake(function() { - expect(reporter.specDone.calls.count()).toEqual(1); - jasmine.clock().tick(1); - realSetTimeout(done); - }); - env.addReporter(reporter); jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 8414; @@ -1119,12 +1057,16 @@ describe("Env integration", function() { jasmine.clock().tick(1); }); - env.execute(); + env.execute(null, function() { + expect(reporter.specDone.calls.count()).toEqual(1); + jasmine.clock().tick(1); + realSetTimeout(done); + }); }); it("should not use the mock clock for asynchronous timeouts", function(done){ createMockedEnv(); - var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]), + var reporter = jasmine.createSpyObj('fakeReporter', [ "specDone" ]), clock = env.clock; reporter.specDone.and.callFake(function() { @@ -1133,13 +1075,6 @@ describe("Env integration", function() { }, 0); }); - reporter.jasmineDone.and.callFake(function() { - expect(reporter.specDone).toHaveBeenCalledTimes(1); - expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(jasmine.objectContaining({status: 'passed'})); - jasmine.clock().tick(1); - realSetTimeout(done); - }); - env.addReporter(reporter); jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 5; @@ -1157,25 +1092,18 @@ describe("Env integration", function() { realSetTimeout(innerDone); }); - env.execute(); + env.execute(null, function() { + expect(reporter.specDone).toHaveBeenCalledTimes(1); + expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(jasmine.objectContaining({status: 'passed'})); + jasmine.clock().tick(1); + realSetTimeout(done); + }); }); it('should wait a custom interval before reporting async functions that fail to complete', function(done) { createMockedEnv(); var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(r) { - expect(r.failedExpectations).toEqual([]); - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite beforeAll', [ /^Error: Timeout - Async function did not complete within 5000ms \(custom timeout\)/ ]); - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite afterAll', [ /^Error: Timeout - Async function did not complete within 2000ms \(custom timeout\)/ ]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite beforeEach times out', [/^Error: Timeout - Async function did not complete within 1000ms \(custom timeout\)/]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite afterEach times out', [ /^Error: Timeout - Async function did not complete within 4000ms \(custom timeout\)/ ]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite it times out', [ /^Error: Timeout - Async function did not complete within 6000ms \(custom timeout\)/ ]); - - jasmine.clock().tick(1); - realSetTimeout(done); - }); - env.addReporter(reporter); jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 10000; @@ -1256,35 +1184,25 @@ describe("Env integration", function() { }, 6000); }); - env.execute(); + env.execute(null, function() { + var r = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(r.failedExpectations).toEqual([]); + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite beforeAll', [ /^Error: Timeout - Async function did not complete within 5000ms \(custom timeout\)/ ]); + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite afterAll', [ /^Error: Timeout - Async function did not complete within 2000ms \(custom timeout\)/ ]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite beforeEach times out', [/^Error: Timeout - Async function did not complete within 1000ms \(custom timeout\)/]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite afterEach times out', [ /^Error: Timeout - Async function did not complete within 4000ms \(custom timeout\)/ ]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite it times out', [ /^Error: Timeout - Async function did not complete within 6000ms \(custom timeout\)/ ]); + + jasmine.clock().tick(1); + realSetTimeout(done); + }); }); }); it('explicitly fails an async spec', function(done) { var specDone = jasmine.createSpy('specDone'); - env.addReporter({ - specDone: specDone, - jasmineDone: function() { - expect(specDone).toHaveFailedExpectationsForRunnable('failing has a default message', - ['Failed'] - ); - expect(specDone).toHaveFailedExpectationsForRunnable('failing specifies a message', - ['Failed: messy message'] - ); - expect(specDone).toHaveFailedExpectationsForRunnable('failing fails via the done callback', - ['Failed: done failed'] - ); - expect(specDone).toHaveFailedExpectationsForRunnable('failing has a message from an Error', - ['Failed: error message'] - ); - expect(specDone).toHaveFailedExpectationsForRunnable('failing has a message from an Error to done', - ['Failed: done error'] - ); - - setTimeout(done); - } - }); + env.addReporter({specDone: specDone}); env.describe('failing', function() { env.it('has a default message', function(innerDone) { @@ -1321,20 +1239,31 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + expect(specDone).toHaveFailedExpectationsForRunnable('failing has a default message', + ['Failed'] + ); + expect(specDone).toHaveFailedExpectationsForRunnable('failing specifies a message', + ['Failed: messy message'] + ); + expect(specDone).toHaveFailedExpectationsForRunnable('failing fails via the done callback', + ['Failed: done failed'] + ); + expect(specDone).toHaveFailedExpectationsForRunnable('failing has a message from an Error', + ['Failed: error message'] + ); + expect(specDone).toHaveFailedExpectationsForRunnable('failing has a message from an Error to done', + ['Failed: done error'] + ); + + setTimeout(done); + }); }); describe('focused tests', function() { it('should only run the focused tests', function(done) { var calls = []; - var assertions = function() { - expect(calls).toEqual(['focused']); - done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.describe('a suite', function() { env.fit('is focused', function() { calls.push('focused'); @@ -1345,19 +1274,15 @@ describe("Env integration", function() { }) }); - env.execute(); + env.execute(null, function() { + expect(calls).toEqual(['focused']); + done(); + }); }); it('should only run focused suites', function(done){ var calls = []; - var assertions = function() { - expect(calls).toEqual(['focused']); - done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.fdescribe('a focused suite', function() { env.it('is focused', function() { calls.push('focused'); @@ -1370,20 +1295,30 @@ describe("Env integration", function() { }) }); - env.execute(); + env.execute(null, function() { + expect(calls).toEqual(['focused']); + done(); + }); }); it('should run focused tests inside an xdescribe', function(done) { var reporter = jasmine.createSpyObj('fakeReporter', [ "jasmineStarted", - "jasmineDone", "suiteStarted", "suiteDone", "specStarted", "specDone" ]); - reporter.jasmineDone.and.callFake(function() { + env.addReporter(reporter); + + env.xdescribe("xd suite", function() { + env.fit("with a fit spec", function() { + env.expect(true).toBe(false); + }); + }); + + env.execute(null, function() { expect(reporter.jasmineStarted).toHaveBeenCalledWith({ totalSpecsDefined: 1, order: jasmine.any(jasmineUnderTest.Order) @@ -1396,29 +1331,28 @@ describe("Env integration", function() { done(); }); - - env.addReporter(reporter); - - env.xdescribe("xd suite", function() { - env.fit("with a fit spec", function() { - env.expect(true).toBe(false); - }); - }); - - env.execute(); }); it('should run focused suites inside an xdescribe', function(done) { var reporter = jasmine.createSpyObj('fakeReporter', [ "jasmineStarted", - "jasmineDone", "suiteStarted", "suiteDone", "specStarted", "specDone" ]); - reporter.jasmineDone.and.callFake(function() { + env.addReporter(reporter); + + env.xdescribe("xd suite", function() { + env.fdescribe("fd suite", function() { + env.it("with a spec", function() { + env.expect(true).toBe(false); + }); + }); + }); + + env.execute(null, function() { expect(reporter.jasmineStarted).toHaveBeenCalledWith({ totalSpecsDefined: 1, order: jasmine.any(jasmineUnderTest.Order) @@ -1431,32 +1365,42 @@ describe("Env integration", function() { done(); }); - - env.addReporter(reporter); - - env.xdescribe("xd suite", function() { - env.fdescribe("fd suite", function() { - env.it("with a spec", function() { - env.expect(true).toBe(false); - }); - }); - }); - - env.execute(); }); }); it("should report as expected", function(done) { var reporter = jasmine.createSpyObj('fakeReporter', [ "jasmineStarted", - "jasmineDone", "suiteStarted", "suiteDone", "specStarted", "specDone" ]); - reporter.jasmineDone.and.callFake(function() { + env.addReporter(reporter); + + env.describe("A Suite", function() { + env.it("with a top level spec", function() { + env.expect(true).toBe(true); + }); + env.describe("with a nested suite", function() { + env.xit("with an x'ed spec", function() { + env.expect(true).toBe(true); + }); + env.it("with a spec", function() { + env.expect(true).toBe(false); + }); + }); + + env.describe('with only non-executable specs', function() { + env.it('is pending'); + env.xit('is xed', function() { + env.expect(true).toBe(true); + }); + }); + }); + + env.execute(null, function() { expect(reporter.jasmineStarted).toHaveBeenCalledWith({ totalSpecsDefined: 5, order: jasmine.any(jasmineUnderTest.Order) @@ -1492,31 +1436,6 @@ describe("Env integration", function() { done(); }); - - env.addReporter(reporter); - - env.describe("A Suite", function() { - env.it("with a top level spec", function() { - env.expect(true).toBe(true); - }); - env.describe("with a nested suite", function() { - env.xit("with an x'ed spec", function() { - env.expect(true).toBe(true); - }); - env.it("with a spec", function() { - env.expect(true).toBe(false); - }); - }); - - env.describe('with only non-executable specs', function() { - env.it('is pending'); - env.xit('is xed', function() { - env.expect(true).toBe(true); - }); - }); - }); - - env.execute(); }); it("should report the random seed at the beginning and end of execution", function(done) { @@ -1530,36 +1449,23 @@ describe("Env integration", function() { ]); env.configure({random: true, seed: '123456'}); - reporter.jasmineDone.and.callFake(function(doneArg) { + env.addReporter(reporter); + env.configure({random: true}); + env.execute(null, function() { expect(reporter.jasmineStarted).toHaveBeenCalled(); var startedArg = reporter.jasmineStarted.calls.argsFor(0)[0]; expect(startedArg.order.random).toEqual(true); expect(startedArg.order.seed).toEqual('123456'); + var doneArg = reporter.jasmineDone.calls.argsFor(0)[0]; expect(doneArg.order.random).toEqual(true); expect(doneArg.order.seed).toEqual('123456'); done(); }); - - env.addReporter(reporter); - env.configure({random: true}); - env.execute(); }); it('should report pending spec messages', function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ - 'specDone', - 'jasmineDone' - ]); - - reporter.jasmineDone.and.callFake(function() { - var specStatus = reporter.specDone.calls.argsFor(0)[0]; - - expect(specStatus.status).toBe('pending'); - expect(specStatus.pendingReason).toBe('with a message'); - - done(); - }); + var reporter = jasmine.createSpyObj('fakeReporter', ['specDone']); env.addReporter(reporter); @@ -1567,7 +1473,14 @@ describe("Env integration", function() { env.pending('with a message'); }); - env.execute(); + env.execute(null, function() { + var specStatus = reporter.specDone.calls.argsFor(0)[0]; + + expect(specStatus.status).toBe('pending'); + expect(specStatus.pendingReason).toBe('with a message'); + + done(); + }); }); it('should report pending spec messages from promise-returning functions', function(done) { @@ -1583,19 +1496,7 @@ describe("Env integration", function() { reject(this.exception); }; - var reporter = jasmine.createSpyObj('fakeReporter', [ - 'specDone', - 'jasmineDone' - ]); - - reporter.jasmineDone.and.callFake(function() { - var specStatus = reporter.specDone.calls.argsFor(0)[0]; - - expect(specStatus.status).toBe('pending'); - expect(specStatus.pendingReason).toBe('with a message'); - - done(); - }); + var reporter = jasmine.createSpyObj('fakeReporter', ['specDone']); env.addReporter(reporter); @@ -1605,7 +1506,14 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + var specStatus = reporter.specDone.calls.argsFor(0)[0]; + + expect(specStatus.status).toBe('pending'); + expect(specStatus.pendingReason).toBe('with a message'); + + done(); + }); }); it('should report using fallback reporter', function(done) { @@ -1632,26 +1540,12 @@ describe("Env integration", function() { it('should report xdescribes as expected', function(done) { var reporter = jasmine.createSpyObj('fakeReporter', [ "jasmineStarted", - "jasmineDone", "suiteStarted", "suiteDone", "specStarted", "specDone" ]); - reporter.jasmineDone.and.callFake(function() { - expect(reporter.jasmineStarted).toHaveBeenCalledWith({ - totalSpecsDefined: 1, - order: jasmine.any(jasmineUnderTest.Order) - }); - - expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({ status: 'pending' })); - expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ description: 'xd out', status: 'pending' })); - expect(reporter.suiteDone.calls.count()).toBe(4); - - done(); - }); - env.addReporter(reporter); env.describe("A Suite", function() { @@ -1666,7 +1560,18 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + expect(reporter.jasmineStarted).toHaveBeenCalledWith({ + totalSpecsDefined: 1, + order: jasmine.any(jasmineUnderTest.Order) + }); + + expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({ status: 'pending' })); + expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ description: 'xd out', status: 'pending' })); + expect(reporter.suiteDone.calls.count()).toBe(4); + + done(); + }); }); it("should be possible to get full name from a spec", function() { @@ -1691,20 +1596,7 @@ describe("Env integration", function() { }); it("Custom equality testers should be per spec", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ - "jasmineDone", - "specDone" - ]); - - reporter.jasmineDone.and.callFake(function() { - var firstSpecResult = reporter.specDone.calls.first().args[0], - secondSpecResult = reporter.specDone.calls.mostRecent().args[0]; - - expect(firstSpecResult.status).toEqual("passed"); - expect(secondSpecResult.status).toEqual("failed"); - - done(); - }); + var reporter = jasmine.createSpyObj('fakeReporter', ["specDone"]); env.addReporter(reporter); env.configure({random: false}); @@ -1720,26 +1612,20 @@ describe("Env integration", function() { }); }); - env.execute(); - }); - - it("Custom equality testers should be per suite", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ - "jasmineDone", - "specDone" - ]); - - reporter.jasmineDone.and.callFake(function() { + env.execute(null, function() { var firstSpecResult = reporter.specDone.calls.first().args[0], - secondSpecResult = reporter.specDone.calls.argsFor(0)[0], - thirdSpecResult = reporter.specDone.calls.mostRecent().args[0]; + secondSpecResult = reporter.specDone.calls.mostRecent().args[0]; expect(firstSpecResult.status).toEqual("passed"); - expect(secondSpecResult.status).toEqual("passed"); - expect(thirdSpecResult.status).toEqual("failed"); + expect(secondSpecResult.status).toEqual("failed"); done(); }); + }); + + it("Custom equality testers should be per suite", function(done) { + var reporter = jasmine.createSpyObj('fakeReporter', ["specDone"]); + env.addReporter(reporter); env.configure({random: false}); @@ -1762,24 +1648,21 @@ describe("Env integration", function() { }); }); - env.execute(); - }); - - it("Custom equality testers for toContain should be per spec", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ - "jasmineDone", - "specDone" - ]); - - reporter.jasmineDone.and.callFake(function() { + env.execute(null, function() { var firstSpecResult = reporter.specDone.calls.first().args[0], - secondSpecResult = reporter.specDone.calls.mostRecent().args[0]; + secondSpecResult = reporter.specDone.calls.argsFor(0)[0], + thirdSpecResult = reporter.specDone.calls.mostRecent().args[0]; expect(firstSpecResult.status).toEqual("passed"); - expect(secondSpecResult.status).toEqual("failed"); + expect(secondSpecResult.status).toEqual("passed"); + expect(thirdSpecResult.status).toEqual("failed"); done(); }); + }); + + it("Custom equality testers for toContain should be per spec", function(done) { + var reporter = jasmine.createSpyObj('fakeReporter', ["specDone"]); env.addReporter(reporter); env.configure({random: false}); @@ -1795,15 +1678,18 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + var firstSpecResult = reporter.specDone.calls.first().args[0], + secondSpecResult = reporter.specDone.calls.mostRecent().args[0]; + + expect(firstSpecResult.status).toEqual("passed"); + expect(secondSpecResult.status).toEqual("failed"); + + done(); + }); }); it("produces an understandable error message when an 'expect' is used outside of a current spec", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']); - - reporter.jasmineDone.and.callFake(done); - env.addReporter(reporter); - env.describe("A Suite", function() { env.it("an async spec that is actually synchronous", function(underTestCallback) { underTestCallback(); @@ -1811,26 +1697,11 @@ describe("Env integration", function() { expect(function() { env.expect('a').toEqual('a'); }).toThrowError(/'expect' was used when there was no current spec/); }); - env.execute(); + env.execute(null, done); }); it("Custom equality testers for toContain should be per suite", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ - "jasmineDone", - "specDone" - ]); - - reporter.jasmineDone.and.callFake(function() { - var firstSpecResult = reporter.specDone.calls.first().args[0], - secondSpecResult = reporter.specDone.calls.argsFor(1)[0], - thirdSpecResult = reporter.specDone.calls.mostRecent().args[0]; - - expect(firstSpecResult.status).toEqual("passed"); - expect(secondSpecResult.status).toEqual("passed"); - expect(thirdSpecResult.status).toEqual("failed"); - - done(); - }); + var reporter = jasmine.createSpyObj('fakeReporter', ["specDone"]); env.addReporter(reporter); env.configure({random: false}); @@ -1853,7 +1724,17 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + var firstSpecResult = reporter.specDone.calls.first().args[0], + secondSpecResult = reporter.specDone.calls.argsFor(1)[0], + thirdSpecResult = reporter.specDone.calls.mostRecent().args[0]; + + expect(firstSpecResult.status).toEqual("passed"); + expect(secondSpecResult.status).toEqual("passed"); + expect(thirdSpecResult.status).toEqual("failed"); + + done(); + }); }); it("Custom matchers should be per spec", function(done) { @@ -1872,9 +1753,7 @@ describe("Env integration", function() { }); }); - env.addReporter({jasmineDone: done}); - - env.execute(); + env.execute(null, done); }); it("Custom matchers should be per suite", function(done) { @@ -1900,9 +1779,7 @@ describe("Env integration", function() { }); }); - env.addReporter({jasmineDone: done}); - - env.execute(); + env.execute(null, done); }); it('throws an exception if you try to create a spy outside of a runnable', function (done) { @@ -1917,14 +1794,10 @@ describe("Env integration", function() { } }); - var assertions = function() { + env.execute(null, function() { expect(exception.message).toBe('Spies must be created in a before function or a spec'); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it('throws an exception if you try to add a matcher outside of a runnable', function (done) { @@ -1939,14 +1812,10 @@ describe("Env integration", function() { } }); - var assertions = function() { + env.execute(null, function() { expect(exception.message).toBe('Matchers must be added in a before function or a spec'); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it('throws an exception if you try to add a custom equality outside of a runnable', function (done) { @@ -1961,30 +1830,28 @@ describe("Env integration", function() { } }); - var assertions = function() { + env.execute(null, function() { expect(exception.message).toBe('Custom Equalities must be added in a before function or a spec'); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it('reports test properties on specs', function(done) { var env = new jasmineUnderTest.Env(), - reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); + reporter = jasmine.createSpyObj('reporter', ['suiteDone', 'specDone']); reporter.specDone.and.callFake(function(e) { expect(e.properties).toEqual({a: 'Bee'}); - done(); }); env.addReporter(reporter); env.it('calls setSpecProperty', function() { env.setSpecProperty('a', 'Bee') }); - env.execute(); + env.execute(null, function() { + expect(reporter.specDone).toHaveBeenCalled(); + done(); + }); }); it('throws an exception if you try to setSpecProperty outside of a spec', function (done) { @@ -2000,14 +1867,10 @@ describe("Env integration", function() { } }); - var assertions = function() { + env.execute(null, function() { expect(exception.message).toBe("'setSpecProperty' was used when there was no current spec"); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it('reports test properties on suites', function(done) { @@ -2016,7 +1879,6 @@ describe("Env integration", function() { reporter.suiteDone.and.callFake(function(e) { expect(e.properties).toEqual({b: 'Sweet'}); - done(); }); env.addReporter(reporter); @@ -2029,7 +1891,10 @@ describe("Env integration", function() { }); }); - env.execute(); + env.execute(null, function() { + expect(reporter.suiteDone).toHaveBeenCalled(); + done(); + }); }); it('throws an exception if you try to setSuiteProperty outside of a suite', function (done) { @@ -2044,17 +1909,7 @@ describe("Env integration", function() { }); it("should associate errors thrown from async code with the correct runnable", function(done) { - var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone','specDone']); - - reporter.jasmineDone.and.callFake(function() { - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('async suite', [ - /^(((Uncaught )?(exception: )?Error: suite( thrown)?)|(suite thrown))$/ - ]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite async spec', [ - /^(((Uncaught )?(exception: )?Error: spec( thrown)?)|(spec thrown))$/ - ]); - done(); - }); + var reporter = jasmine.createSpyObj('fakeReport', ['suiteDone','specDone']); env.addReporter(reporter); @@ -2072,31 +1927,19 @@ describe("Env integration", function() { }, 10); }); - env.execute(); + env.execute(null, function() { + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('async suite', [ + /^(((Uncaught )?(exception: )?Error: suite( thrown)?)|(suite thrown))$/ + ]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite async spec', [ + /^(((Uncaught )?(exception: )?Error: spec( thrown)?)|(spec thrown))$/ + ]); + done(); + }); }); it('should throw on suites/specs/befores/afters nested in methods other than \'describe\'', function(done) { - var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - - reporter.jasmineDone.and.callFake(function() { - var msg = /\'.*\' should only be used in \'describe\' function/; - - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite describe', [msg]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite xdescribe', [msg]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite fdescribe', [msg]); - - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('spec it', [msg]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('spec xit', [msg]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('spec fit', [msg]); - - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('beforeAll', [msg]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('beforeEach spec', [msg]); - - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('afterAll', [msg]); - expect(reporter.specDone).toHaveFailedExpectationsForRunnable('afterEach spec', [msg]); - - done(); - }); + var reporter = jasmine.createSpyObj('reporter', ['suiteDone', 'specDone']); env.addReporter(reporter); @@ -2132,7 +1975,25 @@ describe("Env integration", function() { env.it('spec', function() {}); }); - env.execute(); + env.execute(null, function() { + var msg = /\'.*\' should only be used in \'describe\' function/; + + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite describe', [msg]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite xdescribe', [msg]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite fdescribe', [msg]); + + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('spec it', [msg]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('spec xit', [msg]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('spec fit', [msg]); + + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('beforeAll', [msg]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('beforeEach spec', [msg]); + + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('afterAll', [msg]); + expect(reporter.specDone).toHaveFailedExpectationsForRunnable('afterEach spec', [msg]); + + done(); + }); }); it('reports errors that occur during loading', function(done) { @@ -2147,7 +2008,12 @@ describe("Env integration", function() { env = new jasmineUnderTest.Env(); var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { + env.addReporter(reporter); + global.onerror('Uncaught SyntaxError: Unexpected end of input', 'borkenSpec.js', 42, undefined, {stack: 'a stack'}); + global.onerror('Uncaught Error: ENOCHEESE'); + + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.failedExpectations).toEqual([ { passed: false, @@ -2169,12 +2035,6 @@ describe("Env integration", function() { done(); }); - - env.addReporter(reporter); - global.onerror('Uncaught SyntaxError: Unexpected end of input', 'borkenSpec.js', 42, undefined, {stack: 'a stack'}); - global.onerror('Uncaught Error: ENOCHEESE'); - - env.execute(); }); describe('If suppressLoadErrors: true was passed', function() { @@ -2195,16 +2055,15 @@ describe("Env integration", function() { env = new jasmineUnderTest.Env({suppressLoadErrors: true}); var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { + env.addReporter(reporter); + global.onerror('Uncaught Error: ENOCHEESE'); + + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.failedExpectations).toEqual([]); expect(originalOnerror).toHaveBeenCalledWith('Uncaught Error: ENOCHEESE'); done(); }); - - env.addReporter(reporter); - global.onerror('Uncaught Error: ENOCHEESE'); - - env.execute(); }); }); @@ -2213,14 +2072,13 @@ describe("Env integration", function() { it('is "passed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { + env.addReporter(reporter); + env.it('passes', function() {}); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.overallStatus).toEqual('passed'); done(); }); - - env.addReporter(reporter); - env.it('passes', function() {}); - env.execute(); }); }); @@ -2228,16 +2086,15 @@ describe("Env integration", function() { it('is "failed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('failed'); - done(); - }); - env.addReporter(reporter); env.it('fails', function() { env.expect(true).toBe(false); }); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('failed'); + done(); + }) }); }); @@ -2255,23 +2112,21 @@ describe("Env integration", function() { }); it('should report "failed" status if "failSpecWithNoExpectations" is enabled', function(done) { - reporter.jasmineDone.and.callFake(function(e) { + env.configure({ failSpecWithNoExpectations: true }); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.overallStatus).toEqual('failed'); done(); }); - - env.configure({ failSpecWithNoExpectations: true }); - env.execute(); }); it('should report "passed" status if "failSpecWithNoExpectations" is disabled', function(done) { - reporter.jasmineDone.and.callFake(function(e) { + env.configure({ failSpecWithNoExpectations: false }); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.overallStatus).toEqual('passed'); done(); }); - - env.configure({ failSpecWithNoExpectations: false }); - env.execute(); }); }); @@ -2279,17 +2134,16 @@ describe("Env integration", function() { it('is "failed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('failed'); - done(); - }); - env.addReporter(reporter); env.beforeAll(function() { throw new Error('nope'); }); env.it('does not run', function() {}); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('failed'); + done(); + }); }); }); @@ -2297,11 +2151,6 @@ describe("Env integration", function() { it('is "failed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('failed'); - done(); - }); - env.addReporter(reporter); env.describe('something', function() { env.beforeAll(function() { @@ -2309,7 +2158,11 @@ describe("Env integration", function() { }); env.it('does not run', function() {}); }); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('failed'); + done(); + }); }); }); @@ -2317,17 +2170,16 @@ describe("Env integration", function() { it('is "failed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('failed'); - done(); - }); - env.addReporter(reporter); env.afterAll(function() { throw new Error('nope'); }); env.it('does not run', function() {}); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('failed'); + done(); + }); }); }); @@ -2335,11 +2187,6 @@ describe("Env integration", function() { it('is "failed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('failed'); - done(); - }); - env.addReporter(reporter); env.describe('something', function() { env.afterAll(function() { @@ -2347,7 +2194,11 @@ describe("Env integration", function() { }); env.it('does not run', function() {}); }); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('failed'); + done(); + }); }); }); @@ -2365,13 +2216,15 @@ describe("Env integration", function() { reporter.jasmineDone.and.callFake(function(e) { expect(e.overallStatus).toEqual('failed'); - done(); }); env.addReporter(reporter); env.it('passes', function() {}); global.onerror('Uncaught Error: ENOCHEESE'); - env.execute(); + env.execute(null, function() { + expect(reporter.jasmineDone).toHaveBeenCalled(); + done(); + }); }); }); @@ -2379,14 +2232,13 @@ describe("Env integration", function() { it('is "incomplete"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { + env.addReporter(reporter); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.overallStatus).toEqual('incomplete'); expect(e.incompleteReason).toEqual('No specs found'); done(); }); - - env.addReporter(reporter); - env.execute(); }); }); @@ -2394,15 +2246,14 @@ describe("Env integration", function() { it('is "incomplete"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { + env.addReporter(reporter); + env.fit('is focused', function() {}); + env.execute(null, function(e) { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; expect(e.overallStatus).toEqual('incomplete'); expect(e.incompleteReason).toEqual('fit() or fdescribe() was found'); done(); }); - - env.addReporter(reporter); - env.fit('is focused', function() {}); - env.execute(); }); }); @@ -2410,17 +2261,16 @@ describe("Env integration", function() { it('is "incomplete"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('incomplete'); - expect(e.incompleteReason).toEqual('fit() or fdescribe() was found'); - done(); - }); - env.addReporter(reporter); env.fdescribe('something focused', function() { env.it('does a thing', function() {}); }); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('incomplete'); + expect(e.incompleteReason).toEqual('fit() or fdescribe() was found'); + done(); + }); }); }); @@ -2428,17 +2278,16 @@ describe("Env integration", function() { it('is "failed"', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - reporter.jasmineDone.and.callFake(function(e) { - expect(e.overallStatus).toEqual('failed'); - expect(e.incompleteReason).toBeUndefined(); - done(); - }); - env.addReporter(reporter); env.fit('is focused', function() { env.expect(true).toBe(false); }); - env.execute(); + env.execute(null, function() { + var e = reporter.jasmineDone.calls.argsFor(0)[0]; + expect(e.overallStatus).toEqual('failed'); + expect(e.incompleteReason).toBeUndefined(); + done(); + }); }); }); }); @@ -2449,7 +2298,22 @@ describe("Env integration", function() { // prevent deprecation from being displayed spyOn(console, "error"); - reporter.jasmineDone.and.callFake(function(result) { + env.addReporter(reporter); + + env.deprecated('top level deprecation'); + + env.describe('suite', function() { + env.beforeAll(function() { + env.deprecated('suite level deprecation'); + }); + + env.it('spec', function() { + env.deprecated('spec level deprecation'); + }); + }); + + env.execute(null, function() { + var result = reporter.jasmineDone.calls.argsFor(0)[0]; expect(result.deprecationWarnings).toEqual([ jasmine.objectContaining({ message: 'top level deprecation' }) ]); @@ -2470,22 +2334,6 @@ describe("Env integration", function() { done(); }); - - env.addReporter(reporter); - - env.deprecated('top level deprecation'); - - env.describe('suite', function() { - env.beforeAll(function() { - env.deprecated('suite level deprecation'); - }); - - env.it('spec', function() { - env.deprecated('spec level deprecation'); - }); - }); - - env.execute(); }); it('should report deprecation stack with an error object', function(done) { @@ -2500,7 +2348,22 @@ describe("Env integration", function() { // prevent deprecation from being displayed spyOn(console, "error"); - reporter.jasmineDone.and.callFake(function(result) { + env.addReporter(reporter); + + env.deprecated(topLevelError); + + env.describe('suite', function() { + env.beforeAll(function() { + env.deprecated(suiteLevelError); + }); + + env.it('spec', function() { + env.deprecated(specLevelError); + }); + }); + + env.execute(null, function() { + var result = reporter.jasmineDone.calls.argsFor(0)[0]; expect(result.deprecationWarnings).toEqual([ jasmine.objectContaining({ message: topLevelError.message, @@ -2530,54 +2393,19 @@ describe("Env integration", function() { done(); }); - - env.addReporter(reporter); - - env.deprecated(topLevelError); - - env.describe('suite', function() { - env.beforeAll(function() { - env.deprecated(suiteLevelError); - }); - - env.it('spec', function() { - env.deprecated(specLevelError); - }); - }); - - env.execute(); }); it('supports async matchers', function(done) { jasmine.getEnv().requirePromises(); var specDone = jasmine.createSpy('specDone'), - suiteDone = jasmine.createSpy('suiteDone'); + suiteDone = jasmine.createSpy('suiteDone'), + jasmineDone = jasmine.createSpy('jasmineDone'); env.addReporter({ specDone: specDone, suiteDone: suiteDone, - jasmineDone: function(result) { - expect(result.failedExpectations).toEqual([jasmine.objectContaining({ - message: 'Expected [object Promise] to be rejected.' - })]); - - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'has an async failure', - failedExpectations: [jasmine.objectContaining({ - message: 'Expected [object Promise] to be rejected.' - })] - })); - - expect(suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'a suite', - failedExpectations: [jasmine.objectContaining({ - message: 'Expected [object Promise] to be rejected.' - })] - })); - - done(); - } + jasmineDone: jasmineDone }); function fail(innerDone) { @@ -2593,7 +2421,28 @@ describe("Env integration", function() { env.it('has an async failure', fail); }); - env.execute(); + env.execute(null, function() { + var result = jasmineDone.calls.argsFor(0)[0]; + expect(result.failedExpectations).toEqual([jasmine.objectContaining({ + message: 'Expected [object Promise] to be rejected.' + })]); + + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'has an async failure', + failedExpectations: [jasmine.objectContaining({ + message: 'Expected [object Promise] to be rejected.' + })] + })); + + expect(suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'a suite', + failedExpectations: [jasmine.objectContaining({ + message: 'Expected [object Promise] to be rejected.' + })] + })); + + done(); + }); }); it('provides custom equality testers to async matchers', function(done) { @@ -2601,16 +2450,7 @@ describe("Env integration", function() { var specDone = jasmine.createSpy('specDone'); - env.addReporter({ - specDone: specDone, - jasmineDone: function() { - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - description: 'has an async failure', - failedExpectations: [] - })); - done(); - } - }); + env.addReporter({specDone: specDone}); env.it('has an async failure', function() { env.addCustomEqualityTester(function() { return true; }); @@ -2618,7 +2458,13 @@ describe("Env integration", function() { return env.expectAsync(p).toBeResolvedTo('something else'); }); - env.execute(); + env.execute(null, function() { + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + description: 'has an async failure', + failedExpectations: [] + })); + done(); + }); }); it('includes useful stack frames in async matcher failures', function(done) { @@ -2626,17 +2472,7 @@ describe("Env integration", function() { var specDone = jasmine.createSpy('specDone'); - env.addReporter({ - specDone: specDone, - jasmineDone: function() { - expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ - failedExpectations: [jasmine.objectContaining({ - stack: jasmine.stringMatching('EnvSpec.js') - })] - })); - done(); - } - }); + env.addReporter({specDone: specDone}); env.it('has an async failure', function() { env.addCustomEqualityTester(function() { return true; }); @@ -2644,13 +2480,21 @@ describe("Env integration", function() { return env.expectAsync(p).toBeRejected(); }); - env.execute(); + env.execute(null, function() { + expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({ + failedExpectations: [jasmine.objectContaining({ + stack: jasmine.stringMatching('EnvSpec.js') + })] + })); + done(); + }); }); it('reports an error when an async expectation occurs after the spec finishes', function(done) { jasmine.getEnv().requirePromises(); var resolve, + jasmineDone = jasmine.createSpy('jasmineDone'), promise = new Promise(function(res) { resolve = res; }); // eslint-disable-line compat/compat env.describe('a suite', function() { @@ -2666,39 +2510,41 @@ describe("Env integration", function() { specDone: function() { resolve(); }, - jasmineDone: function (result) { - expect(result.failedExpectations).toEqual([ - jasmine.objectContaining({ - passed: false, - globalErrorType: 'lateExpectation', - message: 'Spec "a suite does not wait" ran a "toBeResolved" expectation ' + - 'after it finished.\n' + - 'Did you forget to return or await the result of expectAsync?', - matcherName: 'toBeResolved' - }), - jasmine.objectContaining({ - passed: false, - globalErrorType: 'lateExpectation', - message: 'Spec "a suite does not wait" ran a "toBeResolvedTo" expectation ' + - 'after it finished.\n' + - 'Message: "Expected a promise to be resolved to \'something else\' ' + - 'but it was resolved to undefined."\n' + - 'Did you forget to return or await the result of expectAsync?', - matcherName: 'toBeResolvedTo' - }) - ]); - - done(); - } + jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, function () { + var result = jasmineDone.calls.argsFor(0)[0]; + expect(result.failedExpectations).toEqual([ + jasmine.objectContaining({ + passed: false, + globalErrorType: 'lateExpectation', + message: 'Spec "a suite does not wait" ran a "toBeResolved" expectation ' + + 'after it finished.\n' + + 'Did you forget to return or await the result of expectAsync?', + matcherName: 'toBeResolved' + }), + jasmine.objectContaining({ + passed: false, + globalErrorType: 'lateExpectation', + message: 'Spec "a suite does not wait" ran a "toBeResolvedTo" expectation ' + + 'after it finished.\n' + + 'Message: "Expected a promise to be resolved to \'something else\' ' + + 'but it was resolved to undefined."\n' + + 'Did you forget to return or await the result of expectAsync?', + matcherName: 'toBeResolvedTo' + }) + ]); + + done(); + }); }); it('reports an error when an async expectation occurs after the suite finishes', function(done) { jasmine.getEnv().requirePromises(); var resolve, + jasmineDone = jasmine.createSpy('jasmineDone'), promise = new Promise(function(res) { resolve = res; }); // eslint-disable-line compat/compat env.describe('a suite', function() { @@ -2715,23 +2561,24 @@ describe("Env integration", function() { suiteDone: function() { resolve(); }, - jasmineDone: function (result) { - expect(result.failedExpectations).toEqual([ - jasmine.objectContaining({ - passed: false, - globalErrorType: 'lateExpectation', - message: 'Suite "a suite" ran a "toBeResolved" expectation ' + - 'after it finished.\n' + - 'Did you forget to return or await the result of expectAsync?', - matcherName: 'toBeResolved' - }) - ]); - - done(); - } + jasmineDone: jasmineDone }); - env.execute(); + env.execute(null, function () { + var result = jasmineDone.calls.argsFor(0)[0]; + expect(result.failedExpectations).toEqual([ + jasmine.objectContaining({ + passed: false, + globalErrorType: 'lateExpectation', + message: 'Suite "a suite" ran a "toBeResolved" expectation ' + + 'after it finished.\n' + + 'Did you forget to return or await the result of expectAsync?', + matcherName: 'toBeResolved' + }) + ]); + + done(); + }); }); it("supports asymmetric equality testers that take a matchersUtil", function(done) { @@ -2759,7 +2606,89 @@ describe("Env integration", function() { expect(result.status).toEqual('passed'); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); + }); + + describe('The optional callback argument to #execute', function() { + beforeEach(function() { + this.savedInterval = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL; + }); + + afterEach(function() { + jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = this.savedInterval; + }); + + it('is called after reporter events are dispatched', function(done) { + var reporter = jasmine.createSpyObj( + 'reporter', + ['specDone', 'suiteDone', 'jasmineDone'] + ); + + env.addReporter(reporter); + env.describe('suite', function () { + env.it('spec', function() {}); + }); + + env.execute(null, function() { + expect(reporter.specDone).toHaveBeenCalled(); + expect(reporter.suiteDone).toHaveBeenCalled(); + expect(reporter.jasmineDone).toHaveBeenCalled(); + done(); + }); + }); + + it('is called after the stack is cleared', function(done) { + var realClearStack = jasmineUnderTest.getClearStack(jasmineUnderTest.getGlobal()), + clearStackSpy = jasmine.createSpy('clearStack').and.callFake(realClearStack); + spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(clearStackSpy); + + // Create a new env that has the clearStack defined above + env.cleanup_(); + env = new jasmineUnderTest.Env(); + + env.describe('suite', function () { + env.it('spec', function() {}); + }); + + env.execute(null, function() { + expect(clearStackSpy).toHaveBeenCalled(); // (many times) + clearStackSpy.calls.reset(); + setTimeout(function() { + expect(clearStackSpy).not.toHaveBeenCalled(); + done(); + }); + }); + }); + + it('is called after QueueRunner timeouts are cleared', function(done) { + var setTimeoutSpy = spyOn(jasmineUnderTest.getGlobal(), 'setTimeout') + .and.callThrough(); + var clearTimeoutSpy = spyOn(jasmineUnderTest.getGlobal(), 'clearTimeout') + .and.callThrough(); + + jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 123456; // a distinctive value + + env = new jasmineUnderTest.Env(); + + env.describe('suite', function () { + env.it('spec', function () { + }); + }); + + env.execute(null, function () { + var timeoutIds = setTimeoutSpy.calls.all() + .filter(function(call) { return call.args[1] === 123456; }) + .map(function(call) { return call.returnValue; }); + + expect(timeoutIds.length).toBeGreaterThan(0); + + timeoutIds.forEach(function(timeoutId) { + expect(clearTimeoutSpy).toHaveBeenCalledWith(timeoutId); + }); + + done(); + }); + }); }); }); diff --git a/spec/core/integration/MatchersSpec.js b/spec/core/integration/MatchersSpec.js index 92b7307f..8174faf8 100644 --- a/spec/core/integration/MatchersSpec.js +++ b/spec/core/integration/MatchersSpec.js @@ -28,8 +28,8 @@ describe('Matchers (Integration)', function() { .toBeUndefined(); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); } @@ -54,8 +54,8 @@ describe('Matchers (Integration)', function() { .not.toEqual(''); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); } @@ -75,8 +75,8 @@ describe('Matchers (Integration)', function() { .toEqual(config.expectedMessage); }; - env.addReporter({specDone: specExpectations, jasmineDone: done}); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); } @@ -101,8 +101,8 @@ describe('Matchers (Integration)', function() { .toBeUndefined(); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); } @@ -126,8 +126,8 @@ describe('Matchers (Integration)', function() { .not.toEqual(''); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); } @@ -149,8 +149,8 @@ describe('Matchers (Integration)', function() { .toEqual(config.expectedMessage); }; - env.addReporter({specDone: specExpectations, jasmineDone: done}); - env.execute(); + env.addReporter({ specDone: specExpectations }); + env.execute(null, done); }); } diff --git a/spec/core/integration/SpecRunningSpec.js b/spec/core/integration/SpecRunningSpec.js index d522cf86..33459d02 100644 --- a/spec/core/integration/SpecRunningSpec.js +++ b/spec/core/integration/SpecRunningSpec.js @@ -66,17 +66,14 @@ describe("spec running", function () { expect(bar).toEqual(0); expect(baz).toEqual(0); expect(quux).toEqual(0); - var assertions = function() { + + env.execute(null, function() { expect(foo).toEqual(1); expect(bar).toEqual(1); expect(baz).toEqual(1); expect(quux).toEqual(1); done(); - }; - - env.addReporter({ jasmineDone: assertions }); - - env.execute(); + }); }); it("should permit nested describes", function(done) { @@ -136,7 +133,7 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = [ "topSuite beforeEach", "outer beforeEach", @@ -168,11 +165,7 @@ describe("spec running", function () { ]; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("should run multiple befores and afters ordered so functions declared later are treated as more specific", function(done) { @@ -232,7 +225,7 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = [ "runner beforeAll1", "runner beforeAll2", @@ -250,11 +243,7 @@ describe("spec running", function () { ]; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it('should run beforeAlls before beforeEachs and afterAlls after afterEachs', function(done) { @@ -298,7 +287,7 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = [ "runner beforeAll", "inner beforeAll", @@ -312,10 +301,7 @@ describe("spec running", function () { ]; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute(); + }); }); it('should run beforeAlls and afterAlls in the order declared when runnablesToRun is provided', function(done) { @@ -365,7 +351,7 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute([spec2.id, spec.id], function() { var expected = [ "runner beforeAll", "inner beforeAll", @@ -385,10 +371,7 @@ describe("spec running", function () { ]; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute([spec2.id, spec.id]); + }); }); it('only runs *Alls once in a focused suite', function(done){ @@ -406,13 +389,10 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual(['beforeAll', 'spec', 'afterAll']); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute(); + }); }); describe('focused runnables', function() { @@ -435,7 +415,7 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = [ 'beforeAll', 'beforeEach', @@ -449,10 +429,7 @@ describe("spec running", function () { ]; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute(); + }); }); it('focused specs in focused suites cause non-focused siblings to not run', function(done){ @@ -467,14 +444,11 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = ['focused spec']; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute(); + }); }); it('focused suites in focused suites cause non-focused siblings to not run', function(done){ @@ -491,14 +465,11 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = ['inner spec']; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute(); + }); }); it('focused runnables unfocus ancestor focused suites', function(done) { @@ -515,14 +486,11 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = ['focused spec']; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - env.execute(); + }); }); }); @@ -534,14 +502,10 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { expect(specInADisabledSuite).not.toHaveBeenCalled(); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("shouldn't run before/after functions in disabled suites", function(done) { @@ -556,14 +520,10 @@ describe("spec running", function () { env.it('spec inside a disabled suite', shouldNotRun); }); - var assertions = function() { + env.execute(null, function() { expect(shouldNotRun).not.toHaveBeenCalled(); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("should allow top level suites to be disabled", function(done) { @@ -577,15 +537,11 @@ describe("spec running", function () { env.it('another spec', otherSpec); }); - var assertions = function() { + env.execute(null, function() { expect(specInADisabledSuite).not.toHaveBeenCalled(); expect(otherSpec).toHaveBeenCalled(); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("should set all pending specs to pending when a suite is run", function(done) { @@ -594,31 +550,20 @@ describe("spec running", function () { pendingSpec = env.it("I am a pending spec"); }); - var assertions = function() { + env.execute(null, function() { expect(pendingSpec.status()).toBe("pending"); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("should recover gracefully when there are errors in describe functions", function(done) { var specs = [], - reporter = jasmine.createSpyObj(['specDone', 'suiteDone', 'jasmineDone']); + reporter = jasmine.createSpyObj(['specDone', 'suiteDone']); reporter.specDone.and.callFake(function(result) { specs.push(result.fullName); }); - reporter.jasmineDone.and.callFake(function() { - expect(specs).toEqual(['outer1 inner1 should thingy', 'outer1 inner2 should other thingy', 'outer2 should xxx']); - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1 inner1', [/inner error/]); - expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1', [/outer error/]); - done(); - }); - expect(function() { env.describe("outer1", function() { env.describe("inner1", function() { @@ -647,7 +592,12 @@ describe("spec running", function () { }); env.addReporter(reporter); - env.execute(); + env.execute(null, function() { + expect(specs).toEqual(['outer1 inner1 should thingy', 'outer1 inner2 should other thingy', 'outer2 should xxx']); + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1 inner1', [/inner error/]); + expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1', [/outer error/]); + done(); + }); }); it("re-enters suites that have no *Alls", function(done) { @@ -668,14 +618,10 @@ describe("spec running", function () { actions.push("spec3"); }); - env.addReporter({ - jasmineDone: function() { - expect(actions).toEqual(["spec2", "spec3", "spec1"]); - done(); - } + env.execute([spec2.id, spec3.id, spec1.id], function() { + expect(actions).toEqual(["spec2", "spec3", "spec1"]); + done(); }); - - env.execute([spec2.id, spec3.id, spec1.id]); }); it("refuses to re-enter suites with a beforeAll", function() { @@ -698,16 +644,10 @@ describe("spec running", function () { actions.push("spec3"); }); - env.addReporter({ - jasmineDone: function() { - expect(actions).toEqual([]); - done(); - } - }); - expect(function() { env.execute([spec2.id, spec3.id, spec1.id]); }).toThrowError(/beforeAll/); + expect(actions).toEqual([]); }); it("refuses to re-enter suites with a afterAll", function() { @@ -730,16 +670,10 @@ describe("spec running", function () { actions.push("spec3"); }); - env.addReporter({ - jasmineDone: function() { - expect(actions).toEqual([]); - done(); - } - }); - expect(function() { env.execute([spec2.id, spec3.id, spec1.id]); }).toThrowError(/afterAll/); + expect(actions).toEqual([]); }); it("should run the tests in a consistent order when a seed is supplied", function(done) { @@ -800,7 +734,7 @@ describe("spec running", function () { }); }); - var assertions = function() { + env.execute(null, function() { var expected = [ 'topSuite beforeEach', 'outer beforeEach', @@ -832,11 +766,7 @@ describe("spec running", function () { ]; expect(actions).toEqual(expected); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); describe("When throwOnExpectationFailure is set", function() { @@ -870,18 +800,14 @@ describe("spec running", function () { env.configure({oneFailurePerSpec: true}); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual([ 'outer beforeEach', 'inner afterEach', 'outer afterEach' ]); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("skips to cleanup functions after done.fail is called", function(done) { @@ -905,17 +831,13 @@ describe("spec running", function () { env.configure({oneFailurePerSpec: true}); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual([ 'beforeEach', 'afterEach' ]); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("skips to cleanup functions when an async function times out", function(done) { @@ -937,17 +859,13 @@ describe("spec running", function () { env.configure({oneFailurePerSpec: true}); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual([ 'beforeEach', 'afterEach' ]); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("skips to cleanup functions after an error with deprecations", function(done) { @@ -982,7 +900,7 @@ describe("spec running", function () { env.throwOnExpectationFailure(true); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual([ 'outer beforeEach', 'inner afterEach', @@ -990,11 +908,7 @@ describe("spec running", function () { ]); expect(env.deprecated).toHaveBeenCalled(); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("skips to cleanup functions after done.fail is called with deprecations", function(done) { @@ -1020,18 +934,14 @@ describe("spec running", function () { env.throwOnExpectationFailure(true); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual([ 'beforeEach', 'afterEach' ]); expect(env.deprecated).toHaveBeenCalled(); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); it("skips to cleanup functions when an async function times out with deprecations", function(done) { @@ -1055,18 +965,14 @@ describe("spec running", function () { env.throwOnExpectationFailure(true); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual([ 'beforeEach', 'afterEach' ]); expect(env.deprecated).toHaveBeenCalled(); done(); - }; - - env.addReporter({jasmineDone: assertions}); - - env.execute(); + }); }); }); @@ -1089,13 +995,10 @@ describe("spec running", function () { env.configure({random: false, failFast: true}); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual(['fails']); done(); - }; - - env.addReporter({ jasmineDone: assertions }); - env.execute(); + }); }); it("does not run further specs when one fails when configured with deprecated option", function(done) { @@ -1119,14 +1022,11 @@ describe("spec running", function () { env.configure({random: false}); env.stopOnSpecFailure(true); - var assertions = function() { + env.execute(null, function() { expect(actions).toEqual(['fails']); expect(env.deprecated).toHaveBeenCalled(); done(); - }; - - env.addReporter({ jasmineDone: assertions }); - env.execute(); + }); }); }); }); diff --git a/src/core/Env.js b/src/core/Env.js index d7fdd4c0..7e299717 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -705,7 +705,8 @@ getJasmineRequireObj().Env = function(j$) { queueRunnerFactory ); - this.execute = function(runnablesToRun) { + // Both params are optional. + this.execute = function(runnablesToRun, onComplete) { installGlobalErrors(); if (!runnablesToRun) { @@ -813,7 +814,11 @@ getJasmineRequireObj().Env = function(j$) { failedExpectations: topSuite.result.failedExpectations, deprecationWarnings: topSuite.result.deprecationWarnings }, - function() {} + function() { + if (onComplete) { + onComplete(); + } + } ); }); } diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index 28c1153f..df383632 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -1,4 +1,6 @@ getJasmineRequireObj().QueueRunner = function(j$) { + var nextid = 1; + function StopExecutionError() {} StopExecutionError.prototype = new Error(); j$.StopExecutionError = StopExecutionError; @@ -18,6 +20,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { function emptyFn() {} function QueueRunner(attrs) { + this.id_ = nextid++; var queueableFns = attrs.queueableFns || []; this.queueableFns = queueableFns.concat(attrs.cleanupFns || []); this.firstCleanupIx = queueableFns.length; From 0b81705c112cb7d2b9da03112123174ed7f25841 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Wed, 2 Sep 2020 14:43:17 -0700 Subject: [PATCH 54/57] Detect global error handler stack corruption --- lib/jasmine-core/jasmine.js | 12 +++++++++++- spec/core/GlobalErrorsSpec.js | 19 ++++++++++++++++++- spec/core/integration/EnvSpec.js | 1 - src/core/GlobalErrors.js | 12 +++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 8b449d97..fb91318e 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -4117,7 +4117,17 @@ getJasmineRequireObj().GlobalErrors = function(j$) { handlers.push(listener); }; - this.popListener = function popListener() { + this.popListener = function popListener(listener) { + if (!listener) { + throw new Error('popListener expects a listener'); + } + + if (listener !== handlers[handlers.length - 1]) { + throw new Error( + 'popListener was passed a different listener than the current one' + ); + } + handlers.pop(); }; } diff --git a/spec/core/GlobalErrorsSpec.js b/spec/core/GlobalErrorsSpec.js index 3effa537..16657a7f 100644 --- a/spec/core/GlobalErrorsSpec.js +++ b/spec/core/GlobalErrorsSpec.js @@ -58,7 +58,7 @@ describe('GlobalErrors', function() { errors.pushListener(handler1); errors.pushListener(handler2); - errors.popListener(); + errors.popListener(handler2); fakeGlobal.onerror('foo'); @@ -66,6 +66,23 @@ describe('GlobalErrors', function() { expect(handler2).not.toHaveBeenCalled(); }); + it('throws when no listener is passed to #popListener', function() { + var errors = new jasmineUnderTest.GlobalErrors({}); + expect(function() { + errors.popListener(); + }).toThrowError('popListener expects a listener'); + }); + + it('throws when the argument to #popListener is not the current listener', function() { + var errors = new jasmineUnderTest.GlobalErrors({}); + errors.pushListener(function() {}); + expect(function() { + errors.popListener(function() {}); + }).toThrowError( + 'popListener was passed a different listener than the current one' + ); + }); + it('uninstalls itself, putting back a previous callback', function() { var originalCallback = jasmine.createSpy('error'), fakeGlobal = { onerror: originalCallback }, diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index cf1e997d..b51a7297 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -974,7 +974,6 @@ describe("Env integration", function() { env.execute(null, function() { expect(delayedFunctionForMockClock).toHaveBeenCalled(); expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100); - done(); }); }); diff --git a/src/core/GlobalErrors.js b/src/core/GlobalErrors.js index 282eb262..b79976d9 100644 --- a/src/core/GlobalErrors.js +++ b/src/core/GlobalErrors.js @@ -96,7 +96,17 @@ getJasmineRequireObj().GlobalErrors = function(j$) { handlers.push(listener); }; - this.popListener = function popListener() { + this.popListener = function popListener(listener) { + if (!listener) { + throw new Error('popListener expects a listener'); + } + + if (listener !== handlers[handlers.length - 1]) { + throw new Error( + 'popListener was passed a different listener than the current one' + ); + } + handlers.pop(); }; } From 51ad18cb2814e6ed04b266e34526674f53703aba Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 12 Sep 2020 20:34:21 -0700 Subject: [PATCH 55/57] Warn if a runable both takes a callback and returns a promise --- lib/jasmine-core/jasmine.js | 27 ++++++++++++++++++++--- spec/core/QueueRunnerSpec.js | 42 ++++++++++++++++++++++++++++++++++++ src/core/QueueRunner.js | 27 ++++++++++++++++++++--- 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index fb91318e..71194eeb 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -7056,7 +7056,8 @@ getJasmineRequireObj().QueueRunner = function(j$) { }), errored = false, queueableFn = self.queueableFns[iterativeIndex], - timeoutId; + timeoutId, + maybeThenable; next.fail = function nextFail() { self.fail.apply(null, arguments); @@ -7084,7 +7085,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { try { if (queueableFn.fn.length === 0) { - var maybeThenable = queueableFn.fn.call(self.userContext); + maybeThenable = queueableFn.fn.call(self.userContext); if (maybeThenable && j$.isFunction_(maybeThenable.then)) { maybeThenable.then(next, onPromiseRejection); @@ -7092,7 +7093,8 @@ getJasmineRequireObj().QueueRunner = function(j$) { return { completedSynchronously: false }; } } else { - queueableFn.fn.call(self.userContext, next); + maybeThenable = queueableFn.fn.call(self.userContext, next); + this.diagnoseConflictingAsync_(queueableFn.fn, maybeThenable); completedSynchronously = false; return { completedSynchronously: false }; } @@ -7145,6 +7147,25 @@ getJasmineRequireObj().QueueRunner = function(j$) { }); }; + QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) { + if (retval && j$.isFunction_(retval.then)) { + // Issue a warning that matches the user's code + if (j$.isAsyncFunction_(fn)) { + this.deprecated('An asynchronous before/it/after ' + + 'function was defined with the async keyword but also took a ' + + 'done callback. This is not supported and will stop working in' + + ' the future. Either remove the done callback (recommended) or ' + + 'remove the async keyword.'); + } else { + this.deprecated('An asynchronous before/it/after ' + + 'function took a done callback but also returned a promise. ' + + 'This is not supported and will stop working in the future. ' + + 'Either remove the done callback (recommended) or change the ' + + 'function to not return a promise.'); + } + } + }; + return QueueRunner; }; diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index ac18b81d..c722aaff 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -512,6 +512,48 @@ describe('QueueRunner', function() { expect(onExceptionCallback).toHaveBeenCalledWith('foo'); expect(queueableFn2.fn).toHaveBeenCalled(); }); + + it('issues a deprecation if the function also takes a parameter', function() { + var queueableFn = { + fn: function(done) { + return new StubPromise(); + } + }, + deprecated = jasmine.createSpy('deprecated'), + queueRunner = new jasmineUnderTest.QueueRunner({ + queueableFns: [queueableFn], + deprecated: deprecated + }), + env = jasmineUnderTest.getEnv(); + + queueRunner.execute(); + + expect(deprecated).toHaveBeenCalledWith('An asynchronous ' + + 'before/it/after function took a done callback but also returned a '+ + 'promise. This is not supported and will stop working in the future. ' + + 'Either remove the done callback (recommended) or change the function ' + + 'to not return a promise.' + ); + }); + + it('issues a more specific deprecation if the function is `async`', function() { + jasmine.getEnv().requireAsyncAwait(); + eval('var fn = async function(done){};'); + var deprecated = jasmine.createSpy('deprecated'), + queueRunner = new jasmineUnderTest.QueueRunner({ + queueableFns: [{fn: fn}], + deprecated: deprecated + }); + + queueRunner.execute(); + + expect(deprecated).toHaveBeenCalledWith('An asynchronous ' + + 'before/it/after function was defined with the async keyword but ' + + 'also took a done callback. This is not supported and will stop ' + + 'working in the future. Either remove the done callback ' + + '(recommended) or remove the async keyword.' + ); + }); }); it('passes the error instance to exception handlers in HTML browsers', function() { diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index df383632..f009c3b5 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -123,7 +123,8 @@ getJasmineRequireObj().QueueRunner = function(j$) { }), errored = false, queueableFn = self.queueableFns[iterativeIndex], - timeoutId; + timeoutId, + maybeThenable; next.fail = function nextFail() { self.fail.apply(null, arguments); @@ -151,7 +152,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { try { if (queueableFn.fn.length === 0) { - var maybeThenable = queueableFn.fn.call(self.userContext); + maybeThenable = queueableFn.fn.call(self.userContext); if (maybeThenable && j$.isFunction_(maybeThenable.then)) { maybeThenable.then(next, onPromiseRejection); @@ -159,7 +160,8 @@ getJasmineRequireObj().QueueRunner = function(j$) { return { completedSynchronously: false }; } } else { - queueableFn.fn.call(self.userContext, next); + maybeThenable = queueableFn.fn.call(self.userContext, next); + this.diagnoseConflictingAsync_(queueableFn.fn, maybeThenable); completedSynchronously = false; return { completedSynchronously: false }; } @@ -212,5 +214,24 @@ getJasmineRequireObj().QueueRunner = function(j$) { }); }; + QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) { + if (retval && j$.isFunction_(retval.then)) { + // Issue a warning that matches the user's code + if (j$.isAsyncFunction_(fn)) { + this.deprecated('An asynchronous before/it/after ' + + 'function was defined with the async keyword but also took a ' + + 'done callback. This is not supported and will stop working in' + + ' the future. Either remove the done callback (recommended) or ' + + 'remove the async keyword.'); + } else { + this.deprecated('An asynchronous before/it/after ' + + 'function took a done callback but also returned a promise. ' + + 'This is not supported and will stop working in the future. ' + + 'Either remove the done callback (recommended) or change the ' + + 'function to not return a promise.'); + } + } + }; + return QueueRunner; }; From e7daa429a1808dc1b4a672d745133d1f3f826e2d Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sun, 13 Sep 2020 12:39:42 -0700 Subject: [PATCH 56/57] Show the name of the spec/suite that caused a deprecation --- lib/jasmine-core/jasmine-html.js | 35 ++++++++++++++++++++++++------- lib/jasmine-core/jasmine.js | 36 ++++++++++++++++++++++---------- spec/core/QueueRunnerSpec.js | 24 +++++++++++---------- spec/core/integration/EnvSpec.js | 5 ++++- spec/html/HtmlReporterSpec.js | 11 ++++++++-- src/core/Env.js | 12 ++++++++++- src/core/QueueRunner.js | 24 ++++++++++++--------- src/html/HtmlReporter.js | 35 ++++++++++++++++++++++++------- 8 files changed, 130 insertions(+), 52 deletions(-) diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index 307f20e0..26ae6ac9 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -132,7 +132,7 @@ jasmineRequire.HtmlReporter = function(j$) { if (result.status === 'failed') { failures.push(failureDom(result)); } - addDeprecationWarnings(result); + addDeprecationWarnings(result, 'suite'); }; this.specStarted = function(result) { @@ -168,7 +168,7 @@ jasmineRequire.HtmlReporter = function(j$) { failures.push(failureDom(result)); } - addDeprecationWarnings(result); + addDeprecationWarnings(result, 'spec'); }; this.displaySpecInCorrectFormat = function(result) { @@ -307,14 +307,27 @@ jasmineRequire.HtmlReporter = function(j$) { addDeprecationWarnings(doneResult); - var warningBarClassName = 'jasmine-bar jasmine-warning'; for (i = 0; i < deprecationWarnings.length; i++) { - var warning = deprecationWarnings[i]; + var context; + + switch (deprecationWarnings[i].runnableType) { + case 'spec': + context = '(in spec: ' + deprecationWarnings[i].runnableName + ')'; + break; + case 'suite': + context = '(in suite: ' + deprecationWarnings[i].runnableName + ')'; + break; + default: + context = ''; + } + alert.appendChild( createDom( 'span', - { className: warningBarClassName }, - 'DEPRECATION: ' + warning + { className: 'jasmine-bar jasmine-warning' }, + 'DEPRECATION: ' + deprecationWarnings[i].message, + createDom('br'), + context ) ); } @@ -625,12 +638,18 @@ jasmineRequire.HtmlReporter = function(j$) { return addToExistingQueryString('spec', els.join(' ')); } - function addDeprecationWarnings(result) { + function addDeprecationWarnings(result, runnableType) { if (result && result.deprecationWarnings) { for (var i = 0; i < result.deprecationWarnings.length; i++) { var warning = result.deprecationWarnings[i].message; + debugger; if (!j$.util.arrayContains(warning)) { - deprecationWarnings.push(warning); + debugger; + deprecationWarnings.push({ + message: warning, + runnableName: result.fullName, + runnableType: runnableType + }); } } } diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 71194eeb..f86e9f55 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1537,12 +1537,22 @@ getJasmineRequireObj().Env = function(j$) { this.deprecated = function(deprecation) { var runnable = currentRunnable() || topSuite; + var context; + + if (runnable === topSuite) { + context = ''; + } else if (runnable === currentSuite()) { + context = ' (in suite: ' + runnable.getFullName() + ')'; + } else { + context = ' (in spec: ' + runnable.getFullName() + ')'; + } + runnable.addDeprecationWarning(deprecation); if ( typeof console !== 'undefined' && typeof console.error === 'function' ) { - console.error('DEPRECATION:', deprecation); + console.error('DEPRECATION: ' + deprecation + context); } }; @@ -7151,17 +7161,21 @@ getJasmineRequireObj().QueueRunner = function(j$) { if (retval && j$.isFunction_(retval.then)) { // Issue a warning that matches the user's code if (j$.isAsyncFunction_(fn)) { - this.deprecated('An asynchronous before/it/after ' + - 'function was defined with the async keyword but also took a ' + - 'done callback. This is not supported and will stop working in' + - ' the future. Either remove the done callback (recommended) or ' + - 'remove the async keyword.'); + this.deprecated( + 'An asynchronous before/it/after ' + + 'function was defined with the async keyword but also took a ' + + 'done callback. This is not supported and will stop working in' + + ' the future. Either remove the done callback (recommended) or ' + + 'remove the async keyword.' + ); } else { - this.deprecated('An asynchronous before/it/after ' + - 'function took a done callback but also returned a promise. ' + - 'This is not supported and will stop working in the future. ' + - 'Either remove the done callback (recommended) or change the ' + - 'function to not return a promise.'); + this.deprecated( + 'An asynchronous before/it/after ' + + 'function took a done callback but also returned a promise. ' + + 'This is not supported and will stop working in the future. ' + + 'Either remove the done callback (recommended) or change the ' + + 'function to not return a promise.' + ); } } }; diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index c722aaff..7333b02a 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -528,11 +528,12 @@ describe('QueueRunner', function() { queueRunner.execute(); - expect(deprecated).toHaveBeenCalledWith('An asynchronous ' + - 'before/it/after function took a done callback but also returned a '+ - 'promise. This is not supported and will stop working in the future. ' + - 'Either remove the done callback (recommended) or change the function ' + - 'to not return a promise.' + expect(deprecated).toHaveBeenCalledWith( + 'An asynchronous ' + + 'before/it/after function took a done callback but also returned a ' + + 'promise. This is not supported and will stop working in the future. ' + + 'Either remove the done callback (recommended) or change the function ' + + 'to not return a promise.' ); }); @@ -541,17 +542,18 @@ describe('QueueRunner', function() { eval('var fn = async function(done){};'); var deprecated = jasmine.createSpy('deprecated'), queueRunner = new jasmineUnderTest.QueueRunner({ - queueableFns: [{fn: fn}], + queueableFns: [{ fn: fn }], deprecated: deprecated }); queueRunner.execute(); - expect(deprecated).toHaveBeenCalledWith('An asynchronous ' + - 'before/it/after function was defined with the async keyword but ' + - 'also took a done callback. This is not supported and will stop ' + - 'working in the future. Either remove the done callback ' + - '(recommended) or remove the async keyword.' + expect(deprecated).toHaveBeenCalledWith( + 'An asynchronous ' + + 'before/it/after function was defined with the async keyword but ' + + 'also took a done callback. This is not supported and will stop ' + + 'working in the future. Either remove the done callback ' + + '(recommended) or remove the async keyword.' ); }); }); diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index b51a7297..a11897b3 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -2294,7 +2294,7 @@ describe("Env integration", function() { it('should report deprecation warnings on the correct specs and suites', function(done) { var reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']); - // prevent deprecation from being displayed + // prevent deprecation from being displayed, as well as letting us observe calls spyOn(console, "error"); env.addReporter(reporter); @@ -2316,6 +2316,7 @@ describe("Env integration", function() { expect(result.deprecationWarnings).toEqual([ jasmine.objectContaining({ message: 'top level deprecation' }) ]); + expect(console.error).toHaveBeenCalledWith('DEPRECATION: top level deprecation'); expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ fullName: 'suite', @@ -2323,6 +2324,7 @@ describe("Env integration", function() { jasmine.objectContaining({ message: 'suite level deprecation' }) ] })); + expect(console.error).toHaveBeenCalledWith('DEPRECATION: suite level deprecation (in suite: suite)'); expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({ fullName: 'suite spec', @@ -2330,6 +2332,7 @@ describe("Env integration", function() { jasmine.objectContaining({ message: 'spec level deprecation' }) ] })); + expect(console.error).toHaveBeenCalledWith('DEPRECATION: spec level deprecation (in spec: suite spec)'); done(); }); diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js index 3b4f20e5..c41b68bb 100644 --- a/spec/html/HtmlReporterSpec.js +++ b/spec/html/HtmlReporterSpec.js @@ -270,12 +270,14 @@ describe('HtmlReporter', function() { reporter.jasmineStarted({}); reporter.specDone({ status: 'passed', + fullName: 'a spec with a deprecation', deprecationWarnings: [{ message: 'spec deprecation' }], failedExpectations: [], passedExpectations: [] }); reporter.suiteDone({ status: 'passed', + fullName: 'a suite with a deprecation', deprecationWarnings: [{ message: 'suite deprecation' }], failedExpectations: [] }); @@ -287,12 +289,17 @@ describe('HtmlReporter', function() { var alertBars = container.querySelectorAll('.jasmine-alert .jasmine-bar'); expect(alertBars.length).toEqual(4); - expect(alertBars[1].innerHTML).toMatch(/spec deprecation/); + expect(alertBars[1].innerHTML).toMatch( + /spec deprecation.*\(in spec: a spec with a deprecation\)/ + ); expect(alertBars[1].getAttribute('class')).toEqual( 'jasmine-bar jasmine-warning' ); - expect(alertBars[2].innerHTML).toMatch(/suite deprecation/); + expect(alertBars[2].innerHTML).toMatch( + /suite deprecation.*\(in suite: a suite with a deprecation\)/ + ); expect(alertBars[3].innerHTML).toMatch(/global deprecation/); + expect(alertBars[3].innerHTML).not.toMatch(/in /); }); }); diff --git a/src/core/Env.js b/src/core/Env.js index 7e299717..a70413b8 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -581,12 +581,22 @@ getJasmineRequireObj().Env = function(j$) { this.deprecated = function(deprecation) { var runnable = currentRunnable() || topSuite; + var context; + + if (runnable === topSuite) { + context = ''; + } else if (runnable === currentSuite()) { + context = ' (in suite: ' + runnable.getFullName() + ')'; + } else { + context = ' (in spec: ' + runnable.getFullName() + ')'; + } + runnable.addDeprecationWarning(deprecation); if ( typeof console !== 'undefined' && typeof console.error === 'function' ) { - console.error('DEPRECATION:', deprecation); + console.error('DEPRECATION: ' + deprecation + context); } }; diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index f009c3b5..be9e7f62 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -218,17 +218,21 @@ getJasmineRequireObj().QueueRunner = function(j$) { if (retval && j$.isFunction_(retval.then)) { // Issue a warning that matches the user's code if (j$.isAsyncFunction_(fn)) { - this.deprecated('An asynchronous before/it/after ' + - 'function was defined with the async keyword but also took a ' + - 'done callback. This is not supported and will stop working in' + - ' the future. Either remove the done callback (recommended) or ' + - 'remove the async keyword.'); + this.deprecated( + 'An asynchronous before/it/after ' + + 'function was defined with the async keyword but also took a ' + + 'done callback. This is not supported and will stop working in' + + ' the future. Either remove the done callback (recommended) or ' + + 'remove the async keyword.' + ); } else { - this.deprecated('An asynchronous before/it/after ' + - 'function took a done callback but also returned a promise. ' + - 'This is not supported and will stop working in the future. ' + - 'Either remove the done callback (recommended) or change the ' + - 'function to not return a promise.'); + this.deprecated( + 'An asynchronous before/it/after ' + + 'function took a done callback but also returned a promise. ' + + 'This is not supported and will stop working in the future. ' + + 'Either remove the done callback (recommended) or change the ' + + 'function to not return a promise.' + ); } } }; diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index 24d3a404..7cb2227e 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -101,7 +101,7 @@ jasmineRequire.HtmlReporter = function(j$) { if (result.status === 'failed') { failures.push(failureDom(result)); } - addDeprecationWarnings(result); + addDeprecationWarnings(result, 'suite'); }; this.specStarted = function(result) { @@ -137,7 +137,7 @@ jasmineRequire.HtmlReporter = function(j$) { failures.push(failureDom(result)); } - addDeprecationWarnings(result); + addDeprecationWarnings(result, 'spec'); }; this.displaySpecInCorrectFormat = function(result) { @@ -276,14 +276,27 @@ jasmineRequire.HtmlReporter = function(j$) { addDeprecationWarnings(doneResult); - var warningBarClassName = 'jasmine-bar jasmine-warning'; for (i = 0; i < deprecationWarnings.length; i++) { - var warning = deprecationWarnings[i]; + var context; + + switch (deprecationWarnings[i].runnableType) { + case 'spec': + context = '(in spec: ' + deprecationWarnings[i].runnableName + ')'; + break; + case 'suite': + context = '(in suite: ' + deprecationWarnings[i].runnableName + ')'; + break; + default: + context = ''; + } + alert.appendChild( createDom( 'span', - { className: warningBarClassName }, - 'DEPRECATION: ' + warning + { className: 'jasmine-bar jasmine-warning' }, + 'DEPRECATION: ' + deprecationWarnings[i].message, + createDom('br'), + context ) ); } @@ -594,12 +607,18 @@ jasmineRequire.HtmlReporter = function(j$) { return addToExistingQueryString('spec', els.join(' ')); } - function addDeprecationWarnings(result) { + function addDeprecationWarnings(result, runnableType) { if (result && result.deprecationWarnings) { for (var i = 0; i < result.deprecationWarnings.length; i++) { var warning = result.deprecationWarnings[i].message; + debugger; if (!j$.util.arrayContains(warning)) { - deprecationWarnings.push(warning); + debugger; + deprecationWarnings.push({ + message: warning, + runnableName: result.fullName, + runnableType: runnableType + }); } } } From 795651d3b6d2b49c8278d01b61ef7384443e5157 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sun, 13 Sep 2020 13:40:15 -0700 Subject: [PATCH 57/57] Removed debugger statements --- lib/jasmine-core/jasmine-html.js | 2 -- src/html/HtmlReporter.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index 26ae6ac9..5e436b3e 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -642,9 +642,7 @@ jasmineRequire.HtmlReporter = function(j$) { if (result && result.deprecationWarnings) { for (var i = 0; i < result.deprecationWarnings.length; i++) { var warning = result.deprecationWarnings[i].message; - debugger; if (!j$.util.arrayContains(warning)) { - debugger; deprecationWarnings.push({ message: warning, runnableName: result.fullName, diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index 7cb2227e..e591ccac 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -611,9 +611,7 @@ jasmineRequire.HtmlReporter = function(j$) { if (result && result.deprecationWarnings) { for (var i = 0; i < result.deprecationWarnings.length; i++) { var warning = result.deprecationWarnings[i].message; - debugger; if (!j$.util.arrayContains(warning)) { - debugger; deprecationWarnings.push({ message: warning, runnableName: result.fullName,