From 262a2fe674f9fc7250eb361585d8ddb3e2c0b780 Mon Sep 17 00:00:00 2001 From: Gregg Van Hove Date: Mon, 29 Jan 2018 14:02:02 -0800 Subject: [PATCH] Generate compiled jasmine.js for async reporters work --- lib/jasmine-core/jasmine.js | 289 +++++++++++++++++++++--------------- 1 file changed, 168 insertions(+), 121 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index d7154461..f8a9f028 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -528,7 +528,19 @@ getJasmineRequireObj().Spec = function(j$) { Spec.prototype.execute = function(onComplete, excluded) { var self = this; - this.onStart(this); + var onStart = { + fn: function(done) { + self.onStart(self, done); + } + }; + + var complete = { + fn: function(done) { + self.queueableFn.fn = null; + self.result.status = self.status(excluded); + self.resultCallback(self.result, done); + } + }; var fns = this.beforeAndAfterFns(); var regularFns = fns.befores.concat(this.queueableFn); @@ -537,8 +549,10 @@ getJasmineRequireObj().Spec = function(j$) { isLeaf: true, queueableFns: regularFns, cleanupFns: fns.afters, - onException: function() { self.onException.apply(self, arguments); }, - onComplete: complete, + onException: function () { + self.onException.apply(self, arguments); + }, + onComplete: onComplete, userContext: this.userContext() }; @@ -547,17 +561,10 @@ getJasmineRequireObj().Spec = function(j$) { runnerConfig.cleanupFns = []; } + runnerConfig.queueableFns.unshift(onStart); + runnerConfig.cleanupFns.push(complete); + this.queueRunnerFactory(runnerConfig); - - function complete() { - self.queueableFn.fn = null; - self.result.status = self.status(excluded); - self.resultCallback(self.result); - - if (onComplete) { - onComplete(); - } - } }; Spec.prototype.onException = function onException(e) { @@ -720,59 +727,6 @@ getJasmineRequireObj().Env = function(j$) { return currentSpec || currentSuite(); }; - /** - * This represents the available reporter callback for an object passed to {@link Env#addReporter}. - * @interface Reporter - */ - var reporter = new j$.ReportDispatcher([ - /** - * `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts. - * @function - * @name Reporter#jasmineStarted - * @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run - */ - 'jasmineStarted', - /** - * When the entire suite has finished execution `jasmineDone` is called - * @function - * @name Reporter#jasmineDone - * @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running. - */ - 'jasmineDone', - /** - * `suiteStarted` is invoked when a `describe` starts to run - * @function - * @name Reporter#suiteStarted - * @param {SuiteResult} result Information about the individual {@link describe} being run - */ - 'suiteStarted', - /** - * `suiteDone` is invoked when all of the child specs and suites for a given suite have been run - * - * While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`. - * @function - * @name Reporter#suiteDone - * @param {SuiteResult} result - */ - 'suiteDone', - /** - * `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions) - * @function - * @name Reporter#specStarted - * @param {SpecResult} result Information about the individual {@link it} being run - */ - 'specStarted', - /** - * `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run. - * - * While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed. - * @function - * @name Reporter#specDone - * @param {SpecResult} result - */ - 'specDone' - ]); - var globalErrors = new j$.GlobalErrors(); globalErrors.install(); globalErrors.pushListener(function(message, filename, lineno) { @@ -941,15 +895,18 @@ getJasmineRequireObj().Env = function(j$) { handlingLoadErrors = false; }; - var queueRunnerFactory = function(options) { + var queueRunnerFactory = function(options, args) { options.catchException = catchException; options.clearStack = options.clearStack || clearStack; options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; options.fail = self.fail; options.globalErrors = globalErrors; options.completeOnFirstError = throwOnExpectationFailure && options.isLeaf; + options.onException = options.onException || function(e) { + (currentRunnable() || topSuite).onException(e); + }; - new j$.QueueRunner(options).execute(); + new j$.QueueRunner(options).execute(args); }; var topSuite = new j$.Suite({ @@ -966,6 +923,59 @@ getJasmineRequireObj().Env = function(j$) { return topSuite; }; + /** + * This represents the available reporter callback for an object passed to {@link Env#addReporter}. + * @interface Reporter + */ + var reporter = new j$.ReportDispatcher([ + /** + * `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts. + * @function + * @name Reporter#jasmineStarted + * @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run + */ + 'jasmineStarted', + /** + * When the entire suite has finished execution `jasmineDone` is called + * @function + * @name Reporter#jasmineDone + * @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running. + */ + 'jasmineDone', + /** + * `suiteStarted` is invoked when a `describe` starts to run + * @function + * @name Reporter#suiteStarted + * @param {SuiteResult} result Information about the individual {@link describe} being run + */ + 'suiteStarted', + /** + * `suiteDone` is invoked when all of the child specs and suites for a given suite have been run + * + * While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`. + * @function + * @name Reporter#suiteDone + * @param {SuiteResult} result + */ + 'suiteDone', + /** + * `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions) + * @function + * @name Reporter#specStarted + * @param {SpecResult} result Information about the individual {@link it} being run + */ + 'specStarted', + /** + * `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run. + * + * While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed. + * @function + * @name Reporter#specDone + * @param {SpecResult} result + */ + 'specDone' + ], queueRunnerFactory); + this.execute = function(runnablesToRun) { var self = this; this.suppressLoadErrors(); @@ -987,23 +997,24 @@ getJasmineRequireObj().Env = function(j$) { tree: topSuite, runnableIds: runnablesToRun, queueRunnerFactory: queueRunnerFactory, - nodeStart: function(suite) { + nodeStart: function(suite, next) { currentlyExecutingSuites.push(suite); defaultResourcesForRunnable(suite.id, suite.parentSuite.id); - reporter.suiteStarted(suite.result); + reporter.suiteStarted(suite.result, next); }, - nodeComplete: function(suite, result) { + nodeComplete: function(suite, result, next) { if (suite !== currentSuite()) { throw new Error('Tried to complete the wrong suite'); } clearResourcesForRunnable(suite.id); currentlyExecutingSuites.pop(); - reporter.suiteDone(result); if (result.status === 'failed') { hasFailures = true; } + + reporter.suiteDone(result, next); }, orderChildren: function(node) { return order.sort(node.children); @@ -1026,40 +1037,40 @@ getJasmineRequireObj().Env = function(j$) { reporter.jasmineStarted({ totalSpecsDefined: totalSpecsDefined, order: order - }); + }, function() { + currentlyExecutingSuites.push(topSuite); - currentlyExecutingSuites.push(topSuite); + processor.execute(function () { + clearResourcesForRunnable(topSuite.id); + currentlyExecutingSuites.pop(); + var overallStatus, incompleteReason; - processor.execute(function() { - clearResourcesForRunnable(topSuite.id); - currentlyExecutingSuites.pop(); - var overallStatus, incompleteReason; + if (hasFailures || topSuite.result.failedExpectations.length > 0) { + overallStatus = 'failed'; + } else if (focusedRunnables.length > 0) { + overallStatus = 'incomplete'; + incompleteReason = 'fit() or fdescribe() was found'; + } else if (totalSpecsDefined === 0) { + overallStatus = 'incomplete'; + incompleteReason = 'No specs found'; + } else { + overallStatus = 'passed'; + } - if (hasFailures || topSuite.result.failedExpectations.length > 0) { - overallStatus = 'failed'; - } else if (focusedRunnables.length > 0) { - overallStatus = 'incomplete'; - incompleteReason = 'fit() or fdescribe() was found'; - } else if (totalSpecsDefined === 0) { - overallStatus = 'incomplete'; - incompleteReason = 'No specs found'; - } else { - overallStatus = 'passed'; - } - - /** - * Information passed to the {@link Reporter#jasmineDone} event. - * @typedef JasmineDoneInfo - * @property {OverallStatus} - The overall result of the sute: 'passed', 'failed', or 'incomplete'. - * @property {IncompleteReason} - Explanation of why the suite was incimplete. - * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. - * @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level. - */ - reporter.jasmineDone({ - overallStatus: overallStatus, - incompleteReason: incompleteReason, - order: order, - failedExpectations: topSuite.result.failedExpectations + /** + * Information passed to the {@link Reporter#jasmineDone} event. + * @typedef JasmineDoneInfo + * @property {OverallStatus} - The overall result of the sute: 'passed', 'failed', or 'incomplete'. + * @property {IncompleteReason} - Explanation of why the suite was incimplete. + * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. + * @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level. + */ + reporter.jasmineDone({ + overallStatus: overallStatus, + incompleteReason: incompleteReason, + order: order, + failedExpectations: topSuite.result.failedExpectations + }, function() {}); }); }); }; @@ -1262,20 +1273,21 @@ getJasmineRequireObj().Env = function(j$) { return spec; - function specResultCallback(result) { + function specResultCallback(result, next) { clearResourcesForRunnable(spec.id); currentSpec = null; - reporter.specDone(result); if (result.status === 'failed') { hasFailures = true; } + + reporter.specDone(result, next); } - function specStarted(spec) { + function specStarted(spec, next) { currentSpec = spec; defaultResourcesForRunnable(spec.id, suite.id); - reporter.specStarted(spec.result); + reporter.specStarted(spec.result, next); } }; @@ -4460,6 +4472,10 @@ getJasmineRequireObj().QueueRunner = function(j$) { this.fail = attrs.fail || function() {}; this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} }; this.completeOnFirstError = !!attrs.completeOnFirstError; + + if (typeof(this.onComplete) !== 'function') { + throw new Error('invalid onComplete ' + JSON.stringify(this.onComplete)); + } } QueueRunner.prototype.execute = function() { @@ -4489,15 +4505,15 @@ getJasmineRequireObj().QueueRunner = function(j$) { QueueRunner.prototype.attempt = function attempt(iterativeIndex) { var self = this, completedSynchronously = true, - handleError = function(error) { + handleError = function handleError(error) { onException(error); next(); }, - cleanup = once(function() { + cleanup = once(function cleanup() { self.clearTimeout(timeoutId); self.globalErrors.popListener(handleError); }), - next = once(function () { + next = once(function next() { cleanup(); function runNext() { @@ -4518,7 +4534,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { queueableFn = self.queueableFns[iterativeIndex], timeoutId; - next.fail = function() { + next.fail = function nextFail() { self.fail.apply(null, arguments); errored = true; next(); @@ -4606,7 +4622,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { }; getJasmineRequireObj().ReportDispatcher = function(j$) { - function ReportDispatcher(methods) { + function ReportDispatcher(methods, queueRunnerFactory) { var dispatchedMethods = methods || []; @@ -4640,11 +4656,39 @@ getJasmineRequireObj().ReportDispatcher = function(j$) { if (reporters.length === 0 && fallbackReporter !== null) { reporters.push(fallbackReporter); } + var onComplete = args[args.length - 1]; + args = j$.util.argsToArray(args).splice(0, args.length - 1); + var fns = []; for (var i = 0; i < reporters.length; i++) { var reporter = reporters[i]; - if (reporter[method]) { - reporter[method].apply(reporter, j$.util.cloneArgs(args)); - } + addFn(fns, reporter, method, args); + } + + queueRunnerFactory({ + queueableFns: fns, + onComplete: onComplete + }); + } + + function addFn(fns, reporter, method, args) { + var fn = reporter[method]; + if (!fn) { + return; + } + + var thisArgs = j$.util.cloneArgs(args); + if (fn.length <= 1) { + fns.push({ + fn: function () { + return fn.apply(reporter, thisArgs); + } + }); + } else { + fns.push({ + fn: function (done) { + return fn.apply(reporter, thisArgs.concat([done])); + } + }); } } } @@ -5857,17 +5901,20 @@ getJasmineRequireObj().TreeProcessor = function() { if (node.children) { return { fn: function(done) { - nodeStart(node); + var onStart = { + fn: function(next) { + nodeStart(node, next); + } + }; queueRunnerFactory({ - onComplete: function() { + onComplete: function () { node.cleanupBeforeAfter(); - nodeComplete(node, node.getResult()); - done(); + nodeComplete(node, node.getResult(), done); }, - queueableFns: wrapChildren(node, segmentNumber), + queueableFns: [onStart].concat(wrapChildren(node, segmentNumber)), userContext: node.sharedUserContext(), - onException: function() { + onException: function () { node.onException.apply(node, arguments); } });