Move spec begin and end handling from Env/SuiteBuilder to TreeRunner

This commit is contained in:
Steve Gravrock
2025-08-20 20:53:18 -07:00
parent 759a867094
commit 164a393932
11 changed files with 398 additions and 224 deletions

View File

@@ -94,6 +94,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.reporterEvents = jRequire.reporterEvents(j$);
j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
j$.ParallelReportDispatcher = jRequire.ParallelReportDispatcher(j$);
j$.CurrentRunableTracker = jRequire.CurrentRunableTracker();
j$.RunableResources = jRequire.RunableResources(j$);
j$.Runner = jRequire.Runner(j$);
j$.Spec = jRequire.Spec(j$);
@@ -774,7 +775,6 @@ getJasmineRequireObj().Spec = function(j$) {
this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.setTimeout = attrs.setTimeout;
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
this.filename = attrs.filename;
this.parentSuiteId = attrs.parentSuiteId;
@@ -790,7 +790,6 @@ getJasmineRequireObj().Spec = function(j$) {
function() {
return {};
};
this.onStart = attrs.onStart || function() {};
this.autoCleanClosures =
attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
@@ -845,15 +844,18 @@ getJasmineRequireObj().Spec = function(j$) {
Spec.prototype.execute = function(
runQueue,
globalErrors,
onStart,
// TODO: may be able to merge resultCallback into onComplete
resultCallback,
onComplete,
excluded,
failSpecWithNoExp,
detectLateRejectionHandling
) {
const onStart = {
const start = {
fn: done => {
this.timer.start();
this.onStart(this, done);
onStart(done);
}
};
@@ -869,7 +871,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.result.debugLogs = null;
}
this.resultCallback(this.result, done);
resultCallback(this.result, done);
},
type: 'specCleanup'
};
@@ -908,7 +910,7 @@ getJasmineRequireObj().Spec = function(j$) {
runnerConfig.queueableFns = [];
}
runnerConfig.queueableFns.unshift(onStart);
runnerConfig.queueableFns.unshift(start);
if (detectLateRejectionHandling) {
// Conditional because the setTimeout imposes a significant performance
@@ -1674,8 +1676,6 @@ getJasmineRequireObj().Env = function(j$) {
expectationFactory,
asyncExpectationFactory,
onLateError: recordLateError,
specResultCallback,
specStarted,
runQueue
});
topSuite = suiteBuilder.topSuite;
@@ -1717,8 +1717,7 @@ getJasmineRequireObj().Env = function(j$) {
runQueue,
TreeProcessor: j$.TreeProcessor,
globalErrors,
getConfig: () => config,
reportSpecDone
getConfig: () => config
});
this.setParallelLoadingState = function(state) {
@@ -1960,28 +1959,6 @@ getJasmineRequireObj().Env = function(j$) {
.metadata;
};
function specResultCallback(spec, result, next) {
runableResources.clearForRunable(spec.id);
runner.setCurrentSpec(null);
if (result.status === 'failed') {
runner.hasFailures = true;
}
reportSpecDone(spec, result, next);
}
function specStarted(spec, suite, next) {
runner.setCurrentSpec(spec);
runableResources.initForRunable(spec.id, suite.id);
reportDispatcher.specStarted(spec.result).then(next);
}
function reportSpecDone(spec, result, next) {
spec.reportedDone = true;
reportDispatcher.specDone(result).then(next);
}
this.it = function(description, fn, timeout) {
ensureIsNotNested('it');
const filename = callerCallerFilename();
@@ -3488,6 +3465,45 @@ getJasmineRequireObj().CompleteOnFirstErrorSkipPolicy = function(j$) {
return CompleteOnFirstErrorSkipPolicy;
};
getJasmineRequireObj().CurrentRunableTracker = function() {
class CurrentRunableTracker {
#currentSpec;
#currentlyExecutingSuites;
constructor() {
this.#currentlyExecutingSuites = [];
}
currentRunable() {
return this.currentSpec() || this.currentSuite();
}
currentSpec() {
return this.#currentSpec;
}
setCurrentSpec(spec) {
this.#currentSpec = spec;
}
currentSuite() {
return this.#currentlyExecutingSuites[
this.#currentlyExecutingSuites.length - 1
];
}
pushSuite(suite) {
this.#currentlyExecutingSuites.push(suite);
}
popSuite() {
this.#currentlyExecutingSuites.pop();
}
}
return CurrentRunableTracker;
};
// Warning: don't add "use strict" to this file. Doing so potentially changes
// the behavior of user code that does things like setTimeout("var x = 1;")
// while the mock clock is installed.
@@ -9423,7 +9439,6 @@ getJasmineRequireObj().Runner = function(j$) {
#globalErrors;
#reportDispatcher;
#getConfig;
#reportSpecDone;
#executedBefore;
#currentRunableTracker;
@@ -9437,10 +9452,8 @@ getJasmineRequireObj().Runner = function(j$) {
this.#globalErrors = options.globalErrors;
this.#reportDispatcher = options.reportDispatcher;
this.#getConfig = options.getConfig;
this.#reportSpecDone = options.reportSpecDone;
this.hasFailures = false;
this.#executedBefore = false;
this.#currentRunableTracker = new CurrentRunableTracker();
this.#currentRunableTracker = new j$.CurrentRunableTracker();
}
currentSpec() {
@@ -9469,7 +9482,6 @@ getJasmineRequireObj().Runner = function(j$) {
}
this.#executedBefore = true;
this.hasFailures = false;
const focusedRunables = this.#getFocusedRunables();
const config = this.#getConfig();
@@ -9537,8 +9549,7 @@ getJasmineRequireObj().Runner = function(j$) {
),
currentRunableTracker: this.#currentRunableTracker
});
await treeRunner.execute();
this.hasFailures = this.hasFailures || treeRunner.hasFailures;
const { hasFailures } = await treeRunner.execute();
if (this.#topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
@@ -9548,10 +9559,7 @@ getJasmineRequireObj().Runner = function(j$) {
this.#currentRunableTracker.popSuite();
let overallStatus, incompleteReason, incompleteCode;
if (
this.hasFailures ||
this.#topSuite.result.failedExpectations.length > 0
) {
if (hasFailures || this.#topSuite.result.failedExpectations.length > 0) {
overallStatus = 'failed';
} else if (this.#getFocusedRunables().length > 0) {
overallStatus = 'incomplete';
@@ -9592,6 +9600,12 @@ getJasmineRequireObj().Runner = function(j$) {
return jasmineDoneInfo;
}
// TODO: de-duplicate w/TreeRunner
#reportSpecDone(spec, result, next) {
spec.reportedDone = true;
this.#reportDispatcher.specDone(result).then(next);
}
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
@@ -9628,41 +9642,6 @@ getJasmineRequireObj().Runner = function(j$) {
}
}
class CurrentRunableTracker {
#currentSpec;
#currentlyExecutingSuites;
constructor() {
this.#currentlyExecutingSuites = [];
}
currentRunable() {
return this.currentSpec() || this.currentSuite();
}
currentSpec() {
return this.#currentSpec;
}
setCurrentSpec(spec) {
this.#currentSpec = spec;
}
currentSuite() {
return this.#currentlyExecutingSuites[
this.#currentlyExecutingSuites.length - 1
];
}
pushSuite(suite) {
this.#currentlyExecutingSuites.push(suite);
}
popSuite() {
this.#currentlyExecutingSuites.pop();
}
}
return Runner;
};
@@ -10937,8 +10916,6 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
return options.asyncExpectationFactory(actual, suite, 'Spec');
};
this.onLateError_ = options.onLateError;
this.specResultCallback_ = options.specResultCallback;
this.specStarted_ = options.specStarted;
this.nextSuiteId_ = 0;
this.nextSpecId_ = 0;
@@ -11176,11 +11153,7 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
asyncExpectationFactory: this.specAsyncExpectationFactory_,
setTimeout: global.setTimeout.bind(global),
onLateError: this.onLateError_,
resultCallback: (result, next) => {
this.specResultCallback_(spec, result, next);
},
getPath: spec => this.getSpecPath_(spec, suite),
onStart: (spec, next) => this.specStarted_(spec, suite, next),
description: description,
userContext: function() {
return suite.clonedSharedUserContext();
@@ -11544,6 +11517,7 @@ getJasmineRequireObj().TreeRunner = function(j$) {
#getConfig;
#reportChildrenOfBeforeAllFailure;
#currentRunableTracker;
#hasFailures;
constructor(attrs) {
this.#executionTree = attrs.executionTree;
@@ -11558,7 +11532,7 @@ getJasmineRequireObj().TreeRunner = function(j$) {
}
async execute() {
this.hasFailures = false;
this.#hasFailures = false;
const topSuite = this.#executionTree.topSuite;
const wrappedChildren = this.#wrapNodes(
this.#executionTree.childrenOfTopSuite()
@@ -11581,6 +11555,8 @@ getJasmineRequireObj().TreeRunner = function(j$) {
: null
});
});
return { hasFailures: this.#hasFailures };
}
#wrapNodes(nodes) {
@@ -11602,6 +11578,14 @@ getJasmineRequireObj().TreeRunner = function(j$) {
spec.execute(
this.#runQueueWithSkipPolicy.bind(this),
this.#globalErrors,
next => {
this.#currentRunableTracker.setCurrentSpec(spec);
this.#runableResources.initForRunable(spec.id, spec.parentSuiteId);
this.#reportDispatcher.specStarted(spec.result).then(next);
},
(result, next) => {
this.#specComplete(spec, result, next);
},
done,
this.#executionTree.isExcluded(spec),
config.failSpecWithNoExpectations,
@@ -11661,7 +11645,7 @@ getJasmineRequireObj().TreeRunner = function(j$) {
this.#currentRunableTracker.popSuite();
if (result.status === 'failed') {
this.hasFailures = true;
this.#hasFailures = true;
}
suite.endTimer();
@@ -11679,6 +11663,22 @@ getJasmineRequireObj().TreeRunner = function(j$) {
this.#reportDispatcher.suiteDone(result).then(next);
}
#specComplete(spec, result, next) {
this.#runableResources.clearForRunable(spec.id);
this.#currentRunableTracker.setCurrentSpec(null);
if (result.status === 'failed') {
this.#hasFailures = true;
}
this.#reportSpecDone(spec, result, next);
}
#reportSpecDone(spec, result, next) {
spec.reportedDone = true;
this.#reportDispatcher.specDone(result).then(next);
}
#addBeforeAndAfterAlls(suite, wrappedChildren) {
if (this.#executionTree.isExcluded(suite)) {
return wrappedChildren;