From 21f25972bbf32a343258b30ff6770c4acb2c0852 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Tue, 14 Jun 2022 19:36:11 -0700 Subject: [PATCH 1/3] Converted ReportDispatcher to promises --- lib/jasmine-core/jasmine.js | 174 ++++++++++++++---------------- spec/core/ReportDispatcherSpec.js | 24 ++--- src/core/Env.js | 4 +- src/core/ReportDispatcher.js | 30 +++--- src/core/Runner.js | 140 +++++++++++------------- 5 files changed, 172 insertions(+), 200 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 1201ec00..22c24bec 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1843,12 +1843,12 @@ getJasmineRequireObj().Env = function(j$) { function specStarted(spec, suite, next) { runner.currentSpec = spec; runableResources.initForRunable(spec.id, suite.id); - reporter.specStarted(spec.result, next); + reporter.specStarted(spec.result).then(next); } function reportSpecDone(spec, result, next) { spec.reportedDone = true; - reporter.specDone(result, next); + reporter.specDone(result).then(next); } this.it = function(description, fn, timeout) { @@ -7700,7 +7700,7 @@ getJasmineRequireObj().ReportDispatcher = function(j$) { for (const method of dispatchedMethods) { this[method] = (function(m) { return function() { - dispatch(m, arguments); + return dispatch(m, arguments); }; })(method); } @@ -7726,25 +7726,25 @@ getJasmineRequireObj().ReportDispatcher = function(j$) { if (reporters.length === 0 && fallbackReporter !== null) { reporters.push(fallbackReporter); } - const onComplete = args[args.length - 1]; - args = Array.from(args).splice(0, args.length - 1); const fns = []; for (const reporter of reporters) { addFn(fns, reporter, method, args); } - queueRunnerFactory({ - queueableFns: fns, - onComplete: onComplete, - isReporter: true, - onMultipleDone: function() { - onLateError( - new Error( - "An asynchronous reporter callback called its 'done' callback " + - 'more than once.' - ) - ); - } + return new Promise(function(resolve) { + queueRunnerFactory({ + queueableFns: fns, + onComplete: resolve, + isReporter: true, + onMultipleDone: function() { + onLateError( + new Error( + "An asynchronous reporter callback called its 'done' callback " + + 'more than once.' + ) + ); + } + }); }); } @@ -8400,7 +8400,6 @@ getJasmineRequireObj().Runner = function(j$) { this.executedBefore_ = true; this.hasFailures = false; - const totalSpecsDefined = this.totalSpecsDefined_(); const focusedRunables = this.focusedRunables_(); const config = this.getConfig_(); @@ -8439,7 +8438,7 @@ getJasmineRequireObj().Runner = function(j$) { nodeStart: (suite, next) => { this.currentlyExecutingSuites_.push(suite); this.runableResources_.initForRunable(suite.id, suite.parentSuite.id); - this.reporter_.suiteStarted(suite.result, next); + this.reporter_.suiteStarted(suite.result).then(next); suite.startTimer(); }, nodeComplete: (suite, result, next) => { @@ -8477,106 +8476,95 @@ getJasmineRequireObj().Runner = function(j$) { ); } + return this.execute2_(runablesToRun, order, processor); + } + + async execute2_(runablesToRun, order, processor) { + const totalSpecsDefined = this.totalSpecsDefined_(); + this.runableResources_.initForRunable(this.topSuite_.id); const jasmineTimer = new j$.Timer(); jasmineTimer.start(); + await this.reporter_.jasmineStarted({ + totalSpecsDefined, + order: order + }); + + this.currentlyExecutingSuites_.push(this.topSuite_); + return new Promise(resolve => { - /** - * Information passed to the {@link Reporter#jasmineStarted} event. - * @typedef JasmineStartedInfo - * @property {Int} totalSpecsDefined - The total number of specs defined in this suite. - * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. - * @since 2.0.0 - */ - this.reporter_.jasmineStarted( - { - totalSpecsDefined, - order: order - }, - () => { - this.currentlyExecutingSuites_.push(this.topSuite_); + processor.execute(() => { + (async () => { + if (this.topSuite_.hadBeforeAllFailure) { + await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); + } - processor.execute(() => { - (async () => { - if (this.topSuite_.hadBeforeAllFailure) { - await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); - } + this.runableResources_.clearForRunable(this.topSuite_.id); + this.currentlyExecutingSuites_.pop(); + let overallStatus, incompleteReason; - this.runableResources_.clearForRunable(this.topSuite_.id); - this.currentlyExecutingSuites_.pop(); - let overallStatus, incompleteReason; + if ( + this.hasFailures || + this.topSuite_.result.failedExpectations.length > 0 + ) { + overallStatus = 'failed'; + } else if (this.focusedRunables_().length > 0) { + overallStatus = 'incomplete'; + incompleteReason = 'fit() or fdescribe() was found'; + } else if (totalSpecsDefined === 0) { + overallStatus = 'incomplete'; + incompleteReason = 'No specs found'; + } else { + overallStatus = 'passed'; + } - if ( - this.hasFailures || - this.topSuite_.result.failedExpectations.length > 0 - ) { - overallStatus = 'failed'; - } else if (focusedRunables.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} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. - * @property {Int} totalTime - The total time (in ms) that it took to execute the suite - * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. - * @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. - * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. - * @since 2.4.0 - */ - const jasmineDoneInfo = { - overallStatus: overallStatus, - totalTime: jasmineTimer.elapsed(), - incompleteReason: incompleteReason, - order: order, - failedExpectations: this.topSuite_.result.failedExpectations, - deprecationWarnings: this.topSuite_.result.deprecationWarnings - }; - this.topSuite_.reportedDone = true; - this.reporter_.jasmineDone(jasmineDoneInfo, function() { - resolve(jasmineDoneInfo); - }); - })(); - }); - } - ); + /** + * Information passed to the {@link Reporter#jasmineDone} event. + * @typedef JasmineDoneInfo + * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. + * @property {Int} totalTime - The total time (in ms) that it took to execute the suite + * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. + * @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. + * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. + * @since 2.4.0 + */ + const jasmineDoneInfo = { + overallStatus: overallStatus, + totalTime: jasmineTimer.elapsed(), + incompleteReason: incompleteReason, + order: order, + failedExpectations: this.topSuite_.result.failedExpectations, + deprecationWarnings: this.topSuite_.result.deprecationWarnings + }; + this.topSuite_.reportedDone = true; + await this.reporter_.jasmineDone(jasmineDoneInfo); + resolve(jasmineDoneInfo); + })(); + }); }); } reportSuiteDone_(suite, result, next) { suite.reportedDone = true; - this.reporter_.suiteDone(result, next); + this.reporter_.suiteDone(result).then(next); } async reportChildrenOfBeforeAllFailure_(suite) { for (const child of suite.children) { if (child instanceof j$.Suite) { - await new Promise(resolve => { - this.reporter_.suiteStarted(child.result, resolve); - }); + await this.reporter_.suiteStarted(child.result); await this.reportChildrenOfBeforeAllFailure_(child); // Marking the suite passed is consistent with how suites that // contain failed specs but no suite-level failures are reported. child.result.status = 'passed'; - await new Promise(resolve => { - this.reporter_.suiteDone(child.result, resolve); - }); + await this.reporter_.suiteDone(child.result); } else { /* a spec */ - await new Promise(resolve => { - this.reporter_.specStarted(child.result, resolve); - }); + await this.reporter_.specStarted(child.result); child.addExpectationResult( false, diff --git a/spec/core/ReportDispatcherSpec.js b/spec/core/ReportDispatcherSpec.js index d435239e..0bee1d00 100644 --- a/spec/core/ReportDispatcherSpec.js +++ b/spec/core/ReportDispatcherSpec.js @@ -18,13 +18,12 @@ describe('ReportDispatcher', function() { queueRunnerFactory ), reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']), - anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']), - completeCallback = jasmine.createSpy('complete'); + anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']); dispatcher.addReporter(reporter); dispatcher.addReporter(anotherReporter); - dispatcher.foo(123, 456, completeCallback); + dispatcher.foo(123, 456); expect(queueRunnerFactory).toHaveBeenCalledWith( jasmine.objectContaining({ @@ -47,7 +46,7 @@ describe('ReportDispatcher', function() { queueRunnerFactory.calls.reset(); - dispatcher.bar('a', 'b', completeCallback); + dispatcher.bar('a', 'b'); expect(queueRunnerFactory).toHaveBeenCalledWith( jasmine.objectContaining({ @@ -91,11 +90,10 @@ describe('ReportDispatcher', function() { ['foo', 'bar'], queueRunnerFactory ), - reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']), - completeCallback = jasmine.createSpy('complete'); + reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']); dispatcher.provideFallbackReporter(reporter); - dispatcher.foo(123, 456, completeCallback); + dispatcher.foo(123, 456); expect(queueRunnerFactory).toHaveBeenCalledWith( jasmine.objectContaining({ @@ -116,12 +114,11 @@ describe('ReportDispatcher', function() { queueRunnerFactory ), reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']), - fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']), - completeCallback = jasmine.createSpy('complete'); + fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']); dispatcher.provideFallbackReporter(fallbackReporter); dispatcher.addReporter(reporter); - dispatcher.foo(123, 456, completeCallback); + dispatcher.foo(123, 456); expect(queueRunnerFactory).toHaveBeenCalledWith( jasmine.objectContaining({ @@ -143,11 +140,10 @@ describe('ReportDispatcher', function() { queueRunnerFactory ), reporter1 = jasmine.createSpyObj('reporter1', ['foo', 'bar']), - reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']), - completeCallback = jasmine.createSpy('complete'); + reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']); dispatcher.addReporter(reporter1); - dispatcher.foo(123, completeCallback); + dispatcher.foo(123); expect(queueRunnerFactory).toHaveBeenCalledWith( jasmine.objectContaining({ queueableFns: [{ fn: jasmine.any(Function) }], @@ -161,7 +157,7 @@ describe('ReportDispatcher', function() { dispatcher.clearReporters(); dispatcher.addReporter(reporter2); - dispatcher.bar(456, completeCallback); + dispatcher.bar(456); expect(queueRunnerFactory).toHaveBeenCalledWith( jasmine.objectContaining({ diff --git a/src/core/Env.js b/src/core/Env.js index a9905328..b6fabb6d 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -701,12 +701,12 @@ getJasmineRequireObj().Env = function(j$) { function specStarted(spec, suite, next) { runner.currentSpec = spec; runableResources.initForRunable(spec.id, suite.id); - reporter.specStarted(spec.result, next); + reporter.specStarted(spec.result).then(next); } function reportSpecDone(spec, result, next) { spec.reportedDone = true; - reporter.specDone(result, next); + reporter.specDone(result).then(next); } this.it = function(description, fn, timeout) { diff --git a/src/core/ReportDispatcher.js b/src/core/ReportDispatcher.js index 55a7097c..55759d03 100644 --- a/src/core/ReportDispatcher.js +++ b/src/core/ReportDispatcher.js @@ -5,7 +5,7 @@ getJasmineRequireObj().ReportDispatcher = function(j$) { for (const method of dispatchedMethods) { this[method] = (function(m) { return function() { - dispatch(m, arguments); + return dispatch(m, arguments); }; })(method); } @@ -31,25 +31,25 @@ getJasmineRequireObj().ReportDispatcher = function(j$) { if (reporters.length === 0 && fallbackReporter !== null) { reporters.push(fallbackReporter); } - const onComplete = args[args.length - 1]; - args = Array.from(args).splice(0, args.length - 1); const fns = []; for (const reporter of reporters) { addFn(fns, reporter, method, args); } - queueRunnerFactory({ - queueableFns: fns, - onComplete: onComplete, - isReporter: true, - onMultipleDone: function() { - onLateError( - new Error( - "An asynchronous reporter callback called its 'done' callback " + - 'more than once.' - ) - ); - } + return new Promise(function(resolve) { + queueRunnerFactory({ + queueableFns: fns, + onComplete: resolve, + isReporter: true, + onMultipleDone: function() { + onLateError( + new Error( + "An asynchronous reporter callback called its 'done' callback " + + 'more than once.' + ) + ); + } + }); }); } diff --git a/src/core/Runner.js b/src/core/Runner.js index 10df5195..cc1ce3a9 100644 --- a/src/core/Runner.js +++ b/src/core/Runner.js @@ -37,7 +37,6 @@ getJasmineRequireObj().Runner = function(j$) { this.executedBefore_ = true; this.hasFailures = false; - const totalSpecsDefined = this.totalSpecsDefined_(); const focusedRunables = this.focusedRunables_(); const config = this.getConfig_(); @@ -76,7 +75,7 @@ getJasmineRequireObj().Runner = function(j$) { nodeStart: (suite, next) => { this.currentlyExecutingSuites_.push(suite); this.runableResources_.initForRunable(suite.id, suite.parentSuite.id); - this.reporter_.suiteStarted(suite.result, next); + this.reporter_.suiteStarted(suite.result).then(next); suite.startTimer(); }, nodeComplete: (suite, result, next) => { @@ -114,106 +113,95 @@ getJasmineRequireObj().Runner = function(j$) { ); } + return this.execute2_(runablesToRun, order, processor); + } + + async execute2_(runablesToRun, order, processor) { + const totalSpecsDefined = this.totalSpecsDefined_(); + this.runableResources_.initForRunable(this.topSuite_.id); const jasmineTimer = new j$.Timer(); jasmineTimer.start(); + await this.reporter_.jasmineStarted({ + totalSpecsDefined, + order: order + }); + + this.currentlyExecutingSuites_.push(this.topSuite_); + return new Promise(resolve => { - /** - * Information passed to the {@link Reporter#jasmineStarted} event. - * @typedef JasmineStartedInfo - * @property {Int} totalSpecsDefined - The total number of specs defined in this suite. - * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. - * @since 2.0.0 - */ - this.reporter_.jasmineStarted( - { - totalSpecsDefined, - order: order - }, - () => { - this.currentlyExecutingSuites_.push(this.topSuite_); + processor.execute(() => { + (async () => { + if (this.topSuite_.hadBeforeAllFailure) { + await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); + } - processor.execute(() => { - (async () => { - if (this.topSuite_.hadBeforeAllFailure) { - await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); - } + this.runableResources_.clearForRunable(this.topSuite_.id); + this.currentlyExecutingSuites_.pop(); + let overallStatus, incompleteReason; - this.runableResources_.clearForRunable(this.topSuite_.id); - this.currentlyExecutingSuites_.pop(); - let overallStatus, incompleteReason; + if ( + this.hasFailures || + this.topSuite_.result.failedExpectations.length > 0 + ) { + overallStatus = 'failed'; + } else if (this.focusedRunables_().length > 0) { + overallStatus = 'incomplete'; + incompleteReason = 'fit() or fdescribe() was found'; + } else if (totalSpecsDefined === 0) { + overallStatus = 'incomplete'; + incompleteReason = 'No specs found'; + } else { + overallStatus = 'passed'; + } - if ( - this.hasFailures || - this.topSuite_.result.failedExpectations.length > 0 - ) { - overallStatus = 'failed'; - } else if (focusedRunables.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} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. - * @property {Int} totalTime - The total time (in ms) that it took to execute the suite - * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. - * @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. - * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. - * @since 2.4.0 - */ - const jasmineDoneInfo = { - overallStatus: overallStatus, - totalTime: jasmineTimer.elapsed(), - incompleteReason: incompleteReason, - order: order, - failedExpectations: this.topSuite_.result.failedExpectations, - deprecationWarnings: this.topSuite_.result.deprecationWarnings - }; - this.topSuite_.reportedDone = true; - this.reporter_.jasmineDone(jasmineDoneInfo, function() { - resolve(jasmineDoneInfo); - }); - })(); - }); - } - ); + /** + * Information passed to the {@link Reporter#jasmineDone} event. + * @typedef JasmineDoneInfo + * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. + * @property {Int} totalTime - The total time (in ms) that it took to execute the suite + * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. + * @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. + * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. + * @since 2.4.0 + */ + const jasmineDoneInfo = { + overallStatus: overallStatus, + totalTime: jasmineTimer.elapsed(), + incompleteReason: incompleteReason, + order: order, + failedExpectations: this.topSuite_.result.failedExpectations, + deprecationWarnings: this.topSuite_.result.deprecationWarnings + }; + this.topSuite_.reportedDone = true; + await this.reporter_.jasmineDone(jasmineDoneInfo); + resolve(jasmineDoneInfo); + })(); + }); }); } reportSuiteDone_(suite, result, next) { suite.reportedDone = true; - this.reporter_.suiteDone(result, next); + this.reporter_.suiteDone(result).then(next); } async reportChildrenOfBeforeAllFailure_(suite) { for (const child of suite.children) { if (child instanceof j$.Suite) { - await new Promise(resolve => { - this.reporter_.suiteStarted(child.result, resolve); - }); + await this.reporter_.suiteStarted(child.result); await this.reportChildrenOfBeforeAllFailure_(child); // Marking the suite passed is consistent with how suites that // contain failed specs but no suite-level failures are reported. child.result.status = 'passed'; - await new Promise(resolve => { - this.reporter_.suiteDone(child.result, resolve); - }); + await this.reporter_.suiteDone(child.result); } else { /* a spec */ - await new Promise(resolve => { - this.reporter_.specStarted(child.result, resolve); - }); + await this.reporter_.specStarted(child.result); child.addExpectationResult( false, From 5f3475342eb42fd69d979fd9a81a433f4b396e01 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 6 Aug 2022 10:53:28 -0700 Subject: [PATCH 2/3] Re-added missing JasmineStartedInfo jsdoc --- lib/jasmine-core/jasmine.js | 7 +++++++ src/core/Runner.js | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 22c24bec..8be445a0 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -8486,6 +8486,13 @@ getJasmineRequireObj().Runner = function(j$) { const jasmineTimer = new j$.Timer(); jasmineTimer.start(); + /** + * Information passed to the {@link Reporter#jasmineStarted} event. + * @typedef JasmineStartedInfo + * @property {Int} totalSpecsDefined - The total number of specs defined in this suite. + * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. + * @since 2.0.0 + */ await this.reporter_.jasmineStarted({ totalSpecsDefined, order: order diff --git a/src/core/Runner.js b/src/core/Runner.js index cc1ce3a9..c9e1c70f 100644 --- a/src/core/Runner.js +++ b/src/core/Runner.js @@ -123,6 +123,13 @@ getJasmineRequireObj().Runner = function(j$) { const jasmineTimer = new j$.Timer(); jasmineTimer.start(); + /** + * Information passed to the {@link Reporter#jasmineStarted} event. + * @typedef JasmineStartedInfo + * @property {Int} totalSpecsDefined - The total number of specs defined in this suite. + * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. + * @since 2.0.0 + */ await this.reporter_.jasmineStarted({ totalSpecsDefined, order: order From b3d9435dbb9d9412bd56a5c2c050546c298ebee9 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Mon, 22 Aug 2022 17:04:44 -0700 Subject: [PATCH 3/3] Convreted TreeProcessor to async/await --- lib/jasmine-core/jasmine.js | 115 ++++++++++++++++----------------- spec/core/TreeProcessorSpec.js | 30 +++++---- src/core/Runner.js | 91 ++++++++++++-------------- src/core/TreeProcessor.js | 24 +++---- 4 files changed, 129 insertions(+), 131 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 7ef23418..50db1ce3 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -8518,58 +8518,53 @@ getJasmineRequireObj().Runner = function(j$) { }); this.currentlyExecutingSuites_.push(this.topSuite_); + await processor.execute(); - return new Promise(resolve => { - processor.execute(() => { - (async () => { - if (this.topSuite_.hadBeforeAllFailure) { - await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); - } + if (this.topSuite_.hadBeforeAllFailure) { + await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); + } - this.runableResources_.clearForRunable(this.topSuite_.id); - this.currentlyExecutingSuites_.pop(); - let overallStatus, incompleteReason; + this.runableResources_.clearForRunable(this.topSuite_.id); + this.currentlyExecutingSuites_.pop(); + let overallStatus, incompleteReason; - if ( - this.hasFailures || - this.topSuite_.result.failedExpectations.length > 0 - ) { - overallStatus = 'failed'; - } else if (this.focusedRunables_().length > 0) { - overallStatus = 'incomplete'; - incompleteReason = 'fit() or fdescribe() was found'; - } else if (totalSpecsDefined === 0) { - overallStatus = 'incomplete'; - incompleteReason = 'No specs found'; - } else { - overallStatus = 'passed'; - } + if ( + this.hasFailures || + this.topSuite_.result.failedExpectations.length > 0 + ) { + overallStatus = 'failed'; + } else if (this.focusedRunables_().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} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. - * @property {Int} totalTime - The total time (in ms) that it took to execute the suite - * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. - * @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. - * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. - * @since 2.4.0 - */ - const jasmineDoneInfo = { - overallStatus: overallStatus, - totalTime: jasmineTimer.elapsed(), - incompleteReason: incompleteReason, - order: order, - failedExpectations: this.topSuite_.result.failedExpectations, - deprecationWarnings: this.topSuite_.result.deprecationWarnings - }; - this.topSuite_.reportedDone = true; - await this.reporter_.jasmineDone(jasmineDoneInfo); - resolve(jasmineDoneInfo); - })(); - }); - }); + /** + * Information passed to the {@link Reporter#jasmineDone} event. + * @typedef JasmineDoneInfo + * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. + * @property {Int} totalTime - The total time (in ms) that it took to execute the suite + * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. + * @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. + * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. + * @since 2.4.0 + */ + const jasmineDoneInfo = { + overallStatus: overallStatus, + totalTime: jasmineTimer.elapsed(), + incompleteReason: incompleteReason, + order: order, + failedExpectations: this.topSuite_.result.failedExpectations, + deprecationWarnings: this.topSuite_.result.deprecationWarnings + }; + this.topSuite_.reportedDone = true; + await this.reporter_.jasmineDone(jasmineDoneInfo); + return jasmineDoneInfo; } reportSuiteDone_(suite, result, next) { @@ -10190,7 +10185,7 @@ getJasmineRequireObj().TreeProcessor = function() { return stats; }; - this.execute = function(done) { + this.execute = async function() { if (!processed) { this.processTree(); } @@ -10201,16 +10196,18 @@ getJasmineRequireObj().TreeProcessor = function() { const childFns = wrapChildren(tree, 0); - queueRunnerFactory({ - queueableFns: childFns, - userContext: tree.sharedUserContext(), - onException: function() { - tree.handleException.apply(tree, arguments); - }, - onComplete: done, - onMultipleDone: tree.onMultipleDone - ? tree.onMultipleDone.bind(tree) - : null + await new Promise(function(resolve) { + queueRunnerFactory({ + queueableFns: childFns, + userContext: tree.sharedUserContext(), + onException: function() { + tree.handleException.apply(tree, arguments); + }, + onComplete: resolve, + onMultipleDone: tree.onMultipleDone + ? tree.onMultipleDone.bind(tree) + : null + }); }); }; diff --git a/spec/core/TreeProcessorSpec.js b/spec/core/TreeProcessorSpec.js index 25e955e6..dc03dc18 100644 --- a/spec/core/TreeProcessorSpec.js +++ b/spec/core/TreeProcessorSpec.js @@ -274,7 +274,7 @@ describe('TreeProcessor', function() { expect(result.valid).toBe(true); }); - it('runs a single leaf', function() { + it('runs a single leaf', async function() { const leaf = new Leaf(), node = new Node({ children: [leaf], userContext: { root: 'context' } }), queueRunner = jasmine.createSpy('queueRunner'), @@ -282,25 +282,27 @@ describe('TreeProcessor', function() { tree: node, runnableIds: [leaf.id], queueRunnerFactory: queueRunner - }), - treeComplete = jasmine.createSpy('treeComplete'); + }); - processor.execute(treeComplete); + const promise = processor.execute(); expect(queueRunner).toHaveBeenCalledWith({ - onComplete: treeComplete, + onComplete: jasmine.any(Function), onException: jasmine.any(Function), userContext: { root: 'context' }, queueableFns: [{ fn: jasmine.any(Function) }], onMultipleDone: null }); - queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo'); - + const queueRunnerArgs = queueRunner.calls.mostRecent().args[0]; + queueRunnerArgs.queueableFns[0].fn('foo'); expect(leaf.execute).toHaveBeenCalledWith(queueRunner, 'foo', false, false); + + queueRunnerArgs.onComplete(); + await expectAsync(promise).toBeResolvedTo(undefined); }); - it('runs a node with no children', function() { + it('runs a node with no children', async function() { const node = new Node({ userContext: { node: 'context' } }), root = new Node({ children: [node], userContext: { root: 'context' } }), nodeStart = jasmine.createSpy('nodeStart'), @@ -313,21 +315,20 @@ describe('TreeProcessor', function() { nodeComplete: nodeComplete, queueRunnerFactory: queueRunner }), - treeComplete = jasmine.createSpy('treeComplete'), nodeDone = jasmine.createSpy('nodeDone'); - processor.execute(treeComplete); + const promise = processor.execute(); expect(queueRunner).toHaveBeenCalledWith({ - onComplete: treeComplete, + onComplete: jasmine.any(Function), onException: jasmine.any(Function), userContext: { root: 'context' }, queueableFns: [{ fn: jasmine.any(Function) }], onMultipleDone: null }); - queueRunner.calls.mostRecent().args[0].queueableFns[0].fn(nodeDone); - + const queueRunnerArgs = queueRunner.calls.mostRecent().args[0]; + queueRunnerArgs.queueableFns[0].fn(nodeDone); expect(queueRunner).toHaveBeenCalledWith({ onComplete: jasmine.any(Function), onMultipleDone: null, @@ -348,6 +349,9 @@ describe('TreeProcessor', function() { { my: 'result' }, jasmine.any(Function) ); + + queueRunnerArgs.onComplete(); + await expectAsync(promise).toBeResolvedTo(undefined); }); it('runs a node with children', function() { diff --git a/src/core/Runner.js b/src/core/Runner.js index c9e1c70f..5fa2af1f 100644 --- a/src/core/Runner.js +++ b/src/core/Runner.js @@ -136,58 +136,53 @@ getJasmineRequireObj().Runner = function(j$) { }); this.currentlyExecutingSuites_.push(this.topSuite_); + await processor.execute(); - return new Promise(resolve => { - processor.execute(() => { - (async () => { - if (this.topSuite_.hadBeforeAllFailure) { - await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); - } + if (this.topSuite_.hadBeforeAllFailure) { + await this.reportChildrenOfBeforeAllFailure_(this.topSuite_); + } - this.runableResources_.clearForRunable(this.topSuite_.id); - this.currentlyExecutingSuites_.pop(); - let overallStatus, incompleteReason; + this.runableResources_.clearForRunable(this.topSuite_.id); + this.currentlyExecutingSuites_.pop(); + let overallStatus, incompleteReason; - if ( - this.hasFailures || - this.topSuite_.result.failedExpectations.length > 0 - ) { - overallStatus = 'failed'; - } else if (this.focusedRunables_().length > 0) { - overallStatus = 'incomplete'; - incompleteReason = 'fit() or fdescribe() was found'; - } else if (totalSpecsDefined === 0) { - overallStatus = 'incomplete'; - incompleteReason = 'No specs found'; - } else { - overallStatus = 'passed'; - } + if ( + this.hasFailures || + this.topSuite_.result.failedExpectations.length > 0 + ) { + overallStatus = 'failed'; + } else if (this.focusedRunables_().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} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. - * @property {Int} totalTime - The total time (in ms) that it took to execute the suite - * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. - * @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. - * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. - * @since 2.4.0 - */ - const jasmineDoneInfo = { - overallStatus: overallStatus, - totalTime: jasmineTimer.elapsed(), - incompleteReason: incompleteReason, - order: order, - failedExpectations: this.topSuite_.result.failedExpectations, - deprecationWarnings: this.topSuite_.result.deprecationWarnings - }; - this.topSuite_.reportedDone = true; - await this.reporter_.jasmineDone(jasmineDoneInfo); - resolve(jasmineDoneInfo); - })(); - }); - }); + /** + * Information passed to the {@link Reporter#jasmineDone} event. + * @typedef JasmineDoneInfo + * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'. + * @property {Int} totalTime - The total time (in ms) that it took to execute the suite + * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete. + * @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. + * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level. + * @since 2.4.0 + */ + const jasmineDoneInfo = { + overallStatus: overallStatus, + totalTime: jasmineTimer.elapsed(), + incompleteReason: incompleteReason, + order: order, + failedExpectations: this.topSuite_.result.failedExpectations, + deprecationWarnings: this.topSuite_.result.deprecationWarnings + }; + this.topSuite_.reportedDone = true; + await this.reporter_.jasmineDone(jasmineDoneInfo); + return jasmineDoneInfo; } reportSuiteDone_(suite, result, next) { diff --git a/src/core/TreeProcessor.js b/src/core/TreeProcessor.js index 97be7108..2349dcd3 100644 --- a/src/core/TreeProcessor.js +++ b/src/core/TreeProcessor.js @@ -27,7 +27,7 @@ getJasmineRequireObj().TreeProcessor = function() { return stats; }; - this.execute = function(done) { + this.execute = async function() { if (!processed) { this.processTree(); } @@ -38,16 +38,18 @@ getJasmineRequireObj().TreeProcessor = function() { const childFns = wrapChildren(tree, 0); - queueRunnerFactory({ - queueableFns: childFns, - userContext: tree.sharedUserContext(), - onException: function() { - tree.handleException.apply(tree, arguments); - }, - onComplete: done, - onMultipleDone: tree.onMultipleDone - ? tree.onMultipleDone.bind(tree) - : null + await new Promise(function(resolve) { + queueRunnerFactory({ + queueableFns: childFns, + userContext: tree.sharedUserContext(), + onException: function() { + tree.handleException.apply(tree, arguments); + }, + onComplete: resolve, + onMultipleDone: tree.onMultipleDone + ? tree.onMultipleDone.bind(tree) + : null + }); }); };