diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 75a341e8..86fa8bd6 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -89,7 +89,9 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy( j$ ); + j$.reporterEvents = jRequire.reporterEvents(j$); j$.ReportDispatcher = jRequire.ReportDispatcher(j$); + j$.ParallelReportDispatcher = jRequire.ParallelReportDispatcher(j$); j$.RunableResources = jRequire.RunableResources(j$); j$.Runner = jRequire.Runner(j$); j$.Spec = jRequire.Spec(j$); @@ -1555,72 +1557,7 @@ getJasmineRequireObj().Env = function(j$) { * @see custom_reporter */ 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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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. - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - 'specDone' - ], + j$.reporterEvents, function(options) { options.SkipPolicy = j$.NeverSkipPolicy; return queueRunnerFactory(options); @@ -7172,6 +7109,72 @@ getJasmineRequireObj().NeverSkipPolicy = function(j$) { return NeverSkipPolicy; }; +getJasmineRequireObj().ParallelReportDispatcher = function(j$) { + /* + A report dispatcher packaged for convenient use from outside jasmine-core. + + This isn't part of the public interface, but it is used by + jasmine-npm. -core and -npm version in lockstep at the major and minor + levels but version independently at the patch level. Any changes that + would break -npm should be done in a major or minor release, never a + patch release, and accompanied by a change to -npm that's released in + the same version. + */ + function ParallelReportDispatcher(onError, deps = {}) { + const ReportDispatcher = deps.ReportDispatcher || j$.ReportDispatcher; + const QueueRunner = deps.QueueRunner || j$.QueueRunner; + const globalErrors = deps.globalErrors || new j$.GlobalErrors(); + const dispatcher = ReportDispatcher( + j$.reporterEvents, + function(queueRunnerOptions) { + queueRunnerOptions = { + ...queueRunnerOptions, + globalErrors, + timeout: { setTimeout, clearTimeout }, + fail: function(error) { + // A callback-style async reporter called either done.fail() + // or done(anError). + if (!error) { + error = new Error('A reporter called done.fail()'); + } + + onError(error); + }, + onException: function(error) { + // A reporter method threw an exception or returned a rejected + // promise, or there was an unhandled exception or unhandled promise + // rejection while an asynchronous reporter method was running. + onError(error); + } + }; + new QueueRunner(queueRunnerOptions).execute(); + }, + function(error) { + // A reporter called done() more than once. + onError(error); + } + ); + + const self = { + addReporter: dispatcher.addReporter.bind(dispatcher), + clearReporters: dispatcher.clearReporters.bind(dispatcher), + installGlobalErrors: globalErrors.install.bind(globalErrors), + uninstallGlobalErrors: function() { + // late-bind uninstall because it doesn't exist until install is called + globalErrors.uninstall(globalErrors); + } + }; + + for (const eventName of j$.reporterEvents) { + self[eventName] = dispatcher[eventName].bind(dispatcher); + } + + return self; + } + + return ParallelReportDispatcher; +}; + getJasmineRequireObj().makePrettyPrinter = function(j$) { class SinglePrettyPrintRun { constructor(customObjectFormatters, pp) { @@ -7798,17 +7801,21 @@ getJasmineRequireObj().QueueRunner = function(j$) { // on the stack at this point. if (j$.isAsyncFunction_(fn)) { this.onException( - 'An asynchronous before/it/after ' + - 'function was defined with the async keyword but also took a ' + - 'done callback. Either remove the done callback (recommended) or ' + - 'remove the async keyword.' + new Error( + 'An asynchronous before/it/after ' + + 'function was defined with the async keyword but also took a ' + + 'done callback. Either remove the done callback (recommended) or ' + + 'remove the async keyword.' + ) ); } else { this.onException( - 'An asynchronous before/it/after ' + - 'function took a done callback but also returned a promise. ' + - 'Either remove the done callback (recommended) or change the ' + - 'function to not return a promise.' + new Error( + 'An asynchronous before/it/after ' + + 'function took a done callback but also returned a promise. ' + + 'Either remove the done callback (recommended) or change the ' + + 'function to not return a promise.' + ) ); } } @@ -7917,6 +7924,77 @@ getJasmineRequireObj().ReportDispatcher = function(j$) { return ReportDispatcher; }; +getJasmineRequireObj().reporterEvents = function() { + const events = [ + /** + * `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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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. + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + 'specDone' + ]; + Object.freeze(events); + return events; +}; + getJasmineRequireObj().interface = function(jasmine, env) { const jasmineInterface = { /** diff --git a/spec/core/ParallelReportDispatcherSpec.js b/spec/core/ParallelReportDispatcherSpec.js new file mode 100644 index 00000000..b4d2e137 --- /dev/null +++ b/spec/core/ParallelReportDispatcherSpec.js @@ -0,0 +1,176 @@ +describe('ParallelReportDispatcher', function() { + it('dispatches the standard reporter events', async function() { + const subject = new jasmineUnderTest.ParallelReportDispatcher(() => {}, { + globalErrors: mockGlobalErrors() + }); + const events = [ + 'jasmineStarted', + 'jasmineDone', + 'suiteStarted', + 'suiteDone', + 'specStarted', + 'specDone' + ]; + const reporter = jasmine.createSpyObj('reporter', events); + subject.addReporter(reporter); + + for (const eventName of events) { + const payload = { payloadFor: eventName }; + await subject[eventName](payload); + expect(reporter[eventName]).toHaveBeenCalledWith(payload); + } + }); + + it('installs and uninstalls the global error handler', function() { + const globalErrors = mockGlobalErrors(); + const subject = new jasmineUnderTest.ParallelReportDispatcher(() => {}, { + globalErrors + }); + + subject.installGlobalErrors(); + expect(globalErrors.install).toHaveBeenCalled(); + + subject.uninstallGlobalErrors(); + expect(globalErrors.uninstall).toHaveBeenCalled(); + }); + + it('handles global errors from async reporters', async function() { + const globalErrors = mockGlobalErrors(); + const onError = jasmine.createSpy('onError'); + const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, { + globalErrors + }); + const reporter = jasmine.createSpyObj('reporter', [ + 'jasmineStarted', + 'jasmineDone' + ]); + let resolveStarted; + reporter.jasmineStarted.and.callFake(function() { + return new Promise(function(res) { + resolveStarted = res; + }); + }); + subject.addReporter(reporter); + + const promise = subject.jasmineStarted({}); + expect(globalErrors.pushListener).toHaveBeenCalled(); + expect(globalErrors.popListener).not.toHaveBeenCalled(); + const error = new Error('nope'); + globalErrors.pushListener.calls.argsFor(0)[0](error); + expect(onError).toHaveBeenCalledWith(error); + + resolveStarted(); + await promise; + expect(globalErrors.popListener).toHaveBeenCalled(); + }); + + it('handles done(error) from callback-style async reporters', function() { + const globalErrors = mockGlobalErrors(); + const onError = jasmine.createSpy('onError'); + const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, { + globalErrors + }); + const reporter = jasmine.createSpyObj('reporter', [ + 'jasmineStarted', + 'jasmineDone' + ]); + let callback; + reporter.jasmineStarted = function(event, cb) { + callback = cb; + }; + subject.addReporter(reporter); + + subject.jasmineStarted({}); + + expect(callback).toBeInstanceOf(Function); + const error = new Error('nope'); + callback(error); + + expect(onError).toHaveBeenCalledWith(error); + }); + + it('handles done.fail() from callback-style async reporters', function() { + const globalErrors = mockGlobalErrors(); + const onError = jasmine.createSpy('onError'); + const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, { + globalErrors + }); + const reporter = jasmine.createSpyObj('reporter', [ + 'jasmineStarted', + 'jasmineDone' + ]); + let callback; + reporter.jasmineStarted = function(event, cb) { + callback = cb; + }; + subject.addReporter(reporter); + + subject.jasmineStarted({}); + + expect(callback).toBeInstanceOf(Function); + const error = new Error('nope'); + callback.fail(error); + expect(onError).toHaveBeenCalledWith(error); + onError.calls.reset(); + + callback.fail(); + expect(onError).toHaveBeenCalledWith( + new Error('A reporter called done.fail()') + ); + }); + + it('handles errors due to mixed async style in reporters', async function() { + const globalErrors = mockGlobalErrors(); + const onError = jasmine.createSpy('onError'); + const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, { + globalErrors + }); + subject.addReporter({ + async jasmineStarted(event, done) { + done(); + } + }); + + await subject.jasmineStarted({}); + expect(onError).toHaveBeenCalledWith( + new Error( + 'An asynchronous before/it/after function took a done callback but also returned a promise. Either remove the done callback (recommended) or change the function to not return a promise.' + ) + ); + }); + + it('handles errors due to multiple done calls in reporters', async function() { + const globalErrors = mockGlobalErrors(); + const onError = jasmine.createSpy('onError'); + const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, { + globalErrors + }); + subject.addReporter({ + jasmineStarted(event, done) { + done(); + done(); + } + }); + + await subject.jasmineStarted({}); + expect(onError).toHaveBeenCalledWith( + new Error( + "An asynchronous reporter callback called its 'done' callback more than once." + ) + ); + }); + + function mockGlobalErrors() { + const globalErrors = jasmine.createSpyObj('globalErrors', [ + 'install', + 'pushListener', + 'popListener' + ]); + + globalErrors.install.and.callFake(function() { + globalErrors.uninstall = jasmine.createSpy('globalErrors.uninstall'); + }); + + return globalErrors; + } +}); diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index 276e4eea..ed743b7f 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -595,11 +595,13 @@ describe('QueueRunner', function() { queueRunner.execute(); expect(onException).toHaveBeenCalledWith( - 'An asynchronous ' + - 'before/it/after function took a done callback but also returned a ' + - 'promise. ' + - 'Either remove the done callback (recommended) or change the function ' + - 'to not return a promise.' + new Error( + 'An asynchronous ' + + 'before/it/after function took a done callback but also returned a ' + + 'promise. ' + + 'Either remove the done callback (recommended) or change the function ' + + 'to not return a promise.' + ) ); }); @@ -615,10 +617,12 @@ describe('QueueRunner', function() { queueRunner.execute(); expect(onException).toHaveBeenCalledWith( - 'An asynchronous ' + - 'before/it/after function was defined with the async keyword but ' + - 'also took a done callback. Either remove the done callback ' + - '(recommended) or remove the async keyword.' + new Error( + 'An asynchronous ' + + 'before/it/after function was defined with the async keyword but ' + + 'also took a done callback. Either remove the done callback ' + + '(recommended) or remove the async keyword.' + ) ); }); }); diff --git a/src/core/Env.js b/src/core/Env.js index 360bf441..355a22d7 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -420,72 +420,7 @@ getJasmineRequireObj().Env = function(j$) { * @see custom_reporter */ 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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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. - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - '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 - * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. - * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. - * @see async - */ - 'specDone' - ], + j$.reporterEvents, function(options) { options.SkipPolicy = j$.NeverSkipPolicy; return queueRunnerFactory(options); diff --git a/src/core/ParallelReportDispatcher.js b/src/core/ParallelReportDispatcher.js new file mode 100644 index 00000000..fc508eb9 --- /dev/null +++ b/src/core/ParallelReportDispatcher.js @@ -0,0 +1,65 @@ +getJasmineRequireObj().ParallelReportDispatcher = function(j$) { + /* + A report dispatcher packaged for convenient use from outside jasmine-core. + + This isn't part of the public interface, but it is used by + jasmine-npm. -core and -npm version in lockstep at the major and minor + levels but version independently at the patch level. Any changes that + would break -npm should be done in a major or minor release, never a + patch release, and accompanied by a change to -npm that's released in + the same version. + */ + function ParallelReportDispatcher(onError, deps = {}) { + const ReportDispatcher = deps.ReportDispatcher || j$.ReportDispatcher; + const QueueRunner = deps.QueueRunner || j$.QueueRunner; + const globalErrors = deps.globalErrors || new j$.GlobalErrors(); + const dispatcher = ReportDispatcher( + j$.reporterEvents, + function(queueRunnerOptions) { + queueRunnerOptions = { + ...queueRunnerOptions, + globalErrors, + timeout: { setTimeout, clearTimeout }, + fail: function(error) { + // A callback-style async reporter called either done.fail() + // or done(anError). + if (!error) { + error = new Error('A reporter called done.fail()'); + } + + onError(error); + }, + onException: function(error) { + // A reporter method threw an exception or returned a rejected + // promise, or there was an unhandled exception or unhandled promise + // rejection while an asynchronous reporter method was running. + onError(error); + } + }; + new QueueRunner(queueRunnerOptions).execute(); + }, + function(error) { + // A reporter called done() more than once. + onError(error); + } + ); + + const self = { + addReporter: dispatcher.addReporter.bind(dispatcher), + clearReporters: dispatcher.clearReporters.bind(dispatcher), + installGlobalErrors: globalErrors.install.bind(globalErrors), + uninstallGlobalErrors: function() { + // late-bind uninstall because it doesn't exist until install is called + globalErrors.uninstall(globalErrors); + } + }; + + for (const eventName of j$.reporterEvents) { + self[eventName] = dispatcher[eventName].bind(dispatcher); + } + + return self; + } + + return ParallelReportDispatcher; +}; diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index 7667af68..65bdc4df 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -264,17 +264,21 @@ getJasmineRequireObj().QueueRunner = function(j$) { // on the stack at this point. if (j$.isAsyncFunction_(fn)) { this.onException( - 'An asynchronous before/it/after ' + - 'function was defined with the async keyword but also took a ' + - 'done callback. Either remove the done callback (recommended) or ' + - 'remove the async keyword.' + new Error( + 'An asynchronous before/it/after ' + + 'function was defined with the async keyword but also took a ' + + 'done callback. Either remove the done callback (recommended) or ' + + 'remove the async keyword.' + ) ); } else { this.onException( - 'An asynchronous before/it/after ' + - 'function took a done callback but also returned a promise. ' + - 'Either remove the done callback (recommended) or change the ' + - 'function to not return a promise.' + new Error( + 'An asynchronous before/it/after ' + + 'function took a done callback but also returned a promise. ' + + 'Either remove the done callback (recommended) or change the ' + + 'function to not return a promise.' + ) ); } } diff --git a/src/core/reporterEvents.js b/src/core/reporterEvents.js new file mode 100644 index 00000000..828e87a6 --- /dev/null +++ b/src/core/reporterEvents.js @@ -0,0 +1,70 @@ +getJasmineRequireObj().reporterEvents = function() { + const events = [ + /** + * `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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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. + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + '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 + * @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on. + * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion. + * @see async + */ + 'specDone' + ]; + Object.freeze(events); + return events; +}; diff --git a/src/core/requireCore.js b/src/core/requireCore.js index dacd9557..c0f9c884 100644 --- a/src/core/requireCore.js +++ b/src/core/requireCore.js @@ -67,7 +67,9 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy( j$ ); + j$.reporterEvents = jRequire.reporterEvents(j$); j$.ReportDispatcher = jRequire.ReportDispatcher(j$); + j$.ParallelReportDispatcher = jRequire.ParallelReportDispatcher(j$); j$.RunableResources = jRequire.RunableResources(j$); j$.Runner = jRequire.Runner(j$); j$.Spec = jRequire.Spec(j$);