Runner: naming improvements, use private members

This commit is contained in:
Steve Gravrock
2025-08-11 23:17:52 -07:00
parent c15a1aaa6d
commit 8eee6ebb91
4 changed files with 155 additions and 129 deletions

View File

@@ -1245,7 +1245,7 @@ getJasmineRequireObj().Env = function(j$) {
globalErrors
});
let reporter;
let reportDispatcher;
let topSuite;
let runner;
let parallelLoadingState = null; // 'specs', 'helpers', or null for non-parallel
@@ -1698,7 +1698,7 @@ getJasmineRequireObj().Env = function(j$) {
* @interface Reporter
* @see custom_reporter
*/
reporter = new j$.ReportDispatcher(
reportDispatcher = new j$.ReportDispatcher(
j$.reporterEvents,
function(options) {
options.SkipPolicy = j$.NeverSkipPolicy;
@@ -1712,7 +1712,7 @@ getJasmineRequireObj().Env = function(j$) {
totalSpecsDefined: () => suiteBuilder.totalSpecsDefined,
focusedRunables: () => suiteBuilder.focusedRunables,
runableResources,
reporter,
reporter: reportDispatcher,
runQueue,
TreeProcessor: j$.TreeProcessor,
globalErrors,
@@ -1780,7 +1780,7 @@ getJasmineRequireObj().Env = function(j$) {
throw new Error('Reporters cannot be added via Env in parallel mode');
}
reporter.addReporter(reporterToAdd);
reportDispatcher.addReporter(reporterToAdd);
};
/**
@@ -1792,7 +1792,7 @@ getJasmineRequireObj().Env = function(j$) {
* @see custom_reporter
*/
this.provideFallbackReporter = function(reporterToAdd) {
reporter.provideFallbackReporter(reporterToAdd);
reportDispatcher.provideFallbackReporter(reporterToAdd);
};
/**
@@ -1806,7 +1806,7 @@ getJasmineRequireObj().Env = function(j$) {
throw new Error('Reporters cannot be removed via Env in parallel mode');
}
reporter.clearReporters();
reportDispatcher.clearReporters();
};
/**
@@ -1973,12 +1973,12 @@ getJasmineRequireObj().Env = function(j$) {
function specStarted(spec, suite, next) {
runner.currentSpec = spec;
runableResources.initForRunable(spec.id, suite.id);
reporter.specStarted(spec.result).then(next);
reportDispatcher.specStarted(spec.result).then(next);
}
function reportSpecDone(spec, result, next) {
spec.reportedDone = true;
reporter.specDone(result).then(next);
reportDispatcher.specDone(result).then(next);
}
this.it = function(description, fn, timeout) {
@@ -9401,20 +9401,31 @@ getJasmineRequireObj().RunableResources = function(j$) {
getJasmineRequireObj().Runner = function(j$) {
class Runner {
#topSuite;
#getTotalSpecsDefined;
#getFocusedRunables;
#runableResources;
#runQueue;
#TreeProcessor;
#globalErrors;
#reportDispatcher;
#getConfig;
#reportSpecDone;
#executedBefore;
constructor(options) {
this.topSuite_ = options.topSuite;
// TODO use names that read like getters
this.totalSpecsDefined_ = options.totalSpecsDefined;
this.focusedRunables_ = options.focusedRunables;
this.runableResources_ = options.runableResources;
this.runQueue_ = options.runQueue;
this.TreeProcessor_ = options.TreeProcessor;
this.globalErrors_ = options.globalErrors;
this.reporter_ = options.reporter;
this.getConfig_ = options.getConfig;
this.reportSpecDone_ = options.reportSpecDone;
this.#topSuite = options.topSuite;
this.#getTotalSpecsDefined = options.totalSpecsDefined;
this.#getFocusedRunables = options.focusedRunables;
this.#runableResources = options.runableResources;
this.#runQueue = options.runQueue;
this.#TreeProcessor = options.TreeProcessor;
this.#globalErrors = options.globalErrors;
this.#reportDispatcher = options.reporter;
this.#getConfig = options.getConfig;
this.#reportSpecDone = options.reportSpecDone;
this.hasFailures = false;
this.executedBefore_ = false;
this.#executedBefore = false;
this.currentlyExecutingSuites_ = [];
this.currentSpec = null;
@@ -9431,24 +9442,24 @@ getJasmineRequireObj().Runner = function(j$) {
}
parallelReset() {
this.executedBefore_ = false;
this.#executedBefore = false;
}
async execute(runablesToRun) {
if (this.executedBefore_) {
this.topSuite_.reset();
if (this.#executedBefore) {
this.#topSuite.reset();
}
this.executedBefore_ = true;
this.#executedBefore = true;
this.hasFailures = false;
const focusedRunables = this.focusedRunables_();
const config = this.getConfig_();
const focusedRunables = this.#getFocusedRunables();
const config = this.#getConfig();
if (!runablesToRun) {
if (focusedRunables.length) {
runablesToRun = focusedRunables;
} else {
runablesToRun = [this.topSuite_.id];
runablesToRun = [this.#topSuite.id];
}
}
@@ -9457,8 +9468,8 @@ getJasmineRequireObj().Runner = function(j$) {
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
});
const processor = new this.TreeProcessor_({
tree: this.topSuite_,
const processor = new this.#TreeProcessor({
tree: this.#topSuite,
runnableIds: runablesToRun,
runQueue: options => {
if (options.isLeaf) {
@@ -9473,15 +9484,15 @@ getJasmineRequireObj().Runner = function(j$) {
}
}
return this.runQueue_(options);
return this.#runQueue(options);
},
globalErrors: this.globalErrors_,
globalErrors: this.#globalErrors,
failSpecWithNoExpectations: config.failSpecWithNoExpectations,
detectLateRejectionHandling: config.detectLateRejectionHandling,
nodeStart: (suite, next) => {
this.currentlyExecutingSuites_.push(suite);
this.runableResources_.initForRunable(suite.id, suite.parentSuite.id);
this.reporter_.suiteStarted(suite.result).then(next);
this.#runableResources.initForRunable(suite.id, suite.parentSuite.id);
this.#reportDispatcher.suiteStarted(suite.result).then(next);
suite.startTimer();
},
nodeComplete: (suite, result, next) => {
@@ -9489,7 +9500,7 @@ getJasmineRequireObj().Runner = function(j$) {
throw new Error('Tried to complete the wrong suite');
}
this.runableResources_.clearForRunable(suite.id);
this.#runableResources.clearForRunable(suite.id);
this.currentlyExecutingSuites_.pop();
if (result.status === 'failed') {
@@ -9498,11 +9509,11 @@ getJasmineRequireObj().Runner = function(j$) {
suite.endTimer();
if (suite.hadBeforeAllFailure) {
this.reportChildrenOfBeforeAllFailure_(suite).then(() => {
this.reportSuiteDone_(suite, result, next);
this.#reportChildrenOfBeforeAllFailure(suite).then(() => {
this.#reportSuiteDone(suite, result, next);
});
} else {
this.reportSuiteDone_(suite, result, next);
this.#reportSuiteDone(suite, result, next);
}
},
orderChildren: function(node) {
@@ -9519,13 +9530,13 @@ getJasmineRequireObj().Runner = function(j$) {
);
}
return this.execute2_(runablesToRun, order, processor);
return this.#execute2(runablesToRun, order, processor);
}
async execute2_(runablesToRun, order, processor) {
const totalSpecsDefined = this.totalSpecsDefined_();
async #execute2(runablesToRun, order, processor) {
const totalSpecsDefined = this.#getTotalSpecsDefined();
this.runableResources_.initForRunable(this.topSuite_.id);
this.#runableResources.initForRunable(this.#topSuite.id);
const jasmineTimer = new j$.Timer();
jasmineTimer.start();
@@ -9537,7 +9548,7 @@ getJasmineRequireObj().Runner = function(j$) {
* @property {Boolean} parallel - Whether Jasmine is being run in parallel mode.
* @since 2.0.0
*/
await this.reporter_.jasmineStarted({
await this.#reportDispatcher.jasmineStarted({
// In parallel mode, the jasmineStarted event is separately dispatched
// by jasmine-npm. This event only reaches reporters in non-parallel.
totalSpecsDefined,
@@ -9545,23 +9556,23 @@ getJasmineRequireObj().Runner = function(j$) {
parallel: false
});
this.currentlyExecutingSuites_.push(this.topSuite_);
this.currentlyExecutingSuites_.push(this.#topSuite);
await processor.execute();
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.#runableResources.clearForRunable(this.#topSuite.id);
this.currentlyExecutingSuites_.pop();
let overallStatus, incompleteReason, incompleteCode;
if (
this.hasFailures ||
this.topSuite_.result.failedExpectations.length > 0
this.#topSuite.result.failedExpectations.length > 0
) {
overallStatus = 'failed';
} else if (this.focusedRunables_().length > 0) {
} else if (this.#getFocusedRunables().length > 0) {
overallStatus = 'incomplete';
incompleteReason = 'fit() or fdescribe() was found';
incompleteCode = 'focused';
@@ -9592,33 +9603,33 @@ getJasmineRequireObj().Runner = function(j$) {
incompleteReason: incompleteReason,
incompleteCode: incompleteCode,
order: order,
failedExpectations: this.topSuite_.result.failedExpectations,
deprecationWarnings: this.topSuite_.result.deprecationWarnings
failedExpectations: this.#topSuite.result.failedExpectations,
deprecationWarnings: this.#topSuite.result.deprecationWarnings
};
this.topSuite_.reportedDone = true;
await this.reporter_.jasmineDone(jasmineDoneInfo);
this.#topSuite.reportedDone = true;
await this.#reportDispatcher.jasmineDone(jasmineDoneInfo);
return jasmineDoneInfo;
}
reportSuiteDone_(suite, result, next) {
#reportSuiteDone(suite, result, next) {
suite.reportedDone = true;
this.reporter_.suiteDone(result).then(next);
this.#reportDispatcher.suiteDone(result).then(next);
}
async reportChildrenOfBeforeAllFailure_(suite) {
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
await this.reporter_.suiteStarted(child.result);
await this.reportChildrenOfBeforeAllFailure_(child);
await this.#reportDispatcher.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 this.reporter_.suiteDone(child.result);
await this.#reportDispatcher.suiteDone(child.result);
} else {
/* a spec */
await this.reporter_.specStarted(child.result);
await this.#reportDispatcher.specStarted(child.result);
child.addExpectationResult(
false,
@@ -9634,7 +9645,7 @@ getJasmineRequireObj().Runner = function(j$) {
child.result.status = 'failed';
await new Promise(resolve => {
this.reportSpecDone_(child, child.result, resolve);
this.#reportSpecDone(child, child.result, resolve);
});
}
}

View File

@@ -129,11 +129,11 @@ describe('Runner', function() {
describe('reporting', function() {
it('reports the suiteDone event', async function() {
const TreeProcessor = spyTreeProcessorCtor();
const reporter = spyReporter();
const reportDispatcher = spyReporter();
const subject = new jasmineUnderTest.Runner({
...defaultCtorOptions(),
TreeProcessor,
reporter
reportDispatcher
});
const promise = subject.execute();
@@ -152,13 +152,13 @@ describe('Runner', function() {
{ status: 'passed' }
]);
expect(reporter.suiteDone).toHaveBeenCalled();
expect(reportDispatcher.suiteDone).toHaveBeenCalled();
});
describe('when the suite had a beforeAll failure', function() {
it('reports children before the suiteDone event', async function() {
const TreeProcessor = spyTreeProcessorCtor();
const reporter = spyReporter();
const reportDispatcher = spyReporter();
const reportSpecDone = jasmine
.createSpy('reportSpecDone')
.and.callFake(function(child, result, next) {
@@ -167,7 +167,7 @@ describe('Runner', function() {
const subject = new jasmineUnderTest.Runner({
...defaultCtorOptions(),
TreeProcessor,
reporter,
reportDispatcher,
reportSpecDone
});
@@ -209,8 +209,12 @@ describe('Runner', function() {
expect(
suiteToRun.children[0].addExpectationResult
).toHaveBeenCalledBefore(reportSpecDone);
expect(reportSpecDone).toHaveBeenCalledBefore(reporter.suiteDone);
expect(reporter.specStarted).toHaveBeenCalledBefore(reportSpecDone);
expect(reportSpecDone).toHaveBeenCalledBefore(
reportDispatcher.suiteDone
);
expect(reportDispatcher.specStarted).toHaveBeenCalledBefore(
reportSpecDone
);
});
});
});
@@ -238,7 +242,7 @@ describe('Runner', function() {
}
function spyReporter() {
return jasmine.createSpyObj('reporter', {
return jasmine.createSpyObj('reportDispatcher', {
jasmineStarted: Promise.resolve(),
jasmineDone: Promise.resolve(),
suiteStarted: Promise.resolve(),
@@ -255,7 +259,7 @@ describe('Runner', function() {
initForRunable: () => {},
clearForRunable: () => {}
},
reporter: spyReporter(),
reportDispatcher: spyReporter(),
focusedRunables: () => [],
getConfig: () => ({}),
totalSpecsDefined: () => 1

View File

@@ -49,7 +49,7 @@ getJasmineRequireObj().Env = function(j$) {
globalErrors
});
let reporter;
let reportDispatcher;
let topSuite;
let runner;
let parallelLoadingState = null; // 'specs', 'helpers', or null for non-parallel
@@ -502,7 +502,7 @@ getJasmineRequireObj().Env = function(j$) {
* @interface Reporter
* @see custom_reporter
*/
reporter = new j$.ReportDispatcher(
reportDispatcher = new j$.ReportDispatcher(
j$.reporterEvents,
function(options) {
options.SkipPolicy = j$.NeverSkipPolicy;
@@ -516,7 +516,7 @@ getJasmineRequireObj().Env = function(j$) {
totalSpecsDefined: () => suiteBuilder.totalSpecsDefined,
focusedRunables: () => suiteBuilder.focusedRunables,
runableResources,
reporter,
reportDispatcher,
runQueue,
TreeProcessor: j$.TreeProcessor,
globalErrors,
@@ -584,7 +584,7 @@ getJasmineRequireObj().Env = function(j$) {
throw new Error('Reporters cannot be added via Env in parallel mode');
}
reporter.addReporter(reporterToAdd);
reportDispatcher.addReporter(reporterToAdd);
};
/**
@@ -596,7 +596,7 @@ getJasmineRequireObj().Env = function(j$) {
* @see custom_reporter
*/
this.provideFallbackReporter = function(reporterToAdd) {
reporter.provideFallbackReporter(reporterToAdd);
reportDispatcher.provideFallbackReporter(reporterToAdd);
};
/**
@@ -610,7 +610,7 @@ getJasmineRequireObj().Env = function(j$) {
throw new Error('Reporters cannot be removed via Env in parallel mode');
}
reporter.clearReporters();
reportDispatcher.clearReporters();
};
/**
@@ -777,12 +777,12 @@ getJasmineRequireObj().Env = function(j$) {
function specStarted(spec, suite, next) {
runner.currentSpec = spec;
runableResources.initForRunable(spec.id, suite.id);
reporter.specStarted(spec.result).then(next);
reportDispatcher.specStarted(spec.result).then(next);
}
function reportSpecDone(spec, result, next) {
spec.reportedDone = true;
reporter.specDone(result).then(next);
reportDispatcher.specDone(result).then(next);
}
this.it = function(description, fn, timeout) {

View File

@@ -1,19 +1,30 @@
getJasmineRequireObj().Runner = function(j$) {
class Runner {
#topSuite;
#getTotalSpecsDefined;
#getFocusedRunables;
#runableResources;
#runQueue;
#TreeProcessor;
#globalErrors;
#reportDispatcher;
#getConfig;
#reportSpecDone;
#executedBefore;
constructor(options) {
this.topSuite_ = options.topSuite;
// TODO use names that read like getters
this.totalSpecsDefined_ = options.totalSpecsDefined;
this.focusedRunables_ = options.focusedRunables;
this.runableResources_ = options.runableResources;
this.runQueue_ = options.runQueue;
this.TreeProcessor_ = options.TreeProcessor;
this.globalErrors_ = options.globalErrors;
this.reporter_ = options.reporter;
this.getConfig_ = options.getConfig;
this.reportSpecDone_ = options.reportSpecDone;
this.#topSuite = options.topSuite;
this.#getTotalSpecsDefined = options.totalSpecsDefined;
this.#getFocusedRunables = options.focusedRunables;
this.#runableResources = options.runableResources;
this.#runQueue = options.runQueue;
this.#TreeProcessor = options.TreeProcessor;
this.#globalErrors = options.globalErrors;
this.#reportDispatcher = options.reportDispatcher;
this.#getConfig = options.getConfig;
this.#reportSpecDone = options.reportSpecDone;
this.hasFailures = false;
this.executedBefore_ = false;
this.#executedBefore = false;
this.currentlyExecutingSuites_ = [];
this.currentSpec = null;
@@ -30,24 +41,24 @@ getJasmineRequireObj().Runner = function(j$) {
}
parallelReset() {
this.executedBefore_ = false;
this.#executedBefore = false;
}
async execute(runablesToRun) {
if (this.executedBefore_) {
this.topSuite_.reset();
if (this.#executedBefore) {
this.#topSuite.reset();
}
this.executedBefore_ = true;
this.#executedBefore = true;
this.hasFailures = false;
const focusedRunables = this.focusedRunables_();
const config = this.getConfig_();
const focusedRunables = this.#getFocusedRunables();
const config = this.#getConfig();
if (!runablesToRun) {
if (focusedRunables.length) {
runablesToRun = focusedRunables;
} else {
runablesToRun = [this.topSuite_.id];
runablesToRun = [this.#topSuite.id];
}
}
@@ -56,8 +67,8 @@ getJasmineRequireObj().Runner = function(j$) {
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
});
const processor = new this.TreeProcessor_({
tree: this.topSuite_,
const processor = new this.#TreeProcessor({
tree: this.#topSuite,
runnableIds: runablesToRun,
runQueue: options => {
if (options.isLeaf) {
@@ -72,15 +83,15 @@ getJasmineRequireObj().Runner = function(j$) {
}
}
return this.runQueue_(options);
return this.#runQueue(options);
},
globalErrors: this.globalErrors_,
globalErrors: this.#globalErrors,
failSpecWithNoExpectations: config.failSpecWithNoExpectations,
detectLateRejectionHandling: config.detectLateRejectionHandling,
nodeStart: (suite, next) => {
this.currentlyExecutingSuites_.push(suite);
this.runableResources_.initForRunable(suite.id, suite.parentSuite.id);
this.reporter_.suiteStarted(suite.result).then(next);
this.#runableResources.initForRunable(suite.id, suite.parentSuite.id);
this.#reportDispatcher.suiteStarted(suite.result).then(next);
suite.startTimer();
},
nodeComplete: (suite, result, next) => {
@@ -88,7 +99,7 @@ getJasmineRequireObj().Runner = function(j$) {
throw new Error('Tried to complete the wrong suite');
}
this.runableResources_.clearForRunable(suite.id);
this.#runableResources.clearForRunable(suite.id);
this.currentlyExecutingSuites_.pop();
if (result.status === 'failed') {
@@ -97,11 +108,11 @@ getJasmineRequireObj().Runner = function(j$) {
suite.endTimer();
if (suite.hadBeforeAllFailure) {
this.reportChildrenOfBeforeAllFailure_(suite).then(() => {
this.reportSuiteDone_(suite, result, next);
this.#reportChildrenOfBeforeAllFailure(suite).then(() => {
this.#reportSuiteDone(suite, result, next);
});
} else {
this.reportSuiteDone_(suite, result, next);
this.#reportSuiteDone(suite, result, next);
}
},
orderChildren: function(node) {
@@ -118,13 +129,13 @@ getJasmineRequireObj().Runner = function(j$) {
);
}
return this.execute2_(runablesToRun, order, processor);
return this.#execute2(runablesToRun, order, processor);
}
async execute2_(runablesToRun, order, processor) {
const totalSpecsDefined = this.totalSpecsDefined_();
async #execute2(runablesToRun, order, processor) {
const totalSpecsDefined = this.#getTotalSpecsDefined();
this.runableResources_.initForRunable(this.topSuite_.id);
this.#runableResources.initForRunable(this.#topSuite.id);
const jasmineTimer = new j$.Timer();
jasmineTimer.start();
@@ -136,7 +147,7 @@ getJasmineRequireObj().Runner = function(j$) {
* @property {Boolean} parallel - Whether Jasmine is being run in parallel mode.
* @since 2.0.0
*/
await this.reporter_.jasmineStarted({
await this.#reportDispatcher.jasmineStarted({
// In parallel mode, the jasmineStarted event is separately dispatched
// by jasmine-npm. This event only reaches reporters in non-parallel.
totalSpecsDefined,
@@ -144,23 +155,23 @@ getJasmineRequireObj().Runner = function(j$) {
parallel: false
});
this.currentlyExecutingSuites_.push(this.topSuite_);
this.currentlyExecutingSuites_.push(this.#topSuite);
await processor.execute();
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.#runableResources.clearForRunable(this.#topSuite.id);
this.currentlyExecutingSuites_.pop();
let overallStatus, incompleteReason, incompleteCode;
if (
this.hasFailures ||
this.topSuite_.result.failedExpectations.length > 0
this.#topSuite.result.failedExpectations.length > 0
) {
overallStatus = 'failed';
} else if (this.focusedRunables_().length > 0) {
} else if (this.#getFocusedRunables().length > 0) {
overallStatus = 'incomplete';
incompleteReason = 'fit() or fdescribe() was found';
incompleteCode = 'focused';
@@ -191,33 +202,33 @@ getJasmineRequireObj().Runner = function(j$) {
incompleteReason: incompleteReason,
incompleteCode: incompleteCode,
order: order,
failedExpectations: this.topSuite_.result.failedExpectations,
deprecationWarnings: this.topSuite_.result.deprecationWarnings
failedExpectations: this.#topSuite.result.failedExpectations,
deprecationWarnings: this.#topSuite.result.deprecationWarnings
};
this.topSuite_.reportedDone = true;
await this.reporter_.jasmineDone(jasmineDoneInfo);
this.#topSuite.reportedDone = true;
await this.#reportDispatcher.jasmineDone(jasmineDoneInfo);
return jasmineDoneInfo;
}
reportSuiteDone_(suite, result, next) {
#reportSuiteDone(suite, result, next) {
suite.reportedDone = true;
this.reporter_.suiteDone(result).then(next);
this.#reportDispatcher.suiteDone(result).then(next);
}
async reportChildrenOfBeforeAllFailure_(suite) {
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
await this.reporter_.suiteStarted(child.result);
await this.reportChildrenOfBeforeAllFailure_(child);
await this.#reportDispatcher.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 this.reporter_.suiteDone(child.result);
await this.#reportDispatcher.suiteDone(child.result);
} else {
/* a spec */
await this.reporter_.specStarted(child.result);
await this.#reportDispatcher.specStarted(child.result);
child.addExpectationResult(
false,
@@ -233,7 +244,7 @@ getJasmineRequireObj().Runner = function(j$) {
child.result.status = 'failed';
await new Promise(resolve => {
this.reportSpecDone_(child, child.result, resolve);
this.#reportSpecDone(child, child.result, resolve);
});
}
}